Test with OpenShift cluster non authenticated (#6395)

* Test with OpenShift cluster non authenticated

* Add analyze commands

* Add same tests as with NoCluster

* Do not try to cleanup namespaces

* Assert non authenticated

* Change Makefile target name
This commit is contained in:
Philippe Martin
2022-12-09 12:41:38 +01:00
committed by GitHub
parent 6c99ca1024
commit 83cdda6960
18 changed files with 1687 additions and 1540 deletions

View File

@@ -0,0 +1,21 @@
#!/bin/bash
LOGFILE="pr-${GIT_PR_NUMBER}-openshift-tests-${BUILD_NUMBER}"
source .ibm/pipelines/functions.sh
ibmcloud login --apikey "${API_KEY_QE}"
ibmcloud target -r eu-de
ibmcloud oc cluster config -c "${CLUSTER_ID}"
(
set -e
make install
make test-integration-openshift-unauth
) |& tee "/tmp/${LOGFILE}"
RESULT=${PIPESTATUS[0]}
save_logs "${LOGFILE}" "OpenShift Unauthenticated Tests" ${RESULT}
exit ${RESULT}

View File

@@ -192,7 +192,11 @@ openshiftci-presubmit-unittests:
.PHONY: test-integration-cluster .PHONY: test-integration-cluster
test-integration-cluster: test-integration-cluster:
$(RUN_GINKGO) $(GINKGO_FLAGS) --junit-report="test-integration.xml" --label-filter="!nocluster && !podman" tests/integration $(RUN_GINKGO) $(GINKGO_FLAGS) --junit-report="test-integration.xml" --label-filter="!unauth && !nocluster && !podman" tests/integration
.PHONY: test-integration-openshift-unauth
test-integration-openshift-unauth:
$(RUN_GINKGO) $(GINKGO_FLAGS) --junit-report="test-integration-unauth.xml" --label-filter="unauth" tests/integration
.PHONY: test-integration-no-cluster .PHONY: test-integration-no-cluster
test-integration-no-cluster: test-integration-no-cluster:

View File

@@ -56,4 +56,5 @@ type CliRunner interface {
AssertContainsLabel(kind, namespace, componentName, appName, mode, key, value string) AssertContainsLabel(kind, namespace, componentName, appName, mode, key, value string)
AssertNoContainsLabel(kind, namespace, componentName, appName, mode, key string) AssertNoContainsLabel(kind, namespace, componentName, appName, mode, key string)
EnsurePodIsUp(namespace, podName string) EnsurePodIsUp(namespace, podName string)
AssertNonAuthenticated()
} }

View File

@@ -197,7 +197,11 @@ func CommonBeforeEach() CommonVar {
commonVar.OriginalKubeconfig = os.Getenv("KUBECONFIG") commonVar.OriginalKubeconfig = os.Getenv("KUBECONFIG")
if NeedsCluster(CurrentSpecReport().Labels()) { if NeedsCluster(CurrentSpecReport().Labels()) {
LocalKubeconfigSet(commonVar.ConfigDir) LocalKubeconfigSet(commonVar.ConfigDir)
commonVar.Project = commonVar.CliRunner.CreateAndSetRandNamespaceProject() if IsAuth(CurrentSpecReport().Labels()) {
commonVar.Project = commonVar.CliRunner.CreateAndSetRandNamespaceProject()
} else {
commonVar.CliRunner.AssertNonAuthenticated()
}
} else { } else {
// Disable the use of in-cluster configuration (seen in IBM Cloud pipeline) // Disable the use of in-cluster configuration (seen in IBM Cloud pipeline)
os.Unsetenv("KUBERNETES_SERVICE_HOST") os.Unsetenv("KUBERNETES_SERVICE_HOST")

View File

@@ -431,3 +431,7 @@ func (kubectl KubectlRunner) AssertNoContainsLabel(kind, namespace, componentNam
all := Cmd(kubectl.path, "get", kind, selector, "-n", namespace, "-o", "jsonpath={.items[0].metadata.labels}").ShouldPass().Out() all := Cmd(kubectl.path, "get", kind, selector, "-n", namespace, "-o", "jsonpath={.items[0].metadata.labels}").ShouldPass().Out()
Expect(all).ToNot(ContainSubstring(fmt.Sprintf(`"%s"`, key))) Expect(all).ToNot(ContainSubstring(fmt.Sprintf(`"%s"`, key)))
} }
func (kubectl KubectlRunner) AssertNonAuthenticated() {
// Nothing to do
}

View File

@@ -622,3 +622,7 @@ func (oc OcRunner) EnsurePodIsUp(namespace, podName string) {
return strings.Contains(output, podName) return strings.Contains(output, podName)
}) })
} }
func (oc OcRunner) AssertNonAuthenticated() {
Cmd(oc.path, "whoami").ShouldFail()
}

View File

@@ -6,6 +6,7 @@ import (
const ( const (
LabelNoCluster = "nocluster" LabelNoCluster = "nocluster"
LabelUnauth = "unauth"
LabelPodman = "podman" LabelPodman = "podman"
) )
@@ -21,6 +22,15 @@ func NeedsCluster(labels []string) bool {
return true return true
} }
func IsAuth(labels []string) bool {
for _, label := range labels {
if label == LabelUnauth {
return false
}
}
return true
}
func LabelPodmanIf(value bool, args ...interface{}) []interface{} { func LabelPodmanIf(value bool, args ...interface{}) []interface{} {
res := []interface{}{} res := []interface{}{}
if value { if value {

View File

@@ -9,45 +9,54 @@ import (
"github.com/redhat-developer/odo/tests/helper" "github.com/redhat-developer/odo/tests/helper"
) )
var _ = Describe("odo analyze command tests", Label(helper.LabelNoCluster), func() { var _ = Describe("odo analyze command tests", func() {
var commonVar helper.CommonVar for _, label := range []string{
helper.LabelNoCluster, helper.LabelUnauth,
} {
label := label
var _ = Context("label "+label, Label(label), func() {
var commonVar helper.CommonVar
// This is run before every Spec (It) // This is run before every Spec (It)
var _ = BeforeEach(func() { var _ = BeforeEach(func() {
commonVar = helper.CommonBeforeEach() commonVar = helper.CommonBeforeEach()
helper.Chdir(commonVar.Context) helper.Chdir(commonVar.Context)
}) })
// This is run after every Spec (It) // This is run after every Spec (It)
var _ = AfterEach(func() { var _ = AfterEach(func() {
helper.CommonAfterEach(commonVar) helper.CommonAfterEach(commonVar)
}) })
When("source files are in the directory", func() { When("source files are in the directory", func() {
BeforeEach(func() { BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project"), commonVar.Context) helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project"), commonVar.Context)
})
It("analyze should return correct value", func() {
res := helper.Cmd("odo", "analyze", "-o", "json").ShouldPass()
stdout, stderr := res.Out(), res.Err()
Expect(stderr).To(BeEmpty())
Expect(helper.IsJSON(stdout)).To(BeTrue())
helper.JsonPathContentIs(stdout, "0.devfile", "nodejs")
helper.JsonPathContentIs(stdout, "0.devfileRegistry", "DefaultDevfileRegistry")
})
})
It("analyze should fail in an empty directory", func() {
res := helper.Cmd("odo", "analyze", "-o", "json").ShouldFail()
stdout, stderr := res.Out(), res.Err()
Expect(stdout).To(BeEmpty())
Expect(helper.IsJSON(stderr)).To(BeTrue())
helper.JsonPathContentContain(stderr, "message", "No valid devfile found for project in")
})
It("analyze should fail without json output", func() {
stderr := helper.Cmd("odo", "analyze").ShouldFail().Err()
Expect(stderr).To(ContainSubstring("this command can be run with json output only"))
})
}) })
It("analyze should return correct value", func() { }
res := helper.Cmd("odo", "analyze", "-o", "json").ShouldPass()
stdout, stderr := res.Out(), res.Err()
Expect(stderr).To(BeEmpty())
Expect(helper.IsJSON(stdout)).To(BeTrue())
helper.JsonPathContentIs(stdout, "0.devfile", "nodejs")
helper.JsonPathContentIs(stdout, "0.devfileRegistry", "DefaultDevfileRegistry")
})
})
It("analyze should fail in an empty directory", func() {
res := helper.Cmd("odo", "analyze", "-o", "json").ShouldFail()
stdout, stderr := res.Out(), res.Err()
Expect(stdout).To(BeEmpty())
Expect(helper.IsJSON(stderr)).To(BeTrue())
helper.JsonPathContentContain(stderr, "message", "No valid devfile found for project in")
})
It("analyze should fail without json output", func() {
stderr := helper.Cmd("odo", "analyze").ShouldFail().Err()
Expect(stderr).To(ContainSubstring("this command can be run with json output only"))
})
}) })

View File

@@ -28,38 +28,43 @@ var _ = Describe("odo describe component command tests", func() {
helper.CommonAfterEach(commonVar) helper.CommonAfterEach(commonVar)
}) })
It("should fail, without cluster", Label(helper.LabelNoCluster), func() { for _, label := range []string{
By("running odo describe component -o json with namespace flag without name flag", func() { helper.LabelNoCluster, helper.LabelUnauth,
res := helper.Cmd("odo", "describe", "component", "--namespace", "default", "-o", "json").ShouldFail() } {
stdout, stderr := res.Out(), res.Err() label := label
Expect(helper.IsJSON(stderr)).To(BeTrue()) It("should fail, without cluster", Label(label), func() {
Expect(stdout).To(BeEmpty()) By("running odo describe component -o json with namespace flag without name flag", func() {
helper.JsonPathContentContain(stderr, "message", "--namespace can be used only with --name") res := helper.Cmd("odo", "describe", "component", "--namespace", "default", "-o", "json").ShouldFail()
}) stdout, stderr := res.Out(), res.Err()
Expect(helper.IsJSON(stderr)).To(BeTrue())
Expect(stdout).To(BeEmpty())
helper.JsonPathContentContain(stderr, "message", "--namespace can be used only with --name")
})
By("running odo describe component -o json without name and without devfile in the current directory", func() { By("running odo describe component -o json without name and without devfile in the current directory", func() {
res := helper.Cmd("odo", "describe", "component", "-o", "json").ShouldFail() res := helper.Cmd("odo", "describe", "component", "-o", "json").ShouldFail()
stdout, stderr := res.Out(), res.Err() stdout, stderr := res.Out(), res.Err()
Expect(helper.IsJSON(stderr)).To(BeTrue()) Expect(helper.IsJSON(stderr)).To(BeTrue())
Expect(stdout).To(BeEmpty()) Expect(stdout).To(BeEmpty())
helper.JsonPathContentContain(stderr, "message", "The current directory does not represent an odo component") helper.JsonPathContentContain(stderr, "message", "The current directory does not represent an odo component")
}) })
By("running odo describe component with namespace flag without name flag", func() { By("running odo describe component with namespace flag without name flag", func() {
res := helper.Cmd("odo", "describe", "component", "--namespace", "default").ShouldFail() res := helper.Cmd("odo", "describe", "component", "--namespace", "default").ShouldFail()
stdout, stderr := res.Out(), res.Err() stdout, stderr := res.Out(), res.Err()
Expect(stdout).To(BeEmpty()) Expect(stdout).To(BeEmpty())
Expect(stderr).To(ContainSubstring("--namespace can be used only with --name")) Expect(stderr).To(ContainSubstring("--namespace can be used only with --name"))
}) })
By("running odo describe component without name and without devfile in the current directory", func() { By("running odo describe component without name and without devfile in the current directory", func() {
res := helper.Cmd("odo", "describe", "component").ShouldFail() res := helper.Cmd("odo", "describe", "component").ShouldFail()
stdout, stderr := res.Out(), res.Err() stdout, stderr := res.Out(), res.Err()
Expect(stdout).To(BeEmpty()) Expect(stdout).To(BeEmpty())
Expect(stderr).To(ContainSubstring("The current directory does not represent an odo component")) Expect(stderr).To(ContainSubstring("The current directory does not represent an odo component"))
}) })
}) })
}
It("should fail, with cluster", func() { It("should fail, with cluster", func() {
By("running odo describe component -o json with an unknown name", func() { By("running odo describe component -o json with an unknown name", func() {

View File

@@ -14,251 +14,257 @@ import (
"github.com/redhat-developer/odo/tests/helper" "github.com/redhat-developer/odo/tests/helper"
) )
var _ = Describe("odo devfile build-images command tests", Label(helper.LabelNoCluster), func() { var _ = Describe("odo devfile build-images command tests", func() {
for _, label := range []string{
var commonVar helper.CommonVar helper.LabelNoCluster, helper.LabelUnauth,
var _ = BeforeEach(func() {
commonVar = helper.CommonBeforeEach()
helper.Chdir(commonVar.Context)
})
// This is run after every Spec (It)
var _ = AfterEach(func() {
helper.CommonAfterEach(commonVar)
})
When("using a devfile.yaml containing an Image component", func() {
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", helper.GetExamplePath("source", "devfiles", "nodejs", "devfile-outerloop.yaml")).ShouldPass()
helper.CreateLocalEnv(commonVar.Context, "aname", commonVar.Project)
})
It("should run odo build-images without push", func() {
stdout := helper.Cmd("odo", "build-images").AddEnv("PODMAN_CMD=echo").ShouldPass().Out()
Expect(stdout).To(ContainSubstring("build -t quay.io/unknown-account/myimage -f " + filepath.Join(commonVar.Context, "Dockerfile ") + commonVar.Context))
})
It("should run odo build-images --push", func() {
stdout := helper.Cmd("odo", "build-images", "--push").AddEnv("PODMAN_CMD=echo").ShouldPass().Out()
Expect(stdout).To(ContainSubstring("build -t quay.io/unknown-account/myimage -f " + filepath.Join(commonVar.Context, "Dockerfile ") + commonVar.Context))
Expect(stdout).To(ContainSubstring("push quay.io/unknown-account/myimage"))
})
})
When("using a devfile.yaml with no Image component", func() {
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "init", "--name", "aname",
"--devfile-path",
helper.GetExamplePath("source", "devfiles", "nodejs", "devfile.yaml")).ShouldPass()
helper.CreateLocalEnv(commonVar.Context, "aname", commonVar.Project)
})
It("should not be able to run odo build-images", func() {
stdout, stderr := helper.Cmd("odo", "build-images").AddEnv("PODMAN_CMD=echo").ShouldFail().OutAndErr()
// Make sure no "{podman,docker} build -t ..." command gets executed
imageBuildCmd := "build -t "
Expect(stdout).ShouldNot(ContainSubstring(imageBuildCmd))
Expect(stderr).ShouldNot(ContainSubstring(imageBuildCmd))
Expect(stderr).To(ContainSubstring("no component with type \"Image\" found in Devfile"))
})
})
When("using a devfile.yaml containing an Image component with Dockerfile args", func() {
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", helper.GetExamplePath("source", "devfiles", "nodejs", "devfile-outerloop-args.yaml")).ShouldPass()
helper.CreateLocalEnv(commonVar.Context, "aname", commonVar.Project)
})
It("should use args to build image when running odo build-images", func() {
stdout := helper.Cmd("odo", "build-images").AddEnv("PODMAN_CMD=echo").ShouldPass().Out()
Expect(stdout).To(ContainSubstring("--unknown-flag value"))
})
})
When("using a devfile.yaml containing an Image component with a build context", func() {
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "init", "--name", "aname",
"--devfile-path",
helper.GetExamplePath("source", "devfiles", "nodejs",
"devfile-outerloop-project_source-in-docker-build-context.yaml")).ShouldPass()
helper.CreateLocalEnv(commonVar.Context, "aname", commonVar.Project)
})
for _, scope := range []struct {
name string
envvars []string
}{
{
name: "Podman",
envvars: []string{"PODMAN_CMD=echo"},
},
{
name: "Docker",
envvars: []string{
"PODMAN_CMD=a-command-not-found-for-podman-should-make-odo-fallback-to-docker",
"DOCKER_CMD=echo",
},
},
} {
// this is a workaround to ensure that the for loop works with `It` blocks
scope := scope
It(fmt.Sprintf("should build image via %s if build context references PROJECT_SOURCE env var", scope.name), func() {
stdout := helper.Cmd("odo", "build-images").AddEnv(scope.envvars...).ShouldPass().Out()
lines, err := helper.ExtractLines(stdout)
Expect(err).ShouldNot(HaveOccurred())
nbLines := len(lines)
Expect(nbLines).To(BeNumerically(">", 2))
containerImage := "localhost:5000/devfile-nodejs-deploy:0.1.0" // from Devfile yaml file
dockerfilePath := filepath.Join(commonVar.Context, "Dockerfile")
buildCtx := commonVar.Context
Expect(lines[nbLines-2]).To(BeEquivalentTo(
fmt.Sprintf("build -t %s -f %s %s", containerImage, dockerfilePath, buildCtx)))
})
}
})
When("using a devfile.yaml containing an Image component with no build context", func() {
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.CopyExampleDevFile(
filepath.Join("source", "devfiles", "nodejs",
"issue-5600-devfile-with-image-component-and-no-buildContext.yaml"),
filepath.Join(commonVar.Context, "devfile.yaml"))
helper.CreateLocalEnv(commonVar.Context, "aname", commonVar.Project)
})
for _, scope := range []struct {
name string
envvars []string
}{
{
name: "Podman",
envvars: []string{"PODMAN_CMD=echo"},
},
{
name: "Docker",
envvars: []string{
"PODMAN_CMD=a-command-not-found-for-podman-should-make-odo-fallback-to-docker",
"DOCKER_CMD=echo",
},
},
} {
// this is a workaround to ensure that the for loop works with `It` blocks
scope := scope
It(fmt.Sprintf("should build image via %s by defaulting build context to devfile path", scope.name), func() {
stdout := helper.Cmd("odo", "build-images").AddEnv(scope.envvars...).ShouldPass().Out()
lines, err := helper.ExtractLines(stdout)
Expect(err).ShouldNot(HaveOccurred())
nbLines := len(lines)
Expect(nbLines).To(BeNumerically(">", 2))
containerImage := "localhost:5000/devfile-nodejs-deploy:0.1.0" // from Devfile yaml file
dockerfilePath := filepath.Join(commonVar.Context, "Dockerfile")
buildCtx := commonVar.Context
Expect(lines[nbLines-2]).To(BeEquivalentTo(
fmt.Sprintf("build -t %s -f %s %s", containerImage, dockerfilePath, buildCtx)))
})
}
})
for _, env := range [][]string{
{"PODMAN_CMD=echo"},
{
"PODMAN_CMD=a-command-not-found-for-podman-should-make-odo-fallback-to-docker",
"DOCKER_CMD=echo",
},
} { } {
env := env label := label
Describe("using a Devfile with an image component using a remote Dockerfile", func() { var _ = Context("label "+label, Label(label), func() {
BeforeEach(func() { var commonVar helper.CommonVar
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile-outerloop.yaml"), var _ = BeforeEach(func() {
path.Join(commonVar.Context, "devfile.yaml")) commonVar = helper.CommonBeforeEach()
helper.Chdir(commonVar.Context)
}) })
When("remote server returns an error", func() { // This is run after every Spec (It)
var server *httptest.Server var _ = AfterEach(func() {
var url string helper.CommonAfterEach(commonVar)
})
When("using a devfile.yaml containing an Image component", func() {
BeforeEach(func() { BeforeEach(func() {
server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
w.WriteHeader(http.StatusNotFound) helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", helper.GetExamplePath("source", "devfiles", "nodejs", "devfile-outerloop.yaml")).ShouldPass()
})) helper.CreateLocalEnv(commonVar.Context, "aname", commonVar.Project)
url = server.URL })
It("should run odo build-images without push", func() {
helper.ReplaceString(filepath.Join(commonVar.Context, "devfile.yaml"), "./Dockerfile", url) stdout := helper.Cmd("odo", "build-images").AddEnv("PODMAN_CMD=echo").ShouldPass().Out()
Expect(stdout).To(ContainSubstring("build -t quay.io/unknown-account/myimage -f " + filepath.Join(commonVar.Context, "Dockerfile ") + commonVar.Context))
}) })
AfterEach(func() { It("should run odo build-images --push", func() {
server.Close() stdout := helper.Cmd("odo", "build-images", "--push").AddEnv("PODMAN_CMD=echo").ShouldPass().Out()
}) Expect(stdout).To(ContainSubstring("build -t quay.io/unknown-account/myimage -f " + filepath.Join(commonVar.Context, "Dockerfile ") + commonVar.Context))
Expect(stdout).To(ContainSubstring("push quay.io/unknown-account/myimage"))
It("should not build images", func() {
cmdWrapper := helper.Cmd("odo", "build-images").AddEnv(env...).ShouldFail()
stderr := cmdWrapper.Err()
stdout := cmdWrapper.Out()
Expect(stderr).To(ContainSubstring("failed to retrieve " + url))
Expect(stdout).NotTo(ContainSubstring("build -t quay.io/unknown-account/myimage -f "))
})
It("should not run 'odo build-images --push'", func() {
cmdWrapper := helper.Cmd("odo", "build-images", "--push").AddEnv(env...).ShouldFail()
stderr := cmdWrapper.Err()
stdout := cmdWrapper.Out()
Expect(stderr).To(ContainSubstring("failed to retrieve " + url))
Expect(stdout).NotTo(ContainSubstring("build -t quay.io/unknown-account/myimage -f "))
Expect(stdout).NotTo(ContainSubstring("push quay.io/unknown-account/myimage"))
}) })
}) })
When("remote server returns a valid file", func() { When("using a devfile.yaml with no Image component", func() {
var buildRegexp string BeforeEach(func() {
var server *httptest.Server helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
var url string helper.Cmd("odo", "init", "--name", "aname",
"--devfile-path",
helper.GetExamplePath("source", "devfiles", "nodejs", "devfile.yaml")).ShouldPass()
helper.CreateLocalEnv(commonVar.Context, "aname", commonVar.Project)
})
It("should not be able to run odo build-images", func() {
stdout, stderr := helper.Cmd("odo", "build-images").AddEnv("PODMAN_CMD=echo").ShouldFail().OutAndErr()
// Make sure no "{podman,docker} build -t ..." command gets executed
imageBuildCmd := "build -t "
Expect(stdout).ShouldNot(ContainSubstring(imageBuildCmd))
Expect(stderr).ShouldNot(ContainSubstring(imageBuildCmd))
Expect(stderr).To(ContainSubstring("no component with type \"Image\" found in Devfile"))
})
})
When("using a devfile.yaml containing an Image component with Dockerfile args", func() {
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", helper.GetExamplePath("source", "devfiles", "nodejs", "devfile-outerloop-args.yaml")).ShouldPass()
helper.CreateLocalEnv(commonVar.Context, "aname", commonVar.Project)
})
It("should use args to build image when running odo build-images", func() {
stdout := helper.Cmd("odo", "build-images").AddEnv("PODMAN_CMD=echo").ShouldPass().Out()
Expect(stdout).To(ContainSubstring("--unknown-flag value"))
})
})
When("using a devfile.yaml containing an Image component with a build context", func() {
BeforeEach(func() { BeforeEach(func() {
buildRegexp = regexp.QuoteMeta("build -t quay.io/unknown-account/myimage -f ") + helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
".*\\.dockerfile " + regexp.QuoteMeta(commonVar.Context) helper.Cmd("odo", "init", "--name", "aname",
server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { "--devfile-path",
fmt.Fprintf(w, `# Dockerfile helper.GetExamplePath("source", "devfiles", "nodejs",
"devfile-outerloop-project_source-in-docker-build-context.yaml")).ShouldPass()
helper.CreateLocalEnv(commonVar.Context, "aname", commonVar.Project)
})
for _, scope := range []struct {
name string
envvars []string
}{
{
name: "Podman",
envvars: []string{"PODMAN_CMD=echo"},
},
{
name: "Docker",
envvars: []string{
"PODMAN_CMD=a-command-not-found-for-podman-should-make-odo-fallback-to-docker",
"DOCKER_CMD=echo",
},
},
} {
// this is a workaround to ensure that the for loop works with `It` blocks
scope := scope
It(fmt.Sprintf("should build image via %s if build context references PROJECT_SOURCE env var", scope.name), func() {
stdout := helper.Cmd("odo", "build-images").AddEnv(scope.envvars...).ShouldPass().Out()
lines, err := helper.ExtractLines(stdout)
Expect(err).ShouldNot(HaveOccurred())
nbLines := len(lines)
Expect(nbLines).To(BeNumerically(">", 2))
containerImage := "localhost:5000/devfile-nodejs-deploy:0.1.0" // from Devfile yaml file
dockerfilePath := filepath.Join(commonVar.Context, "Dockerfile")
buildCtx := commonVar.Context
Expect(lines[nbLines-2]).To(BeEquivalentTo(
fmt.Sprintf("build -t %s -f %s %s", containerImage, dockerfilePath, buildCtx)))
})
}
})
When("using a devfile.yaml containing an Image component with no build context", func() {
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.CopyExampleDevFile(
filepath.Join("source", "devfiles", "nodejs",
"issue-5600-devfile-with-image-component-and-no-buildContext.yaml"),
filepath.Join(commonVar.Context, "devfile.yaml"))
helper.CreateLocalEnv(commonVar.Context, "aname", commonVar.Project)
})
for _, scope := range []struct {
name string
envvars []string
}{
{
name: "Podman",
envvars: []string{"PODMAN_CMD=echo"},
},
{
name: "Docker",
envvars: []string{
"PODMAN_CMD=a-command-not-found-for-podman-should-make-odo-fallback-to-docker",
"DOCKER_CMD=echo",
},
},
} {
// this is a workaround to ensure that the for loop works with `It` blocks
scope := scope
It(fmt.Sprintf("should build image via %s by defaulting build context to devfile path", scope.name), func() {
stdout := helper.Cmd("odo", "build-images").AddEnv(scope.envvars...).ShouldPass().Out()
lines, err := helper.ExtractLines(stdout)
Expect(err).ShouldNot(HaveOccurred())
nbLines := len(lines)
Expect(nbLines).To(BeNumerically(">", 2))
containerImage := "localhost:5000/devfile-nodejs-deploy:0.1.0" // from Devfile yaml file
dockerfilePath := filepath.Join(commonVar.Context, "Dockerfile")
buildCtx := commonVar.Context
Expect(lines[nbLines-2]).To(BeEquivalentTo(
fmt.Sprintf("build -t %s -f %s %s", containerImage, dockerfilePath, buildCtx)))
})
}
})
for _, env := range [][]string{
{"PODMAN_CMD=echo"},
{
"PODMAN_CMD=a-command-not-found-for-podman-should-make-odo-fallback-to-docker",
"DOCKER_CMD=echo",
},
} {
env := env
Describe("using a Devfile with an image component using a remote Dockerfile", func() {
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile-outerloop.yaml"),
path.Join(commonVar.Context, "devfile.yaml"))
})
When("remote server returns an error", func() {
var server *httptest.Server
var url string
BeforeEach(func() {
server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
}))
url = server.URL
helper.ReplaceString(filepath.Join(commonVar.Context, "devfile.yaml"), "./Dockerfile", url)
})
AfterEach(func() {
server.Close()
})
It("should not build images", func() {
cmdWrapper := helper.Cmd("odo", "build-images").AddEnv(env...).ShouldFail()
stderr := cmdWrapper.Err()
stdout := cmdWrapper.Out()
Expect(stderr).To(ContainSubstring("failed to retrieve " + url))
Expect(stdout).NotTo(ContainSubstring("build -t quay.io/unknown-account/myimage -f "))
})
It("should not run 'odo build-images --push'", func() {
cmdWrapper := helper.Cmd("odo", "build-images", "--push").AddEnv(env...).ShouldFail()
stderr := cmdWrapper.Err()
stdout := cmdWrapper.Out()
Expect(stderr).To(ContainSubstring("failed to retrieve " + url))
Expect(stdout).NotTo(ContainSubstring("build -t quay.io/unknown-account/myimage -f "))
Expect(stdout).NotTo(ContainSubstring("push quay.io/unknown-account/myimage"))
})
})
When("remote server returns a valid file", func() {
var buildRegexp string
var server *httptest.Server
var url string
BeforeEach(func() {
buildRegexp = regexp.QuoteMeta("build -t quay.io/unknown-account/myimage -f ") +
".*\\.dockerfile " + regexp.QuoteMeta(commonVar.Context)
server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, `# Dockerfile
FROM node:8.11.1-alpine FROM node:8.11.1-alpine
COPY . /app COPY . /app
WORKDIR /app WORKDIR /app
RUN npm install RUN npm install
CMD ["npm", "start"] CMD ["npm", "start"]
`) `)
})) }))
url = server.URL url = server.URL
helper.ReplaceString(filepath.Join(commonVar.Context, "devfile.yaml"), "./Dockerfile", url) helper.ReplaceString(filepath.Join(commonVar.Context, "devfile.yaml"), "./Dockerfile", url)
}) })
AfterEach(func() { AfterEach(func() {
server.Close() server.Close()
}) })
It("should build images", func() { It("should build images", func() {
stdout := helper.Cmd("odo", "build-images").AddEnv(env...).ShouldPass().Out() stdout := helper.Cmd("odo", "build-images").AddEnv(env...).ShouldPass().Out()
lines, _ := helper.ExtractLines(stdout) lines, _ := helper.ExtractLines(stdout)
_, ok := helper.FindFirstElementIndexMatchingRegExp(lines, buildRegexp) _, ok := helper.FindFirstElementIndexMatchingRegExp(lines, buildRegexp)
Expect(ok).To(BeTrue(), "build regexp not found in output: "+buildRegexp) Expect(ok).To(BeTrue(), "build regexp not found in output: "+buildRegexp)
}) })
It("should run 'odo build-images --push'", func() { It("should run 'odo build-images --push'", func() {
stdout := helper.Cmd("odo", "build-images", "--push").AddEnv(env...).ShouldPass().Out() stdout := helper.Cmd("odo", "build-images", "--push").AddEnv(env...).ShouldPass().Out()
lines, _ := helper.ExtractLines(stdout) lines, _ := helper.ExtractLines(stdout)
_, ok := helper.FindFirstElementIndexMatchingRegExp(lines, buildRegexp) _, ok := helper.FindFirstElementIndexMatchingRegExp(lines, buildRegexp)
Expect(ok).To(BeTrue(), "build regexp not found in output: "+buildRegexp) Expect(ok).To(BeTrue(), "build regexp not found in output: "+buildRegexp)
Expect(stdout).To(ContainSubstring("push quay.io/unknown-account/myimage")) Expect(stdout).To(ContainSubstring("push quay.io/unknown-account/myimage"))
})
})
}) })
}) }
}) })
} }
}) })

View File

@@ -22,500 +22,507 @@ import (
"github.com/redhat-developer/odo/tests/helper" "github.com/redhat-developer/odo/tests/helper"
) )
var _ = Describe("odo devfile init command tests", Label(helper.LabelNoCluster), func() { var _ = Describe("odo devfile init command tests", func() {
for _, label := range []string{
helper.LabelNoCluster, helper.LabelUnauth,
} {
label := label
var _ = Context("label "+label, Label(label), func() {
var commonVar helper.CommonVar var commonVar helper.CommonVar
var _ = BeforeEach(func() { var _ = BeforeEach(func() {
commonVar = helper.CommonBeforeEach() commonVar = helper.CommonBeforeEach()
helper.Chdir(commonVar.Context) helper.Chdir(commonVar.Context)
Expect(helper.VerifyFileExists(".odo/env/env.yaml")).To(BeFalse()) Expect(helper.VerifyFileExists(".odo/env/env.yaml")).To(BeFalse())
})
var _ = AfterEach(func() {
helper.CommonAfterEach(commonVar)
})
It("should fail", func() {
By("running odo init with incomplete flags", func() {
helper.Cmd("odo", "init", "--name", "aname").ShouldFail()
})
By("using an invalid component name", func() {
helper.Cmd("odo", "init", "--devfile", "go", "--name", "123").ShouldFail()
})
By("running odo init with json and no other flags", func() {
res := helper.Cmd("odo", "init", "-o", "json").ShouldFail()
stdout, stderr := res.Out(), res.Err()
Expect(stdout).To(BeEmpty())
Expect(helper.IsJSON(stderr)).To(BeTrue())
helper.JsonPathContentIs(stderr, "message", "parameters are expected to select a devfile")
})
By("running odo init with incomplete flags and JSON output", func() {
res := helper.Cmd("odo", "init", "--name", "aname", "-o", "json").ShouldFail()
stdout, stderr := res.Out(), res.Err()
Expect(stdout).To(BeEmpty())
Expect(helper.IsJSON(stderr)).To(BeTrue())
helper.JsonPathContentContain(stderr, "message", "either --devfile or --devfile-path parameter should be specified")
})
By("keeping an empty directory when running odo init with wrong starter name", func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile", "go", "--starter", "wrongname").ShouldFail()
files := helper.ListFilesInDir(commonVar.Context)
Expect(len(files)).To(Equal(0))
})
By("using an invalid devfile name", func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile", "invalid").ShouldFail()
})
By("running odo init in a directory containing a devfile.yaml", func() {
helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile-registry.yaml"), filepath.Join(commonVar.Context, "devfile.yaml"))
defer os.Remove(filepath.Join(commonVar.Context, "devfile.yaml"))
err := helper.Cmd("odo", "init").ShouldFail().Err()
Expect(err).To(ContainSubstring("a devfile already exists in the current directory"))
})
By("running odo init in a directory containing a .devfile.yaml", func() {
helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile-registry.yaml"), filepath.Join(commonVar.Context, ".devfile.yaml"))
defer helper.DeleteFile(filepath.Join(commonVar.Context, ".devfile.yaml"))
err := helper.Cmd("odo", "init").ShouldFail().Err()
Expect(err).To(ContainSubstring("a devfile already exists in the current directory"))
})
By("running odo init with wrong local file path given to --devfile-path", func() {
err := helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", "/some/path/devfile.yaml").ShouldFail().Err()
Expect(err).To(ContainSubstring("unable to download devfile"))
})
By("running odo init with wrong URL path given to --devfile-path", func() {
err := helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", "https://github.com/path/to/devfile.yaml").ShouldFail().Err()
Expect(err).To(ContainSubstring("unable to download devfile"))
})
By("running odo init multiple times", func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile", "nodejs").ShouldPass()
defer helper.DeleteFile(filepath.Join(commonVar.Context, "devfile.yaml"))
output := helper.Cmd("odo", "init", "--name", "aname", "--devfile", "nodejs").ShouldFail().Err()
Expect(output).To(ContainSubstring("a devfile already exists in the current directory"))
})
By("running odo init with --devfile-path and --devfile-registry", func() {
errOut := helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", "https://github.com/path/to/devfile.yaml", "--devfile-registry", "DefaultDevfileRegistry").ShouldFail().Err()
Expect(errOut).To(ContainSubstring("--devfile-registry parameter cannot be used with --devfile-path"))
})
By("running odo init with invalid --devfile-registry value", func() {
fakeRegistry := "fake"
errOut := helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", "https://github.com/path/to/devfile.yaml", "--devfile-registry", fakeRegistry).ShouldFail().Err()
Expect(errOut).To(ContainSubstring(fmt.Sprintf("%q not found", fakeRegistry)))
})
})
Context("running odo init with valid flags", func() {
When("using --devfile flag", func() {
compName := "aname"
var output string
BeforeEach(func() {
output = helper.Cmd("odo", "init", "--name", compName, "--devfile", "go").ShouldPass().Out()
}) })
It("should download a devfile.yaml file and correctly set the component name in it", func() { var _ = AfterEach(func() {
By("not showing the interactive mode notice message", func() { helper.CommonAfterEach(commonVar)
Expect(output).ShouldNot(ContainSubstring(messages.InteractiveModeEnabled)) })
It("should fail", func() {
By("running odo init with incomplete flags", func() {
helper.Cmd("odo", "init", "--name", "aname").ShouldFail()
})
By("using an invalid component name", func() {
helper.Cmd("odo", "init", "--devfile", "go", "--name", "123").ShouldFail()
})
By("running odo init with json and no other flags", func() {
res := helper.Cmd("odo", "init", "-o", "json").ShouldFail()
stdout, stderr := res.Out(), res.Err()
Expect(stdout).To(BeEmpty())
Expect(helper.IsJSON(stderr)).To(BeTrue())
helper.JsonPathContentIs(stderr, "message", "parameters are expected to select a devfile")
})
By("running odo init with incomplete flags and JSON output", func() {
res := helper.Cmd("odo", "init", "--name", "aname", "-o", "json").ShouldFail()
stdout, stderr := res.Out(), res.Err()
Expect(stdout).To(BeEmpty())
Expect(helper.IsJSON(stderr)).To(BeTrue())
helper.JsonPathContentContain(stderr, "message", "either --devfile or --devfile-path parameter should be specified")
})
By("keeping an empty directory when running odo init with wrong starter name", func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile", "go", "--starter", "wrongname").ShouldFail()
files := helper.ListFilesInDir(commonVar.Context)
Expect(len(files)).To(Equal(0))
})
By("using an invalid devfile name", func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile", "invalid").ShouldFail()
})
By("running odo init in a directory containing a devfile.yaml", func() {
helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile-registry.yaml"), filepath.Join(commonVar.Context, "devfile.yaml"))
defer os.Remove(filepath.Join(commonVar.Context, "devfile.yaml"))
err := helper.Cmd("odo", "init").ShouldFail().Err()
Expect(err).To(ContainSubstring("a devfile already exists in the current directory"))
})
By("running odo init in a directory containing a .devfile.yaml", func() {
helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile-registry.yaml"), filepath.Join(commonVar.Context, ".devfile.yaml"))
defer helper.DeleteFile(filepath.Join(commonVar.Context, ".devfile.yaml"))
err := helper.Cmd("odo", "init").ShouldFail().Err()
Expect(err).To(ContainSubstring("a devfile already exists in the current directory"))
})
By("running odo init with wrong local file path given to --devfile-path", func() {
err := helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", "/some/path/devfile.yaml").ShouldFail().Err()
Expect(err).To(ContainSubstring("unable to download devfile"))
})
By("running odo init with wrong URL path given to --devfile-path", func() {
err := helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", "https://github.com/path/to/devfile.yaml").ShouldFail().Err()
Expect(err).To(ContainSubstring("unable to download devfile"))
})
By("running odo init multiple times", func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile", "nodejs").ShouldPass()
defer helper.DeleteFile(filepath.Join(commonVar.Context, "devfile.yaml"))
output := helper.Cmd("odo", "init", "--name", "aname", "--devfile", "nodejs").ShouldFail().Err()
Expect(output).To(ContainSubstring("a devfile already exists in the current directory"))
})
By("running odo init with --devfile-path and --devfile-registry", func() {
errOut := helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", "https://github.com/path/to/devfile.yaml", "--devfile-registry", "DefaultDevfileRegistry").ShouldFail().Err()
Expect(errOut).To(ContainSubstring("--devfile-registry parameter cannot be used with --devfile-path"))
})
By("running odo init with invalid --devfile-registry value", func() {
fakeRegistry := "fake"
errOut := helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", "https://github.com/path/to/devfile.yaml", "--devfile-registry", fakeRegistry).ShouldFail().Err()
Expect(errOut).To(ContainSubstring(fmt.Sprintf("%q not found", fakeRegistry)))
}) })
files := helper.ListFilesInDir(commonVar.Context)
Expect(files).To(SatisfyAll(
HaveLen(2),
ContainElements("devfile.yaml", util.DotOdoDirectory)))
metadata := helper.GetMetadataFromDevfile(filepath.Join(commonVar.Context, "devfile.yaml"))
Expect(metadata.Name).To(BeEquivalentTo(compName))
})
})
When("using --devfile flag and JSON output", func() {
compName := "aname"
var res *helper.CmdWrapper
BeforeEach(func() {
res = helper.Cmd("odo", "init", "--name", compName, "--devfile", "go", "-o", "json").ShouldPass()
}) })
It("should return correct values in output", func() { Context("running odo init with valid flags", func() {
stdout, stderr := res.Out(), res.Err() When("using --devfile flag", func() {
Expect(stderr).To(BeEmpty()) compName := "aname"
Expect(helper.IsJSON(stdout)).To(BeTrue()) var output string
helper.JsonPathContentIs(stdout, "devfilePath", filepath.Join(commonVar.Context, "devfile.yaml")) BeforeEach(func() {
helper.JsonPathContentIs(stdout, "devfileData.devfile.metadata.name", compName) output = helper.Cmd("odo", "init", "--name", compName, "--devfile", "go").ShouldPass().Out()
helper.JsonPathContentIs(stdout, "devfileData.supportedOdoFeatures.dev", "true")
helper.JsonPathContentIs(stdout, "devfileData.supportedOdoFeatures.debug", "false")
helper.JsonPathContentIs(stdout, "devfileData.supportedOdoFeatures.deploy", "false")
helper.JsonPathContentIs(stdout, "managedBy", "odo")
})
})
When("using --devfile-path flag with a local devfile", func() {
var newContext string
BeforeEach(func() {
newContext = helper.CreateNewContext()
newDevfilePath := filepath.Join(newContext, "devfile.yaml")
helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile-registry.yaml"), newDevfilePath)
helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", newDevfilePath).ShouldPass()
})
AfterEach(func() {
helper.DeleteDir(newContext)
})
It("should copy the devfile.yaml file", func() {
files := helper.ListFilesInDir(commonVar.Context)
Expect(files).To(SatisfyAll(
HaveLen(2),
ContainElements(util.DotOdoDirectory, "devfile.yaml")))
})
})
When("using --devfile-path flag with a URL", func() {
BeforeEach(func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", "https://raw.githubusercontent.com/odo-devfiles/registry/master/devfiles/nodejs/devfile.yaml").ShouldPass()
})
It("should copy the devfile.yaml file", func() {
files := helper.ListFilesInDir(commonVar.Context)
Expect(files).To(SatisfyAll(
HaveLen(2),
ContainElements("devfile.yaml", util.DotOdoDirectory)))
})
})
When("using --devfile-registry flag", func() {
It("should successfully run odo init if specified registry is valid", func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile", "go", "--devfile-registry", "DefaultDevfileRegistry").ShouldPass()
})
})
})
When("a dangling env file exists in the working directory", func() {
BeforeEach(func() {
helper.CreateLocalEnv(commonVar.Context, "aname", commonVar.Project)
})
It("should successfully create a devfile component and remove the dangling env file", func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile", "go").ShouldPass()
})
})
When("a devfile is provided which has a starter that has its own devfile", func() {
BeforeEach(func() {
helper.Cmd("odo", "init", "--name", "aname", "--starter", "nodejs-starter", "--devfile-path", helper.GetExamplePath("source", "devfiles", "nodejs", "devfile-with-starter-with-devfile.yaml")).ShouldPass()
})
It("should pass and keep the devfile in starter", func() {
devfileContent, err := helper.ReadFile(filepath.Join(commonVar.Context, "devfile.yaml"))
Expect(err).To(Not(HaveOccurred()))
helper.MatchAllInOutput(devfileContent, []string{"2.2.0", "kubernetes-deploy", "deployk8s", "image-build"})
})
})
When("running odo init with a devfile that has a subDir starter project", func() {
BeforeEach(func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", helper.GetExamplePath("source", "devfiles", "springboot", "devfile-with-subDir.yaml"), "--starter", "springbootproject").ShouldPass()
})
It("should successfully extract the project in the specified subDir path", func() {
var found, notToBeFound int
pathsToValidate := map[string]bool{
filepath.Join(commonVar.Context, "java", "com"): true,
filepath.Join(commonVar.Context, "java", "com", "example"): true,
filepath.Join(commonVar.Context, "java", "com", "example", "demo"): true,
filepath.Join(commonVar.Context, "java", "com", "example", "demo", "DemoApplication.java"): true,
filepath.Join(commonVar.Context, "resources", "application.properties"): true,
}
pathsNotToBePresent := map[string]bool{
filepath.Join(commonVar.Context, "src"): true,
filepath.Join(commonVar.Context, "main"): true,
}
err := filepath.Walk(commonVar.Context, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if ok := pathsToValidate[path]; ok {
found++
}
if ok := pathsNotToBePresent[path]; ok {
notToBeFound++
}
return nil
})
Expect(err).To(BeNil())
Expect(found).To(Equal(len(pathsToValidate)))
Expect(notToBeFound).To(Equal(0))
})
})
It("should successfully run odo init for devfile with starter project from the specified branch", func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", helper.GetExamplePath("source", "devfiles", "nodejs", "devfile-with-branch.yaml"), "--starter", "nodejs-starter").ShouldPass()
expectedFiles := []string{"package.json", "package-lock.json", "README.md", "devfile.yaml", "test"}
Expect(helper.ListFilesInDir(commonVar.Context)).To(ContainElements(expectedFiles))
})
It("should successfully run odo init for devfile with starter project from the specified tag", func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", helper.GetExamplePath("source", "devfiles", "nodejs", "devfile-with-tag.yaml"), "--starter", "nodejs-starter").ShouldPass()
expectedFiles := []string{"package.json", "package-lock.json", "README.md", "devfile.yaml", "app"}
Expect(helper.ListFilesInDir(commonVar.Context)).To(ContainElements(expectedFiles))
})
It("should successfully run odo init for devfile with starter project on git with main default branch", func() {
helper.Cmd("odo", "init",
"--name", "vertx",
"--devfile-path", helper.GetExamplePath("source", "devfiles", "java", "devfile-with-git-main-branch.yaml"),
"--starter", "vertx-http-example-redhat",
).ShouldPass()
})
When("running odo init from a directory with sources", func() {
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
})
It("should work without --starter flag", func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile", "nodejs").ShouldPass()
})
It("should not accept --starter flag", func() {
err := helper.Cmd("odo", "init", "--name", "aname", "--devfile", "nodejs", "--starter", "nodejs-starter").ShouldFail().Err()
Expect(err).To(ContainSubstring("--starter parameter cannot be used when the directory is not empty"))
})
})
Context("checking odo init final output message", func() {
var newContext, devfilePath string
BeforeEach(func() {
newContext = helper.CreateNewContext()
devfilePath = filepath.Join(newContext, "devfile.yaml")
})
AfterEach(func() {
helper.DeleteDir(newContext)
})
When("the devfile used by `odo init` does not contain a deploy command", func() {
var out string
BeforeEach(func() {
helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile.yaml"), devfilePath)
out = helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", devfilePath).ShouldPass().Out()
})
It("should only show information about `odo dev`, and not `odo deploy`", func() {
Expect(out).To(ContainSubstring("odo dev"))
Expect(out).ToNot(ContainSubstring("odo deploy"))
})
It("should not show the interactive mode notice message", func() {
Expect(out).ShouldNot(ContainSubstring(messages.InteractiveModeEnabled))
})
})
When("the devfile used by `odo init` contains a deploy command", func() {
var out string
BeforeEach(func() {
helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile-deploy.yaml"), devfilePath)
out = helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", devfilePath).ShouldPass().Out()
})
It("should show information about both `odo dev`, and `odo deploy`", func() {
Expect(out).To(ContainSubstring("odo dev"))
Expect(out).To(ContainSubstring("odo deploy"))
})
It("should not show the interactive mode notice message", func() {
Expect(out).ShouldNot(ContainSubstring(messages.InteractiveModeEnabled))
})
})
})
When("devfile contains parent URI", func() {
var originalKeyList []string
var srcDevfile string
BeforeEach(func() {
var err error
srcDevfile = helper.GetExamplePath("source", "devfiles", "nodejs", "devfile-with-parent.yaml")
originalDevfileContent, err := ioutil.ReadFile(srcDevfile)
Expect(err).To(BeNil())
var content map[string]interface{}
Expect(yaml.Unmarshal(originalDevfileContent, &content)).To(BeNil())
for k := range content {
originalKeyList = append(originalKeyList, k)
}
})
It("should not replace the original devfile", func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", srcDevfile).ShouldPass()
devfileContent, err := ioutil.ReadFile(filepath.Join(commonVar.Context, "devfile.yaml"))
Expect(err).To(BeNil())
var content map[string]interface{}
Expect(yaml.Unmarshal(devfileContent, &content)).To(BeNil())
for k := range content {
Expect(k).To(BeElementOf(originalKeyList))
}
})
})
When("source directory is empty", func() {
BeforeEach(func() {
Expect(helper.ListFilesInDir(commonVar.Context)).To(HaveLen(0))
})
It("name in devfile is personalized in non-interactive mode", func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile-path",
filepath.Join(helper.GetExamplePath(), "source", "devfiles", "nodejs",
"devfile-with-starter-with-devfile.yaml")).ShouldPass()
metadata := helper.GetMetadataFromDevfile(filepath.Join(commonVar.Context, "devfile.yaml"))
Expect(metadata.Name).To(BeEquivalentTo("aname"))
Expect(metadata.Language).To(BeEquivalentTo("nodejs"))
})
})
Describe("telemetry", func() {
for _, tt := range []struct {
name string
env map[string]string
}{
{
name: "ODO_DISABLE_TELEMETRY=true and ODO_TRACKING_CONSENT=yes",
env: map[string]string{
//lint:ignore SA1019 We deprecated this env var, but until it is removed, we still want to test it
segment.DisableTelemetryEnv: "true",
segment.TrackingConsentEnv: "yes",
},
},
{
name: "ODO_DISABLE_TELEMETRY=false and ODO_TRACKING_CONSENT=no",
env: map[string]string{
//lint:ignore SA1019 We deprecated this env var, but until it is removed, we still want to test it
segment.DisableTelemetryEnv: "false",
segment.TrackingConsentEnv: "no",
},
},
} {
tt := tt
It("should error out if "+tt.name, func() {
cmd := helper.Cmd("odo", "init", "--name", "aname", "--devfile", "go")
for k, v := range tt.env {
cmd = cmd.AddEnv(fmt.Sprintf("%s=%s", k, v))
}
stderr := cmd.ShouldFail().Err()
//lint:ignore SA1019 We deprecated this env var, but until it is removed, we still want to test it
Expect(stderr).To(ContainSubstring("%s and %s values are in conflict.", segment.DisableTelemetryEnv, segment.TrackingConsentEnv))
})
}
type telemetryTest struct {
title string
env map[string]string
setupFunc func(cfg preference.Client)
callerChecker func(stdout, stderr string, data segment.TelemetryData)
}
allowedTelemetryCallers := []string{segmentContext.VSCode, segmentContext.IntelliJ, segmentContext.JBoss}
telemetryTests := []telemetryTest{
{
title: "no caller env var",
callerChecker: func(_, _ string, td segment.TelemetryData) {
cmdProperties := td.Properties.CmdProperties
Expect(cmdProperties).Should(HaveKey(segmentContext.Caller))
Expect(cmdProperties[segmentContext.Caller]).To(BeEmpty())
},
},
{
title: "empty caller env var",
env: map[string]string{
helper.TelemetryCaller: "",
},
callerChecker: func(_, _ string, td segment.TelemetryData) {
cmdProperties := td.Properties.CmdProperties
Expect(cmdProperties).Should(HaveKey(segmentContext.Caller))
Expect(cmdProperties[segmentContext.Caller]).To(BeEmpty())
},
},
{
title: "invalid caller env var",
env: map[string]string{
helper.TelemetryCaller: "an-invalid-caller",
},
callerChecker: func(stdout, stderr string, td segment.TelemetryData) {
By("not disclosing list of allowed values", func() {
helper.DontMatchAllInOutput(stdout, allowedTelemetryCallers)
helper.DontMatchAllInOutput(stderr, allowedTelemetryCallers)
}) })
By("setting the value as caller property in telemetry even if it is invalid", func() { It("should download a devfile.yaml file and correctly set the component name in it", func() {
Expect(td.Properties.CmdProperties[segmentContext.Caller]).To(Equal("an-invalid-caller")) By("not showing the interactive mode notice message", func() {
Expect(output).ShouldNot(ContainSubstring(messages.InteractiveModeEnabled))
})
files := helper.ListFilesInDir(commonVar.Context)
Expect(files).To(SatisfyAll(
HaveLen(2),
ContainElements("devfile.yaml", util.DotOdoDirectory)))
metadata := helper.GetMetadataFromDevfile(filepath.Join(commonVar.Context, "devfile.yaml"))
Expect(metadata.Name).To(BeEquivalentTo(compName))
}) })
}, })
}, When("using --devfile flag and JSON output", func() {
{ compName := "aname"
title: "ODO_TRACKING_CONSENT=yes env var should take precedence over ConsentTelemetry preference", var res *helper.CmdWrapper
env: map[string]string{segment.TrackingConsentEnv: "yes"}, BeforeEach(func() {
callerChecker: func(_, _ string, td segment.TelemetryData) { res = helper.Cmd("odo", "init", "--name", compName, "--devfile", "go", "-o", "json").ShouldPass()
cmdProperties := td.Properties.CmdProperties })
Expect(cmdProperties).Should(HaveKey(segmentContext.Caller))
Expect(cmdProperties[segmentContext.Caller]).To(BeEmpty()) It("should return correct values in output", func() {
}, stdout, stderr := res.Out(), res.Err()
setupFunc: func(cfg preference.Client) { Expect(stderr).To(BeEmpty())
err := cfg.SetConfiguration(preference.ConsentTelemetrySetting, "false") Expect(helper.IsJSON(stdout)).To(BeTrue())
Expect(err).ShouldNot(HaveOccurred()) helper.JsonPathContentIs(stdout, "devfilePath", filepath.Join(commonVar.Context, "devfile.yaml"))
}, helper.JsonPathContentIs(stdout, "devfileData.devfile.metadata.name", compName)
}, helper.JsonPathContentIs(stdout, "devfileData.supportedOdoFeatures.dev", "true")
} helper.JsonPathContentIs(stdout, "devfileData.supportedOdoFeatures.debug", "false")
for _, c := range allowedTelemetryCallers { helper.JsonPathContentIs(stdout, "devfileData.supportedOdoFeatures.deploy", "false")
c := c helper.JsonPathContentIs(stdout, "managedBy", "odo")
telemetryTests = append(telemetryTests, telemetryTest{ })
title: fmt.Sprintf("valid caller env var: %s", c), })
env: map[string]string{ When("using --devfile-path flag with a local devfile", func() {
helper.TelemetryCaller: c, var newContext string
}, BeforeEach(func() {
callerChecker: func(_, _ string, td segment.TelemetryData) { newContext = helper.CreateNewContext()
Expect(td.Properties.CmdProperties[segmentContext.Caller]).To(Equal(c)) newDevfilePath := filepath.Join(newContext, "devfile.yaml")
}, helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile-registry.yaml"), newDevfilePath)
helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", newDevfilePath).ShouldPass()
})
AfterEach(func() {
helper.DeleteDir(newContext)
})
It("should copy the devfile.yaml file", func() {
files := helper.ListFilesInDir(commonVar.Context)
Expect(files).To(SatisfyAll(
HaveLen(2),
ContainElements(util.DotOdoDirectory, "devfile.yaml")))
})
})
When("using --devfile-path flag with a URL", func() {
BeforeEach(func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", "https://raw.githubusercontent.com/odo-devfiles/registry/master/devfiles/nodejs/devfile.yaml").ShouldPass()
})
It("should copy the devfile.yaml file", func() {
files := helper.ListFilesInDir(commonVar.Context)
Expect(files).To(SatisfyAll(
HaveLen(2),
ContainElements("devfile.yaml", util.DotOdoDirectory)))
})
})
When("using --devfile-registry flag", func() {
It("should successfully run odo init if specified registry is valid", func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile", "go", "--devfile-registry", "DefaultDevfileRegistry").ShouldPass()
})
})
}) })
} When("a dangling env file exists in the working directory", func() {
for _, tt := range telemetryTests {
tt := tt
When("recording telemetry data with "+tt.title, func() {
var stdout string
var stderr string
BeforeEach(func() { BeforeEach(func() {
helper.EnableTelemetryDebug() helper.CreateLocalEnv(commonVar.Context, "aname", commonVar.Project)
})
It("should successfully create a devfile component and remove the dangling env file", func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile", "go").ShouldPass()
})
})
ctx := context.Background() When("a devfile is provided which has a starter that has its own devfile", func() {
envConfig, err := config.GetConfiguration() BeforeEach(func() {
helper.Cmd("odo", "init", "--name", "aname", "--starter", "nodejs-starter", "--devfile-path", helper.GetExamplePath("source", "devfiles", "nodejs", "devfile-with-starter-with-devfile.yaml")).ShouldPass()
})
It("should pass and keep the devfile in starter", func() {
devfileContent, err := helper.ReadFile(filepath.Join(commonVar.Context, "devfile.yaml"))
Expect(err).To(Not(HaveOccurred()))
helper.MatchAllInOutput(devfileContent, []string{"2.2.0", "kubernetes-deploy", "deployk8s", "image-build"})
})
})
When("running odo init with a devfile that has a subDir starter project", func() {
BeforeEach(func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", helper.GetExamplePath("source", "devfiles", "springboot", "devfile-with-subDir.yaml"), "--starter", "springbootproject").ShouldPass()
})
It("should successfully extract the project in the specified subDir path", func() {
var found, notToBeFound int
pathsToValidate := map[string]bool{
filepath.Join(commonVar.Context, "java", "com"): true,
filepath.Join(commonVar.Context, "java", "com", "example"): true,
filepath.Join(commonVar.Context, "java", "com", "example", "demo"): true,
filepath.Join(commonVar.Context, "java", "com", "example", "demo", "DemoApplication.java"): true,
filepath.Join(commonVar.Context, "resources", "application.properties"): true,
}
pathsNotToBePresent := map[string]bool{
filepath.Join(commonVar.Context, "src"): true,
filepath.Join(commonVar.Context, "main"): true,
}
err := filepath.Walk(commonVar.Context, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if ok := pathsToValidate[path]; ok {
found++
}
if ok := pathsNotToBePresent[path]; ok {
notToBeFound++
}
return nil
})
Expect(err).To(BeNil()) Expect(err).To(BeNil())
ctx = envcontext.WithEnvConfig(ctx, *envConfig)
cfg, err := preference.NewClient(ctx) Expect(found).To(Equal(len(pathsToValidate)))
Expect(err).ShouldNot(HaveOccurred()) Expect(notToBeFound).To(Equal(0))
if tt.setupFunc != nil { })
tt.setupFunc(cfg) })
}
cmd := helper.Cmd("odo", "init", "--name", "aname", "--devfile", "go") It("should successfully run odo init for devfile with starter project from the specified branch", func() {
for k, v := range tt.env { helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", helper.GetExamplePath("source", "devfiles", "nodejs", "devfile-with-branch.yaml"), "--starter", "nodejs-starter").ShouldPass()
cmd = cmd.AddEnv(fmt.Sprintf("%s=%s", k, v)) expectedFiles := []string{"package.json", "package-lock.json", "README.md", "devfile.yaml", "test"}
} Expect(helper.ListFilesInDir(commonVar.Context)).To(ContainElements(expectedFiles))
stdout, stderr = cmd.ShouldPass().OutAndErr() })
It("should successfully run odo init for devfile with starter project from the specified tag", func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", helper.GetExamplePath("source", "devfiles", "nodejs", "devfile-with-tag.yaml"), "--starter", "nodejs-starter").ShouldPass()
expectedFiles := []string{"package.json", "package-lock.json", "README.md", "devfile.yaml", "app"}
Expect(helper.ListFilesInDir(commonVar.Context)).To(ContainElements(expectedFiles))
})
It("should successfully run odo init for devfile with starter project on git with main default branch", func() {
helper.Cmd("odo", "init",
"--name", "vertx",
"--devfile-path", helper.GetExamplePath("source", "devfiles", "java", "devfile-with-git-main-branch.yaml"),
"--starter", "vertx-http-example-redhat",
).ShouldPass()
})
When("running odo init from a directory with sources", func() {
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
})
It("should work without --starter flag", func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile", "nodejs").ShouldPass()
})
It("should not accept --starter flag", func() {
err := helper.Cmd("odo", "init", "--name", "aname", "--devfile", "nodejs", "--starter", "nodejs-starter").ShouldFail().Err()
Expect(err).To(ContainSubstring("--starter parameter cannot be used when the directory is not empty"))
})
})
Context("checking odo init final output message", func() {
var newContext, devfilePath string
BeforeEach(func() {
newContext = helper.CreateNewContext()
devfilePath = filepath.Join(newContext, "devfile.yaml")
}) })
AfterEach(func() { AfterEach(func() {
helper.ResetTelemetry() helper.DeleteDir(newContext)
}) })
It("should record the telemetry data correctly", func() { When("the devfile used by `odo init` does not contain a deploy command", func() {
td := helper.GetTelemetryDebugData() var out string
Expect(td.Event).To(ContainSubstring("odo init"))
Expect(td.Properties.Success).To(BeTrue()) BeforeEach(func() {
Expect(td.Properties.Error == "").To(BeTrue()) helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile.yaml"), devfilePath)
Expect(td.Properties.ErrorType == "").To(BeTrue()) out = helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", devfilePath).ShouldPass().Out()
Expect(td.Properties.CmdProperties[segmentContext.DevfileName]).To(ContainSubstring("aname")) })
Expect(td.Properties.CmdProperties[segmentContext.ComponentType]).To(ContainSubstring("Go"))
Expect(td.Properties.CmdProperties[segmentContext.Language]).To(ContainSubstring("Go")) It("should only show information about `odo dev`, and not `odo deploy`", func() {
Expect(td.Properties.CmdProperties[segmentContext.ProjectType]).To(ContainSubstring("Go")) Expect(out).To(ContainSubstring("odo dev"))
Expect(td.Properties.CmdProperties[segmentContext.Flags]).To(ContainSubstring("devfile name")) Expect(out).ToNot(ContainSubstring("odo deploy"))
tt.callerChecker(stdout, stderr, td) })
It("should not show the interactive mode notice message", func() {
Expect(out).ShouldNot(ContainSubstring(messages.InteractiveModeEnabled))
})
}) })
When("the devfile used by `odo init` contains a deploy command", func() {
var out string
BeforeEach(func() {
helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile-deploy.yaml"), devfilePath)
out = helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", devfilePath).ShouldPass().Out()
})
It("should show information about both `odo dev`, and `odo deploy`", func() {
Expect(out).To(ContainSubstring("odo dev"))
Expect(out).To(ContainSubstring("odo deploy"))
})
It("should not show the interactive mode notice message", func() {
Expect(out).ShouldNot(ContainSubstring(messages.InteractiveModeEnabled))
})
})
}) })
}
}) When("devfile contains parent URI", func() {
var originalKeyList []string
var srcDevfile string
BeforeEach(func() {
var err error
srcDevfile = helper.GetExamplePath("source", "devfiles", "nodejs", "devfile-with-parent.yaml")
originalDevfileContent, err := ioutil.ReadFile(srcDevfile)
Expect(err).To(BeNil())
var content map[string]interface{}
Expect(yaml.Unmarshal(originalDevfileContent, &content)).To(BeNil())
for k := range content {
originalKeyList = append(originalKeyList, k)
}
})
It("should not replace the original devfile", func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", srcDevfile).ShouldPass()
devfileContent, err := ioutil.ReadFile(filepath.Join(commonVar.Context, "devfile.yaml"))
Expect(err).To(BeNil())
var content map[string]interface{}
Expect(yaml.Unmarshal(devfileContent, &content)).To(BeNil())
for k := range content {
Expect(k).To(BeElementOf(originalKeyList))
}
})
})
When("source directory is empty", func() {
BeforeEach(func() {
Expect(helper.ListFilesInDir(commonVar.Context)).To(HaveLen(0))
})
It("name in devfile is personalized in non-interactive mode", func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile-path",
filepath.Join(helper.GetExamplePath(), "source", "devfiles", "nodejs",
"devfile-with-starter-with-devfile.yaml")).ShouldPass()
metadata := helper.GetMetadataFromDevfile(filepath.Join(commonVar.Context, "devfile.yaml"))
Expect(metadata.Name).To(BeEquivalentTo("aname"))
Expect(metadata.Language).To(BeEquivalentTo("nodejs"))
})
})
Describe("telemetry", func() {
for _, tt := range []struct {
name string
env map[string]string
}{
{
name: "ODO_DISABLE_TELEMETRY=true and ODO_TRACKING_CONSENT=yes",
env: map[string]string{
//lint:ignore SA1019 We deprecated this env var, but until it is removed, we still want to test it
segment.DisableTelemetryEnv: "true",
segment.TrackingConsentEnv: "yes",
},
},
{
name: "ODO_DISABLE_TELEMETRY=false and ODO_TRACKING_CONSENT=no",
env: map[string]string{
//lint:ignore SA1019 We deprecated this env var, but until it is removed, we still want to test it
segment.DisableTelemetryEnv: "false",
segment.TrackingConsentEnv: "no",
},
},
} {
tt := tt
It("should error out if "+tt.name, func() {
cmd := helper.Cmd("odo", "init", "--name", "aname", "--devfile", "go")
for k, v := range tt.env {
cmd = cmd.AddEnv(fmt.Sprintf("%s=%s", k, v))
}
stderr := cmd.ShouldFail().Err()
//lint:ignore SA1019 We deprecated this env var, but until it is removed, we still want to test it
Expect(stderr).To(ContainSubstring("%s and %s values are in conflict.", segment.DisableTelemetryEnv, segment.TrackingConsentEnv))
})
}
type telemetryTest struct {
title string
env map[string]string
setupFunc func(cfg preference.Client)
callerChecker func(stdout, stderr string, data segment.TelemetryData)
}
allowedTelemetryCallers := []string{segmentContext.VSCode, segmentContext.IntelliJ, segmentContext.JBoss}
telemetryTests := []telemetryTest{
{
title: "no caller env var",
callerChecker: func(_, _ string, td segment.TelemetryData) {
cmdProperties := td.Properties.CmdProperties
Expect(cmdProperties).Should(HaveKey(segmentContext.Caller))
Expect(cmdProperties[segmentContext.Caller]).To(BeEmpty())
},
},
{
title: "empty caller env var",
env: map[string]string{
helper.TelemetryCaller: "",
},
callerChecker: func(_, _ string, td segment.TelemetryData) {
cmdProperties := td.Properties.CmdProperties
Expect(cmdProperties).Should(HaveKey(segmentContext.Caller))
Expect(cmdProperties[segmentContext.Caller]).To(BeEmpty())
},
},
{
title: "invalid caller env var",
env: map[string]string{
helper.TelemetryCaller: "an-invalid-caller",
},
callerChecker: func(stdout, stderr string, td segment.TelemetryData) {
By("not disclosing list of allowed values", func() {
helper.DontMatchAllInOutput(stdout, allowedTelemetryCallers)
helper.DontMatchAllInOutput(stderr, allowedTelemetryCallers)
})
By("setting the value as caller property in telemetry even if it is invalid", func() {
Expect(td.Properties.CmdProperties[segmentContext.Caller]).To(Equal("an-invalid-caller"))
})
},
},
{
title: "ODO_TRACKING_CONSENT=yes env var should take precedence over ConsentTelemetry preference",
env: map[string]string{segment.TrackingConsentEnv: "yes"},
callerChecker: func(_, _ string, td segment.TelemetryData) {
cmdProperties := td.Properties.CmdProperties
Expect(cmdProperties).Should(HaveKey(segmentContext.Caller))
Expect(cmdProperties[segmentContext.Caller]).To(BeEmpty())
},
setupFunc: func(cfg preference.Client) {
err := cfg.SetConfiguration(preference.ConsentTelemetrySetting, "false")
Expect(err).ShouldNot(HaveOccurred())
},
},
}
for _, c := range allowedTelemetryCallers {
c := c
telemetryTests = append(telemetryTests, telemetryTest{
title: fmt.Sprintf("valid caller env var: %s", c),
env: map[string]string{
helper.TelemetryCaller: c,
},
callerChecker: func(_, _ string, td segment.TelemetryData) {
Expect(td.Properties.CmdProperties[segmentContext.Caller]).To(Equal(c))
},
})
}
for _, tt := range telemetryTests {
tt := tt
When("recording telemetry data with "+tt.title, func() {
var stdout string
var stderr string
BeforeEach(func() {
helper.EnableTelemetryDebug()
ctx := context.Background()
envConfig, err := config.GetConfiguration()
Expect(err).To(BeNil())
ctx = envcontext.WithEnvConfig(ctx, *envConfig)
cfg, err := preference.NewClient(ctx)
Expect(err).ShouldNot(HaveOccurred())
if tt.setupFunc != nil {
tt.setupFunc(cfg)
}
cmd := helper.Cmd("odo", "init", "--name", "aname", "--devfile", "go")
for k, v := range tt.env {
cmd = cmd.AddEnv(fmt.Sprintf("%s=%s", k, v))
}
stdout, stderr = cmd.ShouldPass().OutAndErr()
})
AfterEach(func() {
helper.ResetTelemetry()
})
It("should record the telemetry data correctly", func() {
td := helper.GetTelemetryDebugData()
Expect(td.Event).To(ContainSubstring("odo init"))
Expect(td.Properties.Success).To(BeTrue())
Expect(td.Properties.Error == "").To(BeTrue())
Expect(td.Properties.ErrorType == "").To(BeTrue())
Expect(td.Properties.CmdProperties[segmentContext.DevfileName]).To(ContainSubstring("aname"))
Expect(td.Properties.CmdProperties[segmentContext.ComponentType]).To(ContainSubstring("Go"))
Expect(td.Properties.CmdProperties[segmentContext.Language]).To(ContainSubstring("Go"))
Expect(td.Properties.CmdProperties[segmentContext.ProjectType]).To(ContainSubstring("Go"))
Expect(td.Properties.CmdProperties[segmentContext.Flags]).To(ContainSubstring("devfile name"))
tt.callerChecker(stdout, stderr, td)
})
})
}
})
})
}
}) })

View File

@@ -104,6 +104,27 @@ var _ = Describe("odo list with devfile", func() {
helper.Chdir(commonVar.Context) helper.Chdir(commonVar.Context)
}) })
for _, label := range []string{
helper.LabelNoCluster, helper.LabelUnauth,
} {
label := label
It("should list the local component when no authenticated", Label(label), func() {
By("checking the normal output", func() {
stdOut := helper.Cmd("odo", "list", "component").ShouldPass().Out()
Expect(stdOut).To(ContainSubstring(componentName))
})
By("checking the JSON output", func() {
res := helper.Cmd("odo", "list", "component", "-o", "json").ShouldPass()
stdout, stderr := res.Out(), res.Err()
Expect(helper.IsJSON(stdout)).To(BeTrue())
Expect(stderr).To(BeEmpty())
helper.JsonPathContentIs(stdout, "componentInDevfile", componentName)
helper.JsonPathContentIs(stdout, "components.0.name", componentName)
})
})
}
When("dev is running on cluster", func() { When("dev is running on cluster", func() {
BeforeEach(func() { BeforeEach(func() {
var err error var err error
@@ -314,6 +335,11 @@ var _ = Describe("odo list with devfile", func() {
It("should show the language for 'Type' in odo list", Label(helper.LabelNoCluster), func() { It("should show the language for 'Type' in odo list", Label(helper.LabelNoCluster), func() {
checkList(metadata.Language) checkList(metadata.Language)
}) })
It("should show the language for 'Type' in odo list", Label(helper.LabelUnauth), func() {
checkList(metadata.Language)
})
When("the component is pushed in dev mode", func() { When("the component is pushed in dev mode", func() {
var devSession helper.DevSession var devSession helper.DevSession
BeforeEach(func() { BeforeEach(func() {
@@ -341,6 +367,9 @@ var _ = Describe("odo list with devfile", func() {
It("should show 'Not available' for 'Type' in odo list", Label(helper.LabelNoCluster), func() { It("should show 'Not available' for 'Type' in odo list", Label(helper.LabelNoCluster), func() {
checkList("Not available") checkList("Not available")
}) })
It("should show 'Not available' for 'Type' in odo list", Label(helper.LabelUnauth), func() {
checkList("Not available")
})
When("the component is pushed", func() { When("the component is pushed", func() {
var devSession helper.DevSession var devSession helper.DevSession
BeforeEach(func() { BeforeEach(func() {

View File

@@ -9,139 +9,146 @@ import (
"github.com/redhat-developer/odo/tests/helper" "github.com/redhat-developer/odo/tests/helper"
) )
var _ = Describe("odo devfile registry command tests", Label(helper.LabelNoCluster), func() { var _ = Describe("odo devfile registry command tests", func() {
const registryName string = "RegistryName" for _, label := range []string{
helper.LabelNoCluster, helper.LabelUnauth,
} {
label := label
var _ = Context("label "+label, Label(label), func() {
// Use staging OCI-based registry for tests to avoid overload const registryName string = "RegistryName"
var addRegistryURL string = "https://registry.stage.devfile.io"
proxy := os.Getenv("DEVFILE_PROXY")
if proxy != "" {
addRegistryURL = "http://" + proxy
}
var commonVar helper.CommonVar // Use staging OCI-based registry for tests to avoid overload
var addRegistryURL string = "https://registry.stage.devfile.io"
proxy := os.Getenv("DEVFILE_PROXY")
if proxy != "" {
addRegistryURL = "http://" + proxy
}
// This is run before every Spec (It) var commonVar helper.CommonVar
var _ = BeforeEach(func() {
commonVar = helper.CommonBeforeEach()
helper.Chdir(commonVar.Context)
})
// This is run after every Spec (It) // This is run before every Spec (It)
var _ = AfterEach(func() { var _ = BeforeEach(func() {
helper.CommonAfterEach(commonVar) commonVar = helper.CommonBeforeEach()
}) helper.Chdir(commonVar.Context)
It("Should list all default registries", func() {
output := helper.Cmd("odo", "preference", "view").ShouldPass().Out()
helper.MatchAllInOutput(output, []string{"DefaultDevfileRegistry"})
})
It("Should list at least one nodejs component from the default registry", func() {
output := helper.Cmd("odo", "registry").ShouldPass().Out()
helper.MatchAllInOutput(output, []string{"nodejs"})
})
It("Should list detailed information regarding nodejs", func() {
args := []string{"registry", "--details", "--devfile", "nodejs", "--devfile-registry", "DefaultDevfileRegistry"}
By("using human readable output", func() {
output := helper.Cmd("odo", args...).ShouldPass().Out()
helper.MatchAllInOutput(output, []string{"nodejs-starter", "JavaScript", "Node.js Runtime", "Dev: Y"})
})
By("using JSON output", func() {
args = append(args, "-o", "json")
res := helper.Cmd("odo", args...).ShouldPass()
stdout, stderr := res.Out(), res.Err()
Expect(stderr).To(BeEmpty())
Expect(helper.IsJSON(stdout)).To(BeTrue())
helper.JsonPathContentIs(stdout, "0.name", "nodejs")
helper.JsonPathContentContain(stdout, "0.displayName", "Node")
helper.JsonPathContentContain(stdout, "0.description", "Node")
helper.JsonPathContentContain(stdout, "0.language", "JavaScript")
helper.JsonPathContentContain(stdout, "0.projectType", "Node.js")
helper.JsonPathContentContain(stdout, "0.starterProjects.0", "nodejs-starter")
helper.JsonPathContentContain(stdout, "0.devfileData.devfile.metadata.name", "nodejs")
helper.JsonPathContentContain(stdout, "0.devfileData.supportedOdoFeatures.dev", "true")
})
})
It("Should list python specifically", func() {
args := []string{"registry", "--devfile", "python", "--devfile-registry", "DefaultDevfileRegistry"}
By("using human readable output", func() {
output := helper.Cmd("odo", args...).ShouldPass().Out()
helper.MatchAllInOutput(output, []string{"python"})
})
By("using JSON output", func() {
args = append(args, "-o", "json")
res := helper.Cmd("odo", args...).ShouldPass()
stdout, stderr := res.Out(), res.Err()
Expect(stderr).To(BeEmpty())
Expect(helper.IsJSON(stdout)).To(BeTrue())
helper.JsonPathContentIs(stdout, "0.name", "python")
helper.JsonPathContentContain(stdout, "0.displayName", "Python")
helper.JsonPathContentContain(stdout, "0.description", "Python is an interpreted")
helper.JsonPathContentContain(stdout, "0.language", "Python")
helper.JsonPathContentContain(stdout, "0.projectType", "Python")
helper.JsonPathContentContain(stdout, "0.starterProjects.0", "flask-example")
helper.JsonPathContentContain(stdout, "0.devfileData", "")
})
})
It("Should fail with an error with no registries", func() {
helper.Cmd("odo", "preference", "remove", "registry", "DefaultDevfileRegistry", "-f").ShouldPass()
output := helper.Cmd("odo", "preference", "view").ShouldRun().Err()
helper.MatchAllInOutput(output, []string{"No devfile registries added to the configuration. Refer to `odo preference add registry -h` to add one"})
})
It("Should fail to delete the registry, when registry is not present", func() {
helper.Cmd("odo", "preference", "remove", "registry", registryName, "-f").ShouldFail()
})
When("adding a registry", func() {
BeforeEach(func() {
helper.Cmd("odo", "preference", "add", "registry", registryName, addRegistryURL).ShouldPass()
})
It("should list newly added registry", func() {
output := helper.Cmd("odo", "preference", "view").ShouldPass().Out()
helper.MatchAllInOutput(output, []string{registryName, addRegistryURL})
})
It("should pass, when doing odo init with --devfile-registry flag", func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile", "nodejs", "--devfile-registry", registryName).ShouldPass()
})
It("should fail, when adding same registry", func() {
helper.Cmd("odo", "preference", "add", "registry", registryName, addRegistryURL).ShouldFail()
})
It("should successfully delete registry", func() {
helper.Cmd("odo", "preference", "remove", "registry", registryName, "-f").ShouldPass()
})
It("deleting registry and creating component with registry flag ", func() {
helper.Cmd("odo", "preference", "remove", "registry", registryName, "-f").ShouldPass()
helper.Cmd("odo", "init", "--name", "aname", "--devfile", "java-maven", "--devfile-registry", registryName).ShouldFail()
})
It("should list registry with recently added registry on top", func() {
By("for json output", func() {
output := helper.Cmd("odo", "preference", "view", "-o", "json").ShouldPass().Out()
Expect(helper.IsJSON(output)).To(BeTrue())
helper.JsonPathContentIs(output, "registries.0.name", registryName)
helper.JsonPathContentIs(output, "registries.0.url", addRegistryURL)
helper.JsonPathContentIs(output, "registries.1.name", "DefaultDevfileRegistry")
helper.JsonPathContentIs(output, "registries.1.url", addRegistryURL) // as we are using its updated in case of Proxy
}) })
// This is run after every Spec (It)
var _ = AfterEach(func() {
helper.CommonAfterEach(commonVar)
})
It("Should list all default registries", func() {
output := helper.Cmd("odo", "preference", "view").ShouldPass().Out()
helper.MatchAllInOutput(output, []string{"DefaultDevfileRegistry"})
})
It("Should list at least one nodejs component from the default registry", func() {
output := helper.Cmd("odo", "registry").ShouldPass().Out()
helper.MatchAllInOutput(output, []string{"nodejs"})
})
It("Should list detailed information regarding nodejs", func() {
args := []string{"registry", "--details", "--devfile", "nodejs", "--devfile-registry", "DefaultDevfileRegistry"}
By("using human readable output", func() {
output := helper.Cmd("odo", args...).ShouldPass().Out()
helper.MatchAllInOutput(output, []string{"nodejs-starter", "JavaScript", "Node.js Runtime", "Dev: Y"})
})
By("using JSON output", func() {
args = append(args, "-o", "json")
res := helper.Cmd("odo", args...).ShouldPass()
stdout, stderr := res.Out(), res.Err()
Expect(stderr).To(BeEmpty())
Expect(helper.IsJSON(stdout)).To(BeTrue())
helper.JsonPathContentIs(stdout, "0.name", "nodejs")
helper.JsonPathContentContain(stdout, "0.displayName", "Node")
helper.JsonPathContentContain(stdout, "0.description", "Node")
helper.JsonPathContentContain(stdout, "0.language", "JavaScript")
helper.JsonPathContentContain(stdout, "0.projectType", "Node.js")
helper.JsonPathContentContain(stdout, "0.starterProjects.0", "nodejs-starter")
helper.JsonPathContentContain(stdout, "0.devfileData.devfile.metadata.name", "nodejs")
helper.JsonPathContentContain(stdout, "0.devfileData.supportedOdoFeatures.dev", "true")
})
})
It("Should list python specifically", func() {
args := []string{"registry", "--devfile", "python", "--devfile-registry", "DefaultDevfileRegistry"}
By("using human readable output", func() {
output := helper.Cmd("odo", args...).ShouldPass().Out()
helper.MatchAllInOutput(output, []string{"python"})
})
By("using JSON output", func() {
args = append(args, "-o", "json")
res := helper.Cmd("odo", args...).ShouldPass()
stdout, stderr := res.Out(), res.Err()
Expect(stderr).To(BeEmpty())
Expect(helper.IsJSON(stdout)).To(BeTrue())
helper.JsonPathContentIs(stdout, "0.name", "python")
helper.JsonPathContentContain(stdout, "0.displayName", "Python")
helper.JsonPathContentContain(stdout, "0.description", "Python is an interpreted")
helper.JsonPathContentContain(stdout, "0.language", "Python")
helper.JsonPathContentContain(stdout, "0.projectType", "Python")
helper.JsonPathContentContain(stdout, "0.starterProjects.0", "flask-example")
helper.JsonPathContentContain(stdout, "0.devfileData", "")
})
})
It("Should fail with an error with no registries", func() {
helper.Cmd("odo", "preference", "remove", "registry", "DefaultDevfileRegistry", "-f").ShouldPass()
output := helper.Cmd("odo", "preference", "view").ShouldRun().Err()
helper.MatchAllInOutput(output, []string{"No devfile registries added to the configuration. Refer to `odo preference add registry -h` to add one"})
})
It("Should fail to delete the registry, when registry is not present", func() {
helper.Cmd("odo", "preference", "remove", "registry", registryName, "-f").ShouldFail()
})
When("adding a registry", func() {
BeforeEach(func() {
helper.Cmd("odo", "preference", "add", "registry", registryName, addRegistryURL).ShouldPass()
})
It("should list newly added registry", func() {
output := helper.Cmd("odo", "preference", "view").ShouldPass().Out()
helper.MatchAllInOutput(output, []string{registryName, addRegistryURL})
})
It("should pass, when doing odo init with --devfile-registry flag", func() {
helper.Cmd("odo", "init", "--name", "aname", "--devfile", "nodejs", "--devfile-registry", registryName).ShouldPass()
})
It("should fail, when adding same registry", func() {
helper.Cmd("odo", "preference", "add", "registry", registryName, addRegistryURL).ShouldFail()
})
It("should successfully delete registry", func() {
helper.Cmd("odo", "preference", "remove", "registry", registryName, "-f").ShouldPass()
})
It("deleting registry and creating component with registry flag ", func() {
helper.Cmd("odo", "preference", "remove", "registry", registryName, "-f").ShouldPass()
helper.Cmd("odo", "init", "--name", "aname", "--devfile", "java-maven", "--devfile-registry", registryName).ShouldFail()
})
It("should list registry with recently added registry on top", func() {
By("for json output", func() {
output := helper.Cmd("odo", "preference", "view", "-o", "json").ShouldPass().Out()
Expect(helper.IsJSON(output)).To(BeTrue())
helper.JsonPathContentIs(output, "registries.0.name", registryName)
helper.JsonPathContentIs(output, "registries.0.url", addRegistryURL)
helper.JsonPathContentIs(output, "registries.1.name", "DefaultDevfileRegistry")
helper.JsonPathContentIs(output, "registries.1.url", addRegistryURL) // as we are using its updated in case of Proxy
})
})
})
It("should fail when adding a git based registry", func() {
err := helper.Cmd("odo", "preference", "add", "registry", "RegistryFromGitHub", "https://github.com/devfile/registry").ShouldFail().Err()
helper.MatchAllInOutput(err, []string{"github", "no", "supported", "https://github.com/devfile/registry-support"})
})
}) })
}) }
It("should fail when adding a git based registry", func() {
err := helper.Cmd("odo", "preference", "add", "registry", "RegistryFromGitHub", "https://github.com/devfile/registry").ShouldFail().Err()
helper.MatchAllInOutput(err, []string{"github", "no", "supported", "https://github.com/devfile/registry-support"})
})
}) })

View File

@@ -186,6 +186,10 @@ ComponentSettings:
Expect(out).To(ContainSubstring("Please ensure you have an active kubernetes context to your cluster.")) Expect(out).To(ContainSubstring("Please ensure you have an active kubernetes context to your cluster."))
}) })
It("should fail, with unauth cluster", Label(helper.LabelUnauth), func() {
_ = helper.Cmd("odo", "list", commandName).ShouldFail()
})
It(fmt.Sprintf("should successfully list all the %ss", commandName), func() { It(fmt.Sprintf("should successfully list all the %ss", commandName), func() {
Eventually(func() string { Eventually(func() string {
out := helper.Cmd("odo", "list", commandName).ShouldPass().Out() out := helper.Cmd("odo", "list", commandName).ShouldPass().Out()

View File

@@ -13,118 +13,125 @@ import (
const promptMessageSubString = "Help odo improve by allowing it to collect usage data." const promptMessageSubString = "Help odo improve by allowing it to collect usage data."
var _ = Describe("odo preference and config command tests", Label(helper.LabelNoCluster), func() { var _ = Describe("odo preference and config command tests", func() {
// TODO: A neater way to provide odo path. Currently we assume odo and oc in $PATH already.
var commonVar helper.CommonVar
// This is run before every Spec (It) for _, label := range []string{
var _ = BeforeEach(func() { helper.LabelNoCluster, helper.LabelUnauth,
commonVar = helper.CommonBeforeEach() } {
}) label := label
var _ = Context("label "+label, Label(label), func() {
// Clean up after the test // TODO: A neater way to provide odo path. Currently we assume odo and oc in $PATH already.
// This is run after every Spec (It) var commonVar helper.CommonVar
var _ = AfterEach(func() {
helper.CommonAfterEach(commonVar)
})
Context("check that help works", func() { // This is run before every Spec (It)
It("should display help info", func() { var _ = BeforeEach(func() {
helpArgs := []string{"-h", "help", "--help"} commonVar = helper.CommonBeforeEach()
for _, helpArg := range helpArgs { })
appHelp := helper.Cmd("odo", helpArg).ShouldPass().Out()
Expect(appHelp).To(ContainSubstring(`Use "odo [command] --help" for more information about a command.`))
}
})
})
Context("when running help for preference command", func() { // Clean up after the test
It("should display the help", func() { // This is run after every Spec (It)
appHelp := helper.Cmd("odo", "preference", "-h").ShouldPass().Out() var _ = AfterEach(func() {
Expect(appHelp).To(ContainSubstring("Modifies odo specific configuration settings")) helper.CommonAfterEach(commonVar)
}) })
})
Context("When viewing global config", func() { Context("check that help works", func() {
var newContext string It("should display help info", func() {
// ConsentTelemetry is set to false in helper.CommonBeforeEach so that it does not prompt to set a value helpArgs := []string{"-h", "help", "--help"}
// during the tests, but we want to check preference values as they would be in real time and hence for _, helpArg := range helpArgs {
// we set the GLOBALODOCONFIG variable to a value in new context appHelp := helper.Cmd("odo", helpArg).ShouldPass().Out()
var _ = JustBeforeEach(func() { Expect(appHelp).To(ContainSubstring(`Use "odo [command] --help" for more information about a command.`))
newContext = helper.CreateNewContext() }
os.Setenv("GLOBALODOCONFIG", filepath.Join(newContext, "preference.yaml")) })
}) })
var _ = JustAfterEach(func() {
helper.DeleteDir(newContext)
})
It("should get the default global config keys", func() {
configOutput := helper.Cmd("odo", "preference", "view").ShouldPass().Out()
preferences := []string{"UpdateNotification", "Timeout", "PushTimeout", "RegistryCacheTime", "Ephemeral", "ConsentTelemetry"}
helper.MatchAllInOutput(configOutput, preferences)
for _, key := range preferences {
value := helper.GetPreferenceValue(key)
Expect(value).To(BeEmpty())
}
})
It("should get the default global config keys in JSON output", func() {
res := helper.Cmd("odo", "preference", "view", "-o", "json").ShouldPass()
stdout, stderr := res.Out(), res.Err()
Expect(stderr).To(BeEmpty())
Expect(helper.IsJSON(stdout)).To(BeTrue())
preferences := []string{"UpdateNotification", "Timeout", "PushTimeout", "RegistryCacheTime", "ConsentTelemetry", "Ephemeral"}
for i, pref := range preferences {
helper.JsonPathContentIs(stdout, fmt.Sprintf("preferences.%d.name", i), pref)
}
helper.JsonPathContentIs(stdout, "registries.#", "1")
helper.JsonPathContentIs(stdout, "registries.0.name", "DefaultDevfileRegistry")
})
})
Context("When configuring global config values", func() { Context("when running help for preference command", func() {
preferences := []struct { It("should display the help", func() {
name string appHelp := helper.Cmd("odo", "preference", "-h").ShouldPass().Out()
value string Expect(appHelp).To(ContainSubstring("Modifies odo specific configuration settings"))
updateValue string })
invalidValue string })
firstSetWithForce bool
}{
{"UpdateNotification", "false", "true", "foo", false},
{"Timeout", "5s", "6s", "foo", false},
// !! Do not test ConsentTelemetry with true because it sends out the telemetry data and messes up the statistics !!
{"ConsentTelemetry", "false", "false", "foo", false},
{"PushTimeout", "4s", "6s", "foo", false},
{"RegistryCacheTime", "4m", "6m", "foo", false},
{"Ephemeral", "false", "true", "foo", true},
}
It("should successfully updated", func() { Context("When viewing global config", func() {
for _, pref := range preferences { var newContext string
// construct arguments for the first command // ConsentTelemetry is set to false in helper.CommonBeforeEach so that it does not prompt to set a value
firstCmdArgs := []string{"preference", "set"} // during the tests, but we want to check preference values as they would be in real time and hence
if pref.firstSetWithForce { // we set the GLOBALODOCONFIG variable to a value in new context
firstCmdArgs = append(firstCmdArgs, "-f") var _ = JustBeforeEach(func() {
newContext = helper.CreateNewContext()
os.Setenv("GLOBALODOCONFIG", filepath.Join(newContext, "preference.yaml"))
})
var _ = JustAfterEach(func() {
helper.DeleteDir(newContext)
})
It("should get the default global config keys", func() {
configOutput := helper.Cmd("odo", "preference", "view").ShouldPass().Out()
preferences := []string{"UpdateNotification", "Timeout", "PushTimeout", "RegistryCacheTime", "Ephemeral", "ConsentTelemetry"}
helper.MatchAllInOutput(configOutput, preferences)
for _, key := range preferences {
value := helper.GetPreferenceValue(key)
Expect(value).To(BeEmpty())
}
})
It("should get the default global config keys in JSON output", func() {
res := helper.Cmd("odo", "preference", "view", "-o", "json").ShouldPass()
stdout, stderr := res.Out(), res.Err()
Expect(stderr).To(BeEmpty())
Expect(helper.IsJSON(stdout)).To(BeTrue())
preferences := []string{"UpdateNotification", "Timeout", "PushTimeout", "RegistryCacheTime", "ConsentTelemetry", "Ephemeral"}
for i, pref := range preferences {
helper.JsonPathContentIs(stdout, fmt.Sprintf("preferences.%d.name", i), pref)
}
helper.JsonPathContentIs(stdout, "registries.#", "1")
helper.JsonPathContentIs(stdout, "registries.0.name", "DefaultDevfileRegistry")
})
})
Context("When configuring global config values", func() {
preferences := []struct {
name string
value string
updateValue string
invalidValue string
firstSetWithForce bool
}{
{"UpdateNotification", "false", "true", "foo", false},
{"Timeout", "5s", "6s", "foo", false},
// !! Do not test ConsentTelemetry with true because it sends out the telemetry data and messes up the statistics !!
{"ConsentTelemetry", "false", "false", "foo", false},
{"PushTimeout", "4s", "6s", "foo", false},
{"RegistryCacheTime", "4m", "6m", "foo", false},
{"Ephemeral", "false", "true", "foo", true},
} }
firstCmdArgs = append(firstCmdArgs, pref.name, pref.value)
helper.Cmd("odo", firstCmdArgs...).ShouldPass() It("should successfully updated", func() {
value := helper.GetPreferenceValue(pref.name) for _, pref := range preferences {
Expect(value).To(ContainSubstring(pref.value)) // construct arguments for the first command
firstCmdArgs := []string{"preference", "set"}
if pref.firstSetWithForce {
firstCmdArgs = append(firstCmdArgs, "-f")
}
firstCmdArgs = append(firstCmdArgs, pref.name, pref.value)
helper.Cmd("odo", "preference", "set", "-f", pref.name, pref.updateValue).ShouldPass() helper.Cmd("odo", firstCmdArgs...).ShouldPass()
value = helper.GetPreferenceValue(pref.name) value := helper.GetPreferenceValue(pref.name)
Expect(value).To(ContainSubstring(pref.updateValue)) Expect(value).To(ContainSubstring(pref.value))
helper.Cmd("odo", "preference", "unset", "-f", pref.name).ShouldPass() helper.Cmd("odo", "preference", "set", "-f", pref.name, pref.updateValue).ShouldPass()
value = helper.GetPreferenceValue(pref.name) value = helper.GetPreferenceValue(pref.name)
Expect(value).To(BeEmpty()) Expect(value).To(ContainSubstring(pref.updateValue))
}
globalConfPath := os.Getenv("HOME") helper.Cmd("odo", "preference", "unset", "-f", pref.name).ShouldPass()
os.RemoveAll(filepath.Join(globalConfPath, ".odo")) value = helper.GetPreferenceValue(pref.name)
}) Expect(value).To(BeEmpty())
}) }
When("when preference.yaml contains an int value for Timeout", func() { globalConfPath := os.Getenv("HOME")
BeforeEach(func() { os.RemoveAll(filepath.Join(globalConfPath, ".odo"))
preference := ` })
})
When("when preference.yaml contains an int value for Timeout", func() {
BeforeEach(func() {
preference := `
kind: Preference kind: Preference
apiversion: odo.dev/v1alpha1 apiversion: odo.dev/v1alpha1
OdoSettings: OdoSettings:
@@ -136,61 +143,62 @@ OdoSettings:
ConsentTelemetry: true ConsentTelemetry: true
Timeout: 10 Timeout: 10
` `
preferencePath := filepath.Join(commonVar.Context, "preference.yaml") preferencePath := filepath.Join(commonVar.Context, "preference.yaml")
err := helper.CreateFileWithContent(preferencePath, preference) err := helper.CreateFileWithContent(preferencePath, preference)
Expect(err).To(BeNil()) Expect(err).To(BeNil())
os.Setenv("GLOBALODOCONFIG", preferencePath) os.Setenv("GLOBALODOCONFIG", preferencePath)
}) })
It("should show warning about incompatible Timeout value when viewing preferences", func() { It("should show warning about incompatible Timeout value when viewing preferences", func() {
errOut := helper.Cmd("odo", "preference", "view").ShouldPass().Err() errOut := helper.Cmd("odo", "preference", "view").ShouldPass().Err()
Expect(helper.GetPreferenceValue("Timeout")).To(ContainSubstring("10ns")) Expect(helper.GetPreferenceValue("Timeout")).To(ContainSubstring("10ns"))
Expect(errOut).To(ContainSubstring("Please change the preference value for Timeout")) Expect(errOut).To(ContainSubstring("Please change the preference value for Timeout"))
}) })
}) })
It("should fail to set an incompatible format for a preference that accepts duration", func() { It("should fail to set an incompatible format for a preference that accepts duration", func() {
errOut := helper.Cmd("odo", "preference", "set", "RegistryCacheTime", "1d").ShouldFail().Err() errOut := helper.Cmd("odo", "preference", "set", "RegistryCacheTime", "1d").ShouldFail().Err()
Expect(errOut).To(ContainSubstring("unable to set \"registrycachetime\" to \"1d\"")) Expect(errOut).To(ContainSubstring("unable to set \"registrycachetime\" to \"1d\""))
}) })
Context("When no ConsentTelemetry preference value is set", func() { Context("When no ConsentTelemetry preference value is set", func() {
var _ = JustBeforeEach(func() { var _ = JustBeforeEach(func() {
// unset the preference in case it is already set // unset the preference in case it is already set
helper.Cmd("odo", "preference", "unset", "ConsentTelemetry", "-f").ShouldPass() helper.Cmd("odo", "preference", "unset", "ConsentTelemetry", "-f").ShouldPass()
})
It("should not prompt when user calls for help", func() {
output := helper.Cmd("odo", "init", "--help").ShouldPass().Out()
Expect(output).ToNot(ContainSubstring(promptMessageSubString))
})
It("should not prompt when preference command is run", func() {
output := helper.Cmd("odo", "preference", "view").ShouldPass().Out()
Expect(output).ToNot(ContainSubstring(promptMessageSubString))
output = helper.Cmd("odo", "preference", "set", "timeout", "5s", "-f").ShouldPass().Out()
Expect(output).ToNot(ContainSubstring(promptMessageSubString))
output = helper.Cmd("odo", "preference", "unset", "timeout", "-f").ShouldPass().Out()
Expect(output).ToNot(ContainSubstring(promptMessageSubString))
})
})
Context("When ConsentTelemetry preference value is set", func() {
// !! Do not test with true because it sends out the telemetry data and messes up the statistics !!
var workingDir string
BeforeEach(func() {
workingDir = helper.Getwd()
helper.Chdir(commonVar.Context)
})
AfterEach(func() {
helper.Chdir(workingDir)
})
It("should not prompt the user", func() {
helper.Cmd("odo", "preference", "set", "ConsentTelemetry", "false", "-f").ShouldPass()
output := helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", helper.GetExamplePath("source", "devfiles", "nodejs", "devfile-registry.yaml")).ShouldPass().Out()
Expect(output).ToNot(ContainSubstring(promptMessageSubString))
})
})
}) })
}
It("should not prompt when user calls for help", func() {
output := helper.Cmd("odo", "init", "--help").ShouldPass().Out()
Expect(output).ToNot(ContainSubstring(promptMessageSubString))
})
It("should not prompt when preference command is run", func() {
output := helper.Cmd("odo", "preference", "view").ShouldPass().Out()
Expect(output).ToNot(ContainSubstring(promptMessageSubString))
output = helper.Cmd("odo", "preference", "set", "timeout", "5s", "-f").ShouldPass().Out()
Expect(output).ToNot(ContainSubstring(promptMessageSubString))
output = helper.Cmd("odo", "preference", "unset", "timeout", "-f").ShouldPass().Out()
Expect(output).ToNot(ContainSubstring(promptMessageSubString))
})
})
Context("When ConsentTelemetry preference value is set", func() {
// !! Do not test with true because it sends out the telemetry data and messes up the statistics !!
var workingDir string
BeforeEach(func() {
workingDir = helper.Getwd()
helper.Chdir(commonVar.Context)
})
AfterEach(func() {
helper.Chdir(workingDir)
})
It("should not prompt the user", func() {
helper.Cmd("odo", "preference", "set", "ConsentTelemetry", "false", "-f").ShouldPass()
output := helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", helper.GetExamplePath("source", "devfiles", "nodejs", "devfile-registry.yaml")).ShouldPass().Out()
Expect(output).ToNot(ContainSubstring(promptMessageSubString))
})
})
}) })

View File

@@ -29,18 +29,25 @@ var _ = Describe("odo remove binding command tests", func() {
helper.Cmd("odo", "init", "--name", "mynode", "--devfile-path", helper.GetExamplePath("source", "devfiles", "nodejs", "devfile-with-service-binding-files.yaml")).ShouldPass() helper.Cmd("odo", "init", "--name", "mynode", "--devfile-path", helper.GetExamplePath("source", "devfiles", "nodejs", "devfile-with-service-binding-files.yaml")).ShouldPass()
}) })
When("removing the binding", Label(helper.LabelNoCluster), func() { for _, label := range []string{
BeforeEach(func() { helper.LabelNoCluster, helper.LabelUnauth,
helper.Cmd("odo", "remove", "binding", "--name", bindingName).ShouldPass() } {
label := label
When("removing the binding", Label(label), func() {
BeforeEach(func() {
helper.Cmd("odo", "remove", "binding", "--name", bindingName).ShouldPass()
})
It("should successfully remove binding between component and service in the devfile", func() {
components := helper.GetDevfileComponents(filepath.Join(commonVar.Context, "devfile.yaml"), bindingName)
Expect(components).To(BeNil())
})
}) })
It("should successfully remove binding between component and service in the devfile", func() {
components := helper.GetDevfileComponents(filepath.Join(commonVar.Context, "devfile.yaml"), bindingName) It("should fail to remove binding that does not exist", func() {
Expect(components).To(BeNil()) helper.Cmd("odo", "remove", "binding", "--name", "my-binding").ShouldFail()
}) })
}) }
It("should fail to remove binding that does not exist", Label(helper.LabelNoCluster), func() {
helper.Cmd("odo", "remove", "binding", "--name", "my-binding").ShouldFail()
})
When("odo dev is running", func() { When("odo dev is running", func() {
var session helper.DevSession var session helper.DevSession
BeforeEach(func() { BeforeEach(func() {

View File

@@ -26,66 +26,73 @@ var _ = Describe("odo generic", func() {
helper.CommonAfterEach(commonVar) helper.CommonAfterEach(commonVar)
}) })
When("running odo --help", Label(helper.LabelNoCluster), func() { for _, label := range []string{
var output string helper.LabelNoCluster, helper.LabelUnauth,
BeforeEach(func() { } {
output = helper.Cmd("odo", "--help").ShouldPass().Out() label := label
}) Context("label "+label, Label(label), func() {
It("retuns full help contents including usage, examples, commands, utility commands, component shortcuts, and flags sections", func() { When("running odo --help", func() {
helper.MatchAllInOutput(output, []string{"Usage:", "Examples:", "Main Commands:", "OpenShift Commands:", "Utility Commands:", "Flags:"}) var output string
}) BeforeEach(func() {
output = helper.Cmd("odo", "--help").ShouldPass().Out()
})
It("retuns full help contents including usage, examples, commands, utility commands, component shortcuts, and flags sections", func() {
helper.MatchAllInOutput(output, []string{"Usage:", "Examples:", "Main Commands:", "OpenShift Commands:", "Utility Commands:", "Flags:"})
})
}) })
When("running odo without subcommand and flags", Label(helper.LabelNoCluster), func() { When("running odo without subcommand and flags", func() {
var output string var output string
BeforeEach(func() { BeforeEach(func() {
output = helper.Cmd("odo").ShouldPass().Out() output = helper.Cmd("odo").ShouldPass().Out()
})
It("a short vesion of help contents is returned, an error is not expected", func() {
Expect(output).To(ContainSubstring("To see a full list of commands, run 'odo --help'"))
})
})
It("returns error when using an invalid command", func() {
output := helper.Cmd("odo", "hello").ShouldFail().Err()
Expect(output).To(ContainSubstring("Invalid command - see available commands/subcommands above"))
})
It("returns JSON error", func() {
By("using an invalid command with JSON output", func() {
res := helper.Cmd("odo", "unknown-command", "-o", "json").ShouldFail()
stdout, stderr := res.Out(), res.Err()
Expect(stdout).To(BeEmpty())
Expect(helper.IsJSON(stderr)).To(BeTrue())
})
By("using an invalid describe sub-command with JSON output", func() {
res := helper.Cmd("odo", "describe", "unknown-sub-command", "-o", "json").ShouldFail()
stdout, stderr := res.Out(), res.Err()
Expect(stdout).To(BeEmpty())
Expect(helper.IsJSON(stderr)).To(BeTrue())
})
By("using an invalid list sub-command with JSON output", func() {
res := helper.Cmd("odo", "list", "unknown-sub-command", "-o", "json").ShouldFail()
stdout, stderr := res.Out(), res.Err()
Expect(stdout).To(BeEmpty())
Expect(helper.IsJSON(stderr)).To(BeTrue())
})
By("omitting required subcommand with JSON output", func() {
res := helper.Cmd("odo", "describe", "-o", "json").ShouldFail()
stdout, stderr := res.Out(), res.Err()
Expect(stdout).To(BeEmpty())
Expect(helper.IsJSON(stderr)).To(BeTrue())
})
})
It("returns error when using an invalid command with --help", func() {
output := helper.Cmd("odo", "hello", "--help").ShouldFail().Err()
Expect(output).To(ContainSubstring("unknown command 'hello', type --help for a list of all commands"))
})
}) })
It("a short vesion of help contents is returned, an error is not expected", func() { }
Expect(output).To(ContainSubstring("To see a full list of commands, run 'odo --help'"))
})
})
It("returns error when using an invalid command", Label(helper.LabelNoCluster), func() {
output := helper.Cmd("odo", "hello").ShouldFail().Err()
Expect(output).To(ContainSubstring("Invalid command - see available commands/subcommands above"))
})
It("returns JSON error", Label(helper.LabelNoCluster), func() {
By("using an invalid command with JSON output", func() {
res := helper.Cmd("odo", "unknown-command", "-o", "json").ShouldFail()
stdout, stderr := res.Out(), res.Err()
Expect(stdout).To(BeEmpty())
Expect(helper.IsJSON(stderr)).To(BeTrue())
})
By("using an invalid describe sub-command with JSON output", func() {
res := helper.Cmd("odo", "describe", "unknown-sub-command", "-o", "json").ShouldFail()
stdout, stderr := res.Out(), res.Err()
Expect(stdout).To(BeEmpty())
Expect(helper.IsJSON(stderr)).To(BeTrue())
})
By("using an invalid list sub-command with JSON output", func() {
res := helper.Cmd("odo", "list", "unknown-sub-command", "-o", "json").ShouldFail()
stdout, stderr := res.Out(), res.Err()
Expect(stdout).To(BeEmpty())
Expect(helper.IsJSON(stderr)).To(BeTrue())
})
By("omitting required subcommand with JSON output", func() {
res := helper.Cmd("odo", "describe", "-o", "json").ShouldFail()
stdout, stderr := res.Out(), res.Err()
Expect(stdout).To(BeEmpty())
Expect(helper.IsJSON(stderr)).To(BeTrue())
})
})
It("returns error when using an invalid command with --help", Label(helper.LabelNoCluster), func() {
output := helper.Cmd("odo", "hello", "--help").ShouldFail().Err()
Expect(output).To(ContainSubstring("unknown command 'hello', type --help for a list of all commands"))
})
Context("When deleting two project one after the other", func() { Context("When deleting two project one after the other", func() {
It("should be able to delete sequentially", func() { It("should be able to delete sequentially", func() {
@@ -124,6 +131,10 @@ var _ = Describe("odo generic", func() {
reOdoVersion := `^odo\s*v[0-9]+.[0-9]+.[0-9]+(?:-\w+)?\s*\(\w+\)` reOdoVersion := `^odo\s*v[0-9]+.[0-9]+.[0-9]+(?:-\w+)?\s*\(\w+\)`
Expect(odoVersion).Should(MatchRegexp(reOdoVersion)) Expect(odoVersion).Should(MatchRegexp(reOdoVersion))
}) })
It("should show the version of odo major components", Label(helper.LabelUnauth), func() {
reOdoVersion := `^odo\s*v[0-9]+.[0-9]+.[0-9]+(?:-\w+)?\s*\(\w+\)`
Expect(odoVersion).Should(MatchRegexp(reOdoVersion))
})
}) })
Describe("Experimental Mode", func() { Describe("Experimental Mode", func() {

View File

@@ -23,264 +23,40 @@ import (
"github.com/redhat-developer/odo/tests/helper" "github.com/redhat-developer/odo/tests/helper"
) )
var _ = Describe("odo init interactive command tests", Label(helper.LabelNoCluster), func() { var _ = Describe("odo init interactive command tests", func() {
for _, label := range []string{
helper.LabelNoCluster, helper.LabelUnauth,
} {
label := label
var _ = Context("label "+label, Label(label), func() {
var commonVar helper.CommonVar
var commonVar helper.CommonVar // This is run before every Spec (It)
var _ = BeforeEach(func() {
commonVar = helper.CommonBeforeEach()
helper.Chdir(commonVar.Context)
// This is run before every Spec (It) // We make EXPLICITLY sure that we are outputting with NO COLOR
var _ = BeforeEach(func() { // this is because in some cases we are comparing the output with a colorized one
commonVar = helper.CommonBeforeEach() os.Setenv("NO_COLOR", "true")
helper.Chdir(commonVar.Context)
// We make EXPLICITLY sure that we are outputting with NO COLOR
// this is because in some cases we are comparing the output with a colorized one
os.Setenv("NO_COLOR", "true")
})
// Clean up after the test
// This is run after every Spec (It)
var _ = AfterEach(func() {
helper.CommonAfterEach(commonVar)
})
It("should not fail when using -v flag", func() {
command := []string{"odo", "init", "-v", "4"}
output, err := helper.RunInteractive(command, nil, func(ctx helper.InteractiveContext) {
By("showing the interactive mode notice message", func() {
helper.ExpectString(ctx, messages.InteractiveModeEnabled)
}) })
helper.ExpectString(ctx, "Select language") // Clean up after the test
helper.SendLine(ctx, "Go") // This is run after every Spec (It)
var _ = AfterEach(func() {
helper.ExpectString(ctx, "Select project type") helper.CommonAfterEach(commonVar)
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Select container for which you want to change configuration?")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Which starter project do you want to use")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Enter component name")
helper.SendLine(ctx, "my-go-app")
helper.ExpectString(ctx, "Your new component 'my-go-app' is ready in the current directory")
})
Expect(err).To(BeNil())
Expect(output).To(ContainSubstring("Your new component 'my-go-app' is ready in the current directory"))
Expect(helper.ListFilesInDir(commonVar.Context)).To(ContainElements("devfile.yaml"))
})
It("should ask to re-enter the component name when an invalid value is passed", func() {
command := []string{"odo", "init"}
_, err := helper.RunInteractive(command, nil, func(ctx helper.InteractiveContext) {
helper.ExpectString(ctx, "Select language")
helper.SendLine(ctx, "Go")
helper.ExpectString(ctx, "Select project type")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Select container for which you want to change configuration?")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Which starter project do you want to use")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Enter component name")
helper.SendLine(ctx, "myapp-<script>alert('Injected!');</script>")
helper.ExpectString(ctx, "name \"myapp-<script>alert('Injected!');</script>\" is not valid, name should conform the following requirements")
helper.ExpectString(ctx, "Enter component name")
helper.SendLine(ctx, "my-go-app")
helper.ExpectString(ctx, "Your new component 'my-go-app' is ready in the current directory")
})
Expect(err).To(BeNil())
Expect(helper.ListFilesInDir(commonVar.Context)).To(ContainElements("devfile.yaml"))
})
It("should print automation command with proper values", func() {
// This test fails on Windows because of terminal emulator behaviour
if os.Getenv("SKIP_WELCOMING_MESSAGES") == "true" {
Skip("This is a Unix specific scenario, skipping")
}
command := []string{"odo", "init"}
starter := "go-starter"
componentName := "my-go-app"
devfileName := "go"
output, err := helper.RunInteractive(command, nil, func(ctx helper.InteractiveContext) {
helper.ExpectString(ctx, "Select language")
helper.SendLine(ctx, "Go")
helper.ExpectString(ctx, "Select project type")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Select container for which you want to change configuration?")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Which starter project do you want to use")
helper.SendLine(ctx, starter)
helper.ExpectString(ctx, "Enter component name")
helper.SendLine(ctx, componentName)
helper.ExpectString(ctx, "Your new component 'my-go-app' is ready in the current directory")
})
Expect(err).To(BeNil())
Expect(output).To(ContainSubstring("odo init --name %s --devfile %s --devfile-registry DefaultDevfileRegistry --starter %s", componentName, devfileName, starter))
Expect(output).To(ContainSubstring("Your new component 'my-go-app' is ready in the current directory"))
Expect(helper.ListFilesInDir(commonVar.Context)).To(ContainElements("devfile.yaml"))
})
It("should download correct devfile", func() {
command := []string{"odo", "init"}
output, err := helper.RunInteractive(command, nil, func(ctx helper.InteractiveContext) {
By("showing the interactive mode notice message", func() {
helper.ExpectString(ctx, messages.InteractiveModeEnabled)
}) })
helper.ExpectString(ctx, "Select language") It("should not fail when using -v flag", func() {
helper.SendLine(ctx, "Go") command := []string{"odo", "init", "-v", "4"}
output, err := helper.RunInteractive(command, nil, func(ctx helper.InteractiveContext) {
helper.ExpectString(ctx, "Select project type") By("showing the interactive mode notice message", func() {
helper.SendLine(ctx, "") helper.ExpectString(ctx, messages.InteractiveModeEnabled)
})
helper.ExpectString(ctx, "Select container for which you want to change configuration?")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Which starter project do you want to use")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Enter component name")
helper.SendLine(ctx, "my-go-app")
helper.ExpectString(ctx, "Your new component 'my-go-app' is ready in the current directory")
})
Expect(err).To(BeNil())
Expect(output).To(ContainSubstring("Your new component 'my-go-app' is ready in the current directory"))
Expect(helper.ListFilesInDir(commonVar.Context)).To(ContainElements("devfile.yaml"))
})
It("should download correct devfile-starter", func() {
command := []string{"odo", "init"}
output, err := helper.RunInteractive(command, nil, func(ctx helper.InteractiveContext) {
By("showing the interactive mode notice message", func() {
helper.ExpectString(ctx, messages.InteractiveModeEnabled)
})
helper.ExpectString(ctx, "Select language")
helper.SendLine(ctx, "java")
helper.ExpectString(ctx, "Select project type")
helper.SendLine(ctx, "Vert.x Java")
helper.ExpectString(ctx, "Select container for which you want to change configuration?")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Which starter project do you want to use")
helper.SendLine(ctx, "vertx-cache-example-redhat")
helper.ExpectString(ctx, "Enter component name")
helper.SendLine(ctx, "my-app")
helper.ExpectString(ctx, "Your new component 'my-app' is ready in the current directory")
})
Expect(err).To(BeNil())
Expect(output).To(ContainSubstring("Downloading starter project \"vertx-cache-example-redhat\""))
})
Describe("displaying welcoming messages", func() {
// testFunc is a function that returns a `Tester` function (intended to be used via `helper.RunInteractive`),
// which first expects all messages in `welcomingMsgs` to be read from the console,
// then runs an `additionalTester` and finally expects the asking of a component name
// (based on the `language` specified)
testFunc := func(language string, welcomingMsgs []string, additionalTester helper.Tester) helper.Tester {
return func(ctx helper.InteractiveContext) {
for _, msg := range welcomingMsgs {
helper.ExpectString(ctx, msg)
}
if additionalTester != nil {
additionalTester(ctx)
}
helper.ExpectString(ctx, "Enter component name")
helper.SendLine(ctx, fmt.Sprintf("my-%s-app", language))
helper.ExpectString(ctx,
fmt.Sprintf("Your new component 'my-%s-app' is ready in the current directory", language))
}
}
assertBehavior := func(language string, output string, err error, msgs []string, additionalAsserter func()) {
Expect(err).To(BeNil())
lines, err := helper.ExtractLines(output)
if err != nil {
log.Fatal(err)
}
Expect(len(lines)).To(BeNumerically(">", len(msgs)))
Expect(lines[0:len(msgs)]).To(Equal(msgs))
Expect(lines).To(
ContainElement(fmt.Sprintf("Your new component 'my-%s-app' is ready in the current directory", strings.ToLower(language))))
Expect(helper.ListFilesInDir(commonVar.Context)).To(ContainElements("devfile.yaml"))
if additionalAsserter != nil {
additionalAsserter()
}
}
testRunner := func(language string, welcomingMsgs []string, tester helper.Tester) (string, error) {
command := []string{"odo", "init"}
return helper.RunInteractive(command,
// Setting verbosity level to 0, because we would be asserting the welcoming message is the first
// message displayed to the end user. So we do not want any potential debug lines to be printed first.
// Using envvars here (and not via the -v flag), because of https://github.com/redhat-developer/odo/issues/5513
[]string{"ODO_LOG_LEVEL=0"},
testFunc(strings.ToLower(language), welcomingMsgs, tester))
}
When("directory is empty", func() {
BeforeEach(func() {
Expect(helper.ListFilesInDir(commonVar.Context)).To(HaveLen(0))
})
It("should display appropriate welcoming messages", func() {
if os.Getenv("SKIP_WELCOMING_MESSAGES") == "true" {
Skip("This is a Unix specific scenario, skipping")
}
language := "java"
// The first output is welcoming message / paragraph / banner output
welcomingMsgs := strings.Split(odolog.Stitle(messages.InitializingNewComponent, messages.NoSourceCodeDetected, "odo version: "+version.VERSION), "\n")
output, err := testRunner(language, welcomingMsgs, func(ctx helper.InteractiveContext) {
helper.ExpectString(ctx, "Select language") helper.ExpectString(ctx, "Select language")
helper.SendLine(ctx, language) helper.SendLine(ctx, "Go")
helper.ExpectString(ctx, "Select project type") helper.ExpectString(ctx, "Select project type")
helper.SendLine(ctx, "") helper.SendLine(ctx, "")
@@ -290,125 +66,32 @@ var _ = Describe("odo init interactive command tests", Label(helper.LabelNoClust
helper.ExpectString(ctx, "Which starter project do you want to use") helper.ExpectString(ctx, "Which starter project do you want to use")
helper.SendLine(ctx, "") helper.SendLine(ctx, "")
})
assertBehavior(strings.ToLower(language), output, err, welcomingMsgs, nil)
})
})
When("directory is not empty", func() {
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "python"), commonVar.Context)
Expect(helper.ListFilesInDir(commonVar.Context)).To(
SatisfyAll(
HaveLen(2),
ContainElements("requirements.txt", "wsgi.py")))
})
It("should display appropriate welcoming messages", func() {
if os.Getenv("SKIP_WELCOMING_MESSAGES") == "true" {
Skip("This is a Unix specific scenario, skipping")
}
language := "Python"
projectType := "Python"
devfileName := "python"
welcomingMsgs := strings.Split(odolog.Stitle(messages.InitializingNewComponent, messages.SourceCodeDetected, "odo version: "+version.VERSION), "\n")
output, err := testRunner(language, welcomingMsgs, func(ctx helper.InteractiveContext) {
helper.ExpectString(ctx, "Based on the files in the current directory odo detected")
helper.ExpectString(ctx, fmt.Sprintf("Language: %s", language))
helper.ExpectString(ctx, fmt.Sprintf("Project type: %s", projectType))
helper.ExpectString(ctx,
fmt.Sprintf("The devfile \"%s\" from the registry \"DefaultDevfileRegistry\" will be downloaded.", devfileName))
helper.ExpectString(ctx, "Is this correct")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Select container for which you want to change configuration")
helper.SendLine(ctx, "")
})
assertBehavior(strings.ToLower(language), output, err, welcomingMsgs, func() {
// Make sure the original source code files are still present
Expect(helper.ListFilesInDir(commonVar.Context)).To(
SatisfyAll(
HaveLen(4),
ContainElements("devfile.yaml", "requirements.txt", "wsgi.py", util.DotOdoDirectory)))
})
})
})
When("alizer detection of javascript name", func() {
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
Expect(helper.ListFilesInDir(commonVar.Context)).To(
SatisfyAll(
HaveLen(3),
ContainElements("Dockerfile", "package.json", "server.js")))
})
It("should display node-echo name", func() {
language := "JavaScript"
projectType := "Node.js"
projectName := "node-echo"
devfileName := "nodejs"
output, err := helper.RunInteractive([]string{"odo", "init"}, nil, func(ctx helper.InteractiveContext) {
helper.ExpectString(ctx, "Based on the files in the current directory odo detected")
helper.ExpectString(ctx, fmt.Sprintf("Language: %s", language))
helper.ExpectString(ctx, fmt.Sprintf("Project type: %s", projectType))
helper.ExpectString(ctx,
fmt.Sprintf("The devfile \"%s\" from the registry \"DefaultDevfileRegistry\" will be downloaded.", devfileName))
helper.ExpectString(ctx, "Is this correct")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Select container for which you want to change configuration")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Enter component name") helper.ExpectString(ctx, "Enter component name")
helper.SendLine(ctx, "") helper.SendLine(ctx, "my-go-app")
helper.ExpectString(ctx, "Your new component 'my-go-app' is ready in the current directory")
helper.ExpectString(ctx, fmt.Sprintf("Your new component '%s' is ready in the current directory", projectName))
}) })
Expect(err).To(BeNil()) Expect(err).To(BeNil())
Expect(output).To(ContainSubstring("Your new component 'my-go-app' is ready in the current directory"))
lines, err := helper.ExtractLines(output) Expect(helper.ListFilesInDir(commonVar.Context)).To(ContainElements("devfile.yaml"))
Expect(err).To(BeNil())
Expect(len(lines)).To(BeNumerically(">", 2))
Expect(lines[len(lines)-1]).To(Equal(fmt.Sprintf("Your new component '%s' is ready in the current directory", projectName)))
}) })
It("should ask to re-enter the component name if invalid value is passed by the user", func() {
language := "JavaScript"
projectType := "Node.js"
projectName := "node-echo"
devfileName := "nodejs"
_, err := helper.RunInteractive([]string{"odo", "init"}, nil, func(ctx helper.InteractiveContext) { It("should ask to re-enter the component name when an invalid value is passed", func() {
helper.ExpectString(ctx, "Based on the files in the current directory odo detected") command := []string{"odo", "init"}
_, err := helper.RunInteractive(command, nil, func(ctx helper.InteractiveContext) {
helper.ExpectString(ctx, fmt.Sprintf("Language: %s", language)) helper.ExpectString(ctx, "Select language")
helper.SendLine(ctx, "Go")
helper.ExpectString(ctx, fmt.Sprintf("Project type: %s", projectType)) helper.ExpectString(ctx, "Select project type")
helper.ExpectString(ctx,
fmt.Sprintf("The devfile \"%s\" from the registry \"DefaultDevfileRegistry\" will be downloaded.", devfileName))
helper.ExpectString(ctx, "Is this correct")
helper.SendLine(ctx, "") helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Select container for which you want to change configuration") helper.ExpectString(ctx, "Select container for which you want to change configuration?")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Which starter project do you want to use")
helper.SendLine(ctx, "") helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Enter component name") helper.ExpectString(ctx, "Enter component name")
@@ -417,104 +100,427 @@ var _ = Describe("odo init interactive command tests", Label(helper.LabelNoClust
helper.ExpectString(ctx, "name \"myapp-<script>alert('Injected!');</script>\" is not valid, name should conform the following requirements") helper.ExpectString(ctx, "name \"myapp-<script>alert('Injected!');</script>\" is not valid, name should conform the following requirements")
helper.ExpectString(ctx, "Enter component name") helper.ExpectString(ctx, "Enter component name")
helper.SendLine(ctx, "") helper.SendLine(ctx, "my-go-app")
helper.ExpectString(ctx, fmt.Sprintf("Your new component '%s' is ready in the current directory", projectName)) helper.ExpectString(ctx, "Your new component 'my-go-app' is ready in the current directory")
}) })
Expect(err).To(BeNil()) Expect(err).To(BeNil())
Expect(helper.ListFilesInDir(commonVar.Context)).To(ContainElements("devfile.yaml")) Expect(helper.ListFilesInDir(commonVar.Context)).To(ContainElements("devfile.yaml"))
}) })
})
})
It("should start downloading starter project only after all interactive questions have been asked", func() { It("should print automation command with proper values", func() {
output, err := helper.RunInteractive([]string{"odo", "init"}, nil, func(ctx helper.InteractiveContext) { // This test fails on Windows because of terminal emulator behaviour
if os.Getenv("SKIP_WELCOMING_MESSAGES") == "true" {
Skip("This is a Unix specific scenario, skipping")
}
helper.ExpectString(ctx, "Select language") command := []string{"odo", "init"}
helper.SendLine(ctx, ".NET") starter := "go-starter"
componentName := "my-go-app"
devfileName := "go"
helper.ExpectString(ctx, "Select project type") output, err := helper.RunInteractive(command, nil, func(ctx helper.InteractiveContext) {
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Select container for which you want to change configuration?") helper.ExpectString(ctx, "Select language")
helper.SendLine(ctx, "") helper.SendLine(ctx, "Go")
helper.ExpectString(ctx, "Which starter project do you want to use") helper.ExpectString(ctx, "Select project type")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Enter component name")
helper.SendLine(ctx, "my-dotnet-app")
helper.ExpectString(ctx, "Your new component 'my-dotnet-app' is ready in the current directory")
})
Expect(err).To(BeNil())
lines, err := helper.ExtractLines(output)
Expect(err).To(BeNil())
Expect(len(lines)).To(BeNumerically(">", 2))
Expect(lines[len(lines)-1]).To(Equal("Your new component 'my-dotnet-app' is ready in the current directory"))
componentNameQuestionIdx, ok := helper.FindFirstElementIndexMatchingRegExp(lines, ".*Enter component name:.*")
Expect(ok).To(BeTrue())
starterProjectDownloadActionIdx, found := helper.FindFirstElementIndexMatchingRegExp(lines,
".*Downloading starter project \"([^\\s]+)\" \\[.*")
Expect(found).To(BeTrue())
Expect(starterProjectDownloadActionIdx).To(SatisfyAll(
Not(BeZero()),
// #5495: component name question should be displayed before starter project is actually downloaded
BeNumerically(">", componentNameQuestionIdx),
), "Action 'Downloading starter project' should have been displayed after the last interactive question ('Enter component name')")
Expect(helper.ListFilesInDir(commonVar.Context)).To(ContainElements("devfile.yaml"))
})
Context("Automatic port detection via Alizer", func() {
When("starting with an existing project", func() {
const appPort = 34567
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.ReplaceString(filepath.Join(commonVar.Context, "Dockerfile"), "EXPOSE 8080", fmt.Sprintf("EXPOSE %d", appPort))
})
It("should display ports detected", func() {
_, err := helper.RunInteractive([]string{"odo", "init"}, nil, func(ctx helper.InteractiveContext) {
helper.ExpectString(ctx, fmt.Sprintf("Application ports: %d", appPort))
helper.SendLine(ctx, "Is this correct")
helper.SendLine(ctx, "") helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Select container for which you want to change configuration") helper.ExpectString(ctx, "Select container for which you want to change configuration?")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Which starter project do you want to use")
helper.SendLine(ctx, starter)
helper.ExpectString(ctx, "Enter component name")
helper.SendLine(ctx, componentName)
helper.ExpectString(ctx, "Your new component 'my-go-app' is ready in the current directory")
})
Expect(err).To(BeNil())
Expect(output).To(ContainSubstring("odo init --name %s --devfile %s --devfile-registry DefaultDevfileRegistry --starter %s", componentName, devfileName, starter))
Expect(output).To(ContainSubstring("Your new component 'my-go-app' is ready in the current directory"))
Expect(helper.ListFilesInDir(commonVar.Context)).To(ContainElements("devfile.yaml"))
})
It("should download correct devfile", func() {
command := []string{"odo", "init"}
output, err := helper.RunInteractive(command, nil, func(ctx helper.InteractiveContext) {
By("showing the interactive mode notice message", func() {
helper.ExpectString(ctx, messages.InteractiveModeEnabled)
})
helper.ExpectString(ctx, "Select language")
helper.SendLine(ctx, "Go")
helper.ExpectString(ctx, "Select project type")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Select container for which you want to change configuration?")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Which starter project do you want to use")
helper.SendLine(ctx, "") helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Enter component name") helper.ExpectString(ctx, "Enter component name")
helper.SendLine(ctx, "my-nodejs-app-with-port-detected") helper.SendLine(ctx, "my-go-app")
helper.ExpectString(ctx, "Your new component 'my-go-app' is ready in the current directory")
helper.ExpectString(ctx, "Your new component 'my-nodejs-app-with-port-detected' is ready in the current directory")
}) })
Expect(err).ShouldNot(HaveOccurred())
// Now make sure the Devfile contains a single container component with the right endpoint Expect(err).To(BeNil())
d, err := parser.ParseDevfile(parser.ParserArgs{Path: filepath.Join(commonVar.Context, "devfile.yaml"), FlattenedDevfile: pointer.BoolPtr(false)}) Expect(output).To(ContainSubstring("Your new component 'my-go-app' is ready in the current directory"))
Expect(err).ShouldNot(HaveOccurred()) Expect(helper.ListFilesInDir(commonVar.Context)).To(ContainElements("devfile.yaml"))
})
containerComponents, err := d.Data.GetDevfileContainerComponents(common.DevfileOptions{}) It("should download correct devfile-starter", func() {
Expect(err).ShouldNot(HaveOccurred())
allPortsExtracter := func(comps []v1alpha2.Component) []int { command := []string{"odo", "init"}
var ports []int output, err := helper.RunInteractive(command, nil, func(ctx helper.InteractiveContext) {
for _, c := range comps {
for _, ep := range c.Container.Endpoints { By("showing the interactive mode notice message", func() {
ports = append(ports, ep.TargetPort) helper.ExpectString(ctx, messages.InteractiveModeEnabled)
})
helper.ExpectString(ctx, "Select language")
helper.SendLine(ctx, "java")
helper.ExpectString(ctx, "Select project type")
helper.SendLine(ctx, "Vert.x Java")
helper.ExpectString(ctx, "Select container for which you want to change configuration?")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Which starter project do you want to use")
helper.SendLine(ctx, "vertx-cache-example-redhat")
helper.ExpectString(ctx, "Enter component name")
helper.SendLine(ctx, "my-app")
helper.ExpectString(ctx, "Your new component 'my-app' is ready in the current directory")
})
Expect(err).To(BeNil())
Expect(output).To(ContainSubstring("Downloading starter project \"vertx-cache-example-redhat\""))
})
Describe("displaying welcoming messages", func() {
// testFunc is a function that returns a `Tester` function (intended to be used via `helper.RunInteractive`),
// which first expects all messages in `welcomingMsgs` to be read from the console,
// then runs an `additionalTester` and finally expects the asking of a component name
// (based on the `language` specified)
testFunc := func(language string, welcomingMsgs []string, additionalTester helper.Tester) helper.Tester {
return func(ctx helper.InteractiveContext) {
for _, msg := range welcomingMsgs {
helper.ExpectString(ctx, msg)
} }
if additionalTester != nil {
additionalTester(ctx)
}
helper.ExpectString(ctx, "Enter component name")
helper.SendLine(ctx, fmt.Sprintf("my-%s-app", language))
helper.ExpectString(ctx,
fmt.Sprintf("Your new component 'my-%s-app' is ready in the current directory", language))
} }
return ports
} }
Expect(containerComponents).Should(WithTransform(allPortsExtracter, ContainElements(appPort)))
assertBehavior := func(language string, output string, err error, msgs []string, additionalAsserter func()) {
Expect(err).To(BeNil())
lines, err := helper.ExtractLines(output)
if err != nil {
log.Fatal(err)
}
Expect(len(lines)).To(BeNumerically(">", len(msgs)))
Expect(lines[0:len(msgs)]).To(Equal(msgs))
Expect(lines).To(
ContainElement(fmt.Sprintf("Your new component 'my-%s-app' is ready in the current directory", strings.ToLower(language))))
Expect(helper.ListFilesInDir(commonVar.Context)).To(ContainElements("devfile.yaml"))
if additionalAsserter != nil {
additionalAsserter()
}
}
testRunner := func(language string, welcomingMsgs []string, tester helper.Tester) (string, error) {
command := []string{"odo", "init"}
return helper.RunInteractive(command,
// Setting verbosity level to 0, because we would be asserting the welcoming message is the first
// message displayed to the end user. So we do not want any potential debug lines to be printed first.
// Using envvars here (and not via the -v flag), because of https://github.com/redhat-developer/odo/issues/5513
[]string{"ODO_LOG_LEVEL=0"},
testFunc(strings.ToLower(language), welcomingMsgs, tester))
}
When("directory is empty", func() {
BeforeEach(func() {
Expect(helper.ListFilesInDir(commonVar.Context)).To(HaveLen(0))
})
It("should display appropriate welcoming messages", func() {
if os.Getenv("SKIP_WELCOMING_MESSAGES") == "true" {
Skip("This is a Unix specific scenario, skipping")
}
language := "java"
// The first output is welcoming message / paragraph / banner output
welcomingMsgs := strings.Split(odolog.Stitle(messages.InitializingNewComponent, messages.NoSourceCodeDetected, "odo version: "+version.VERSION), "\n")
output, err := testRunner(language, welcomingMsgs, func(ctx helper.InteractiveContext) {
helper.ExpectString(ctx, "Select language")
helper.SendLine(ctx, language)
helper.ExpectString(ctx, "Select project type")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Select container for which you want to change configuration?")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Which starter project do you want to use")
helper.SendLine(ctx, "")
})
assertBehavior(strings.ToLower(language), output, err, welcomingMsgs, nil)
})
})
When("directory is not empty", func() {
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "python"), commonVar.Context)
Expect(helper.ListFilesInDir(commonVar.Context)).To(
SatisfyAll(
HaveLen(2),
ContainElements("requirements.txt", "wsgi.py")))
})
It("should display appropriate welcoming messages", func() {
if os.Getenv("SKIP_WELCOMING_MESSAGES") == "true" {
Skip("This is a Unix specific scenario, skipping")
}
language := "Python"
projectType := "Python"
devfileName := "python"
welcomingMsgs := strings.Split(odolog.Stitle(messages.InitializingNewComponent, messages.SourceCodeDetected, "odo version: "+version.VERSION), "\n")
output, err := testRunner(language, welcomingMsgs, func(ctx helper.InteractiveContext) {
helper.ExpectString(ctx, "Based on the files in the current directory odo detected")
helper.ExpectString(ctx, fmt.Sprintf("Language: %s", language))
helper.ExpectString(ctx, fmt.Sprintf("Project type: %s", projectType))
helper.ExpectString(ctx,
fmt.Sprintf("The devfile \"%s\" from the registry \"DefaultDevfileRegistry\" will be downloaded.", devfileName))
helper.ExpectString(ctx, "Is this correct")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Select container for which you want to change configuration")
helper.SendLine(ctx, "")
})
assertBehavior(strings.ToLower(language), output, err, welcomingMsgs, func() {
// Make sure the original source code files are still present
Expect(helper.ListFilesInDir(commonVar.Context)).To(
SatisfyAll(
HaveLen(4),
ContainElements("devfile.yaml", "requirements.txt", "wsgi.py", util.DotOdoDirectory)))
})
})
})
When("alizer detection of javascript name", func() {
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
Expect(helper.ListFilesInDir(commonVar.Context)).To(
SatisfyAll(
HaveLen(3),
ContainElements("Dockerfile", "package.json", "server.js")))
})
It("should display node-echo name", func() {
language := "JavaScript"
projectType := "Node.js"
projectName := "node-echo"
devfileName := "nodejs"
output, err := helper.RunInteractive([]string{"odo", "init"}, nil, func(ctx helper.InteractiveContext) {
helper.ExpectString(ctx, "Based on the files in the current directory odo detected")
helper.ExpectString(ctx, fmt.Sprintf("Language: %s", language))
helper.ExpectString(ctx, fmt.Sprintf("Project type: %s", projectType))
helper.ExpectString(ctx,
fmt.Sprintf("The devfile \"%s\" from the registry \"DefaultDevfileRegistry\" will be downloaded.", devfileName))
helper.ExpectString(ctx, "Is this correct")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Select container for which you want to change configuration")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Enter component name")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, fmt.Sprintf("Your new component '%s' is ready in the current directory", projectName))
})
Expect(err).To(BeNil())
lines, err := helper.ExtractLines(output)
Expect(err).To(BeNil())
Expect(len(lines)).To(BeNumerically(">", 2))
Expect(lines[len(lines)-1]).To(Equal(fmt.Sprintf("Your new component '%s' is ready in the current directory", projectName)))
})
It("should ask to re-enter the component name if invalid value is passed by the user", func() {
language := "JavaScript"
projectType := "Node.js"
projectName := "node-echo"
devfileName := "nodejs"
_, err := helper.RunInteractive([]string{"odo", "init"}, nil, func(ctx helper.InteractiveContext) {
helper.ExpectString(ctx, "Based on the files in the current directory odo detected")
helper.ExpectString(ctx, fmt.Sprintf("Language: %s", language))
helper.ExpectString(ctx, fmt.Sprintf("Project type: %s", projectType))
helper.ExpectString(ctx,
fmt.Sprintf("The devfile \"%s\" from the registry \"DefaultDevfileRegistry\" will be downloaded.", devfileName))
helper.ExpectString(ctx, "Is this correct")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Select container for which you want to change configuration")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Enter component name")
helper.SendLine(ctx, "myapp-<script>alert('Injected!');</script>")
helper.ExpectString(ctx, "name \"myapp-<script>alert('Injected!');</script>\" is not valid, name should conform the following requirements")
helper.ExpectString(ctx, "Enter component name")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, fmt.Sprintf("Your new component '%s' is ready in the current directory", projectName))
})
Expect(err).To(BeNil())
Expect(helper.ListFilesInDir(commonVar.Context)).To(ContainElements("devfile.yaml"))
})
})
})
It("should start downloading starter project only after all interactive questions have been asked", func() {
output, err := helper.RunInteractive([]string{"odo", "init"}, nil, func(ctx helper.InteractiveContext) {
helper.ExpectString(ctx, "Select language")
helper.SendLine(ctx, ".NET")
helper.ExpectString(ctx, "Select project type")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Select container for which you want to change configuration?")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Which starter project do you want to use")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Enter component name")
helper.SendLine(ctx, "my-dotnet-app")
helper.ExpectString(ctx, "Your new component 'my-dotnet-app' is ready in the current directory")
})
Expect(err).To(BeNil())
lines, err := helper.ExtractLines(output)
Expect(err).To(BeNil())
Expect(len(lines)).To(BeNumerically(">", 2))
Expect(lines[len(lines)-1]).To(Equal("Your new component 'my-dotnet-app' is ready in the current directory"))
componentNameQuestionIdx, ok := helper.FindFirstElementIndexMatchingRegExp(lines, ".*Enter component name:.*")
Expect(ok).To(BeTrue())
starterProjectDownloadActionIdx, found := helper.FindFirstElementIndexMatchingRegExp(lines,
".*Downloading starter project \"([^\\s]+)\" \\[.*")
Expect(found).To(BeTrue())
Expect(starterProjectDownloadActionIdx).To(SatisfyAll(
Not(BeZero()),
// #5495: component name question should be displayed before starter project is actually downloaded
BeNumerically(">", componentNameQuestionIdx),
), "Action 'Downloading starter project' should have been displayed after the last interactive question ('Enter component name')")
Expect(helper.ListFilesInDir(commonVar.Context)).To(ContainElements("devfile.yaml"))
})
Context("Automatic port detection via Alizer", func() {
When("starting with an existing project", func() {
const appPort = 34567
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.ReplaceString(filepath.Join(commonVar.Context, "Dockerfile"), "EXPOSE 8080", fmt.Sprintf("EXPOSE %d", appPort))
})
It("should display ports detected", func() {
_, err := helper.RunInteractive([]string{"odo", "init"}, nil, func(ctx helper.InteractiveContext) {
helper.ExpectString(ctx, fmt.Sprintf("Application ports: %d", appPort))
helper.SendLine(ctx, "Is this correct")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Select container for which you want to change configuration")
helper.SendLine(ctx, "")
helper.ExpectString(ctx, "Enter component name")
helper.SendLine(ctx, "my-nodejs-app-with-port-detected")
helper.ExpectString(ctx, "Your new component 'my-nodejs-app-with-port-detected' is ready in the current directory")
})
Expect(err).ShouldNot(HaveOccurred())
// Now make sure the Devfile contains a single container component with the right endpoint
d, err := parser.ParseDevfile(parser.ParserArgs{Path: filepath.Join(commonVar.Context, "devfile.yaml"), FlattenedDevfile: pointer.BoolPtr(false)})
Expect(err).ShouldNot(HaveOccurred())
containerComponents, err := d.Data.GetDevfileContainerComponents(common.DevfileOptions{})
Expect(err).ShouldNot(HaveOccurred())
allPortsExtracter := func(comps []v1alpha2.Component) []int {
var ports []int
for _, c := range comps {
for _, ep := range c.Container.Endpoints {
ports = append(ports, ep.TargetPort)
}
}
return ports
}
Expect(containerComponents).Should(WithTransform(allPortsExtracter, ContainElements(appPort)))
})
})
}) })
}) })
}) }
}) })