Make sure a Deploy command is present in the Devfile before auto-applying components (#7093)

* Add integration test case highlighting the issue

* Make sure a Deploy command is present in the Devfile before auto-applying components

* Fix expected output in 'odo deploy' interactive tests
This commit is contained in:
Armel Soro
2023-09-20 14:06:56 +02:00
committed by GitHub
parent 9e1698bc99
commit 1ab0178cef
4 changed files with 331 additions and 146 deletions

View File

@@ -39,6 +39,11 @@ func (o *DeployClient) Deploy(ctx context.Context) error {
path = filepath.Dir(devfilePath)
)
_, err := libdevfile.ValidateAndGetCommand(*devfileObj, "", v1alpha2.DeployCommandGroupKind)
if err != nil {
return err
}
handler := component.NewRunHandler(
ctx,
o.kubeClient,
@@ -52,7 +57,7 @@ func (o *DeployClient) Deploy(ctx context.Context) error {
},
)
err := o.buildPushAutoImageComponents(handler, *devfileObj)
err = o.buildPushAutoImageComponents(handler, *devfileObj)
if err != nil {
return err
}

View File

@@ -0,0 +1,151 @@
commands:
- exec:
commandLine: npm install
component: runtime
group:
isDefault: true
kind: build
workingDir: ${PROJECT_SOURCE}
id: build
- exec:
commandLine: npm run start
component: runtime
group:
isDefault: true
kind: run
workingDir: ${PROJECT_SOURCE}
id: start-app
- exec:
commandLine: npm run debug
component: runtime
group:
isDefault: true
kind: debug
workingDir: ${PROJECT_SOURCE}
id: start-app-debug
components:
- container:
command: [ 'tail' ]
args: [ '-f', '/dev/null' ]
endpoints:
- name: "3000-tcp"
targetPort: 3000
- name: "debug"
targetPort: 5858
exposure: none
env:
- name: DEBUG_PORT_PROJECT
value: "5858"
image: registry.access.redhat.com/ubi8/nodejs-12:1-36
memoryLimit: 1024Mi
mountSources: true
name: runtime
#######################
# Kubernetes components
#######################
# deployByDefault true, not referenced in apply command => automatically created on startup
- kubernetes:
deployByDefault: true
inlined: |
apiVersion: v1
kind: Pod
metadata:
name: k8s-deploybydefault-true-and-not-referenced
spec:
containers:
- name: main
image: busybox
command: ["/bin/sh", "-ec", "while :; do echo '.'; sleep 5 ; done"]
name: k8s-deploybydefault-true-and-not-referenced
# deployByDefault not set, not referenced in apply command => automatically created on startup
- kubernetes:
inlined: |
apiVersion: v1
kind: Pod
metadata:
name: k8s-deploybydefault-not-set-and-not-referenced
spec:
containers:
- name: main
image: busybox
command: ["/bin/sh", "-ec", "while :; do echo '.'; sleep 5 ; done"]
name: k8s-deploybydefault-not-set-and-not-referenced
#######################
# OpenShift components
#######################
# deployByDefault true, not referenced in apply command => automatically created on startup
- openshift:
deployByDefault: true
inlined: |
apiVersion: v1
kind: Pod
metadata:
name: ocp-deploybydefault-true-and-not-referenced
spec:
containers:
- name: main
image: busybox
command: ["/bin/sh", "-ec", "while :; do echo '.'; sleep 5 ; done"]
name: ocp-deploybydefault-true-and-not-referenced
# deployByDefault not set, not referenced in apply command => automatically created on startup
- openshift:
inlined: |
apiVersion: v1
kind: Pod
metadata:
name: ocp-deploybydefault-not-set-and-not-referenced
spec:
containers:
- name: main
image: busybox
command: ["/bin/sh", "-ec", "while :; do echo '.'; sleep 5 ; done"]
name: ocp-deploybydefault-not-set-and-not-referenced
#######################
# Image components
#######################
# autoBuild true, not referenced in apply command => automatically created on startup
- image:
autoBuild: true
dockerfile:
buildContext: .
uri: Dockerfile
imageName: "{{ CONTAINER_IMAGE_REPO }}:autobuild-true-and-not-referenced"
name: autobuild-true-and-not-referenced
# autoBuild not set, not referenced in apply command => automatically created on startup
- image:
dockerfile:
buildContext: .
uri: Dockerfile
imageName: "{{ CONTAINER_IMAGE_REPO }}:autobuild-not-set-and-not-referenced"
name: autobuild-not-set-and-not-referenced
metadata:
description: Stack with Node.js 14
displayName: Node.js Runtime
icon: https://nodejs.org/static/images/logos/nodejs-new-pantone-black.svg
language: javascript
name: my-node-app
projectType: nodejs
tags:
- NodeJS
- Express
- ubi8
version: 1.0.0
schemaVersion: 2.2.0
starterProjects:
- git:
remotes:
origin: https://github.com/odo-devfiles/nodejs-ex.git
name: nodejs-starter
variables:
CONTAINER_IMAGE_REPO: localhost:5000/odo-dev/node

View File

@@ -705,165 +705,194 @@ CMD ["npm", "start"]
})
// More details on https://github.com/devfile/api/issues/852#issuecomment-1211928487
When("starting with Devfile with autoBuild or deployByDefault components", func() {
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile-autobuild-deploybydefault.yaml"),
filepath.Join(commonVar.Context, "devfile.yaml"),
cmpName)
})
When("running odo deploy with some components not referenced in the Devfile", func() {
var stdout string
Context("Devfile with autoBuild or deployByDefault components", func() {
When("starting with Devfile with Deploy commands", func() {
BeforeEach(func() {
stdout = helper.Cmd("odo", "deploy").AddEnv("PODMAN_CMD=echo").ShouldPass().Out()
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile-autobuild-deploybydefault.yaml"),
filepath.Join(commonVar.Context, "devfile.yaml"),
cmpName)
})
It("should create the appropriate resources", func() {
By("automatically applying Kubernetes/OpenShift components with deployByDefault=true", func() {
for _, l := range []string{
"k8s-deploybydefault-true-and-referenced",
"k8s-deploybydefault-true-and-not-referenced",
"ocp-deploybydefault-true-and-referenced",
"ocp-deploybydefault-true-and-not-referenced",
} {
Expect(stdout).Should(ContainSubstring("Creating resource Pod/%s", l))
}
})
By("automatically applying non-referenced Kubernetes/OpenShift components with deployByDefault not set", func() {
for _, l := range []string{
"k8s-deploybydefault-not-set-and-not-referenced",
"ocp-deploybydefault-not-set-and-not-referenced",
} {
Expect(stdout).Should(ContainSubstring("Creating resource Pod/%s", l))
}
})
By("not applying Kubernetes/OpenShift components with deployByDefault=false", func() {
for _, l := range []string{
"k8s-deploybydefault-false-and-referenced",
"k8s-deploybydefault-false-and-not-referenced",
"ocp-deploybydefault-false-and-referenced",
"ocp-deploybydefault-false-and-not-referenced",
} {
Expect(stdout).ShouldNot(ContainSubstring("Creating resource Pod/%s", l))
}
})
By("not applying referenced Kubernetes/OpenShift components with deployByDefault unset", func() {
Expect(stdout).ShouldNot(ContainSubstring("Creating resource Pod/k8s-deploybydefault-not-set-and-referenced"))
When("running odo deploy with some components not referenced in the Devfile", func() {
var stdout string
BeforeEach(func() {
stdout = helper.Cmd("odo", "deploy").AddEnv("PODMAN_CMD=echo").ShouldPass().Out()
})
By("automatically applying image components with autoBuild=true", func() {
for _, tag := range []string{
"autobuild-true-and-referenced",
"autobuild-true-and-not-referenced",
} {
Expect(stdout).Should(ContainSubstring("Building & Pushing Image: localhost:5000/odo-dev/node:%s", tag))
}
})
By("automatically applying non-referenced Image components with autoBuild not set", func() {
Expect(stdout).Should(ContainSubstring("Building & Pushing Image: localhost:5000/odo-dev/node:autobuild-not-set-and-not-referenced"))
})
By("not applying image components with autoBuild=false", func() {
for _, tag := range []string{
"autobuild-false-and-referenced",
"autobuild-false-and-not-referenced",
} {
Expect(stdout).ShouldNot(ContainSubstring("localhost:5000/odo-dev/node:%s", tag))
}
})
By("not applying referenced Image components with deployByDefault unset", func() {
Expect(stdout).ShouldNot(ContainSubstring("localhost:5000/odo-dev/node:autobuild-not-set-and-referenced"))
It("should create the appropriate resources", func() {
By("automatically applying Kubernetes/OpenShift components with deployByDefault=true", func() {
for _, l := range []string{
"k8s-deploybydefault-true-and-referenced",
"k8s-deploybydefault-true-and-not-referenced",
"ocp-deploybydefault-true-and-referenced",
"ocp-deploybydefault-true-and-not-referenced",
} {
Expect(stdout).Should(ContainSubstring("Creating resource Pod/%s", l))
}
})
By("automatically applying non-referenced Kubernetes/OpenShift components with deployByDefault not set", func() {
for _, l := range []string{
"k8s-deploybydefault-not-set-and-not-referenced",
"ocp-deploybydefault-not-set-and-not-referenced",
} {
Expect(stdout).Should(ContainSubstring("Creating resource Pod/%s", l))
}
})
By("not applying Kubernetes/OpenShift components with deployByDefault=false", func() {
for _, l := range []string{
"k8s-deploybydefault-false-and-referenced",
"k8s-deploybydefault-false-and-not-referenced",
"ocp-deploybydefault-false-and-referenced",
"ocp-deploybydefault-false-and-not-referenced",
} {
Expect(stdout).ShouldNot(ContainSubstring("Creating resource Pod/%s", l))
}
})
By("not applying referenced Kubernetes/OpenShift components with deployByDefault unset", func() {
Expect(stdout).ShouldNot(ContainSubstring("Creating resource Pod/k8s-deploybydefault-not-set-and-referenced"))
})
By("automatically applying image components with autoBuild=true", func() {
for _, tag := range []string{
"autobuild-true-and-referenced",
"autobuild-true-and-not-referenced",
} {
Expect(stdout).Should(ContainSubstring("Building & Pushing Image: localhost:5000/odo-dev/node:%s", tag))
}
})
By("automatically applying non-referenced Image components with autoBuild not set", func() {
Expect(stdout).Should(ContainSubstring("Building & Pushing Image: localhost:5000/odo-dev/node:autobuild-not-set-and-not-referenced"))
})
By("not applying image components with autoBuild=false", func() {
for _, tag := range []string{
"autobuild-false-and-referenced",
"autobuild-false-and-not-referenced",
} {
Expect(stdout).ShouldNot(ContainSubstring("localhost:5000/odo-dev/node:%s", tag))
}
})
By("not applying referenced Image components with deployByDefault unset", func() {
Expect(stdout).ShouldNot(ContainSubstring("localhost:5000/odo-dev/node:autobuild-not-set-and-referenced"))
})
})
})
When("running odo deploy with some components referenced in the Devfile", func() {
var stdout string
BeforeEach(func() {
//TODO (rm3l): we do not support passing a custom deploy command yet. That's why we are manually updating the Devfile to set the default deploy command.
helper.UpdateDevfileContent(filepath.Join(commonVar.Context, "devfile.yaml"), []helper.DevfileUpdater{
helper.DevfileCommandGroupUpdater("deploy", v1alpha2.CompositeCommandType, &v1alpha2.CommandGroup{
Kind: v1alpha2.DeployCommandGroupKind,
IsDefault: pointer.Bool(false),
}),
helper.DevfileCommandGroupUpdater("deploy-with-referenced-components", v1alpha2.CompositeCommandType, &v1alpha2.CommandGroup{
Kind: v1alpha2.DeployCommandGroupKind,
IsDefault: pointer.Bool(true),
}),
})
stdout = helper.Cmd("odo", "deploy").AddEnv("PODMAN_CMD=echo").ShouldPass().Out()
})
It("should create the appropriate resources", func() {
By("applying referenced Kubernetes/OpenShift components", func() {
for _, l := range []string{
"k8s-deploybydefault-true-and-referenced",
"k8s-deploybydefault-false-and-referenced",
"k8s-deploybydefault-not-set-and-referenced",
"ocp-deploybydefault-true-and-referenced",
"ocp-deploybydefault-false-and-referenced",
"ocp-deploybydefault-not-set-and-referenced",
} {
Expect(stdout).Should(ContainSubstring("Creating resource Pod/%s", l))
}
})
By("automatically applying Kubernetes/OpenShift components with deployByDefault=true", func() {
for _, l := range []string{
"k8s-deploybydefault-true-and-referenced",
"k8s-deploybydefault-true-and-not-referenced",
"ocp-deploybydefault-true-and-referenced",
"ocp-deploybydefault-true-and-not-referenced",
} {
Expect(stdout).Should(ContainSubstring("Creating resource Pod/%s", l))
}
})
By("automatically applying non-referenced Kubernetes/OpenShift components with deployByDefault not set", func() {
for _, l := range []string{
"k8s-deploybydefault-not-set-and-not-referenced",
"ocp-deploybydefault-not-set-and-not-referenced",
} {
Expect(stdout).Should(ContainSubstring("Creating resource Pod/%s", l))
}
})
By("not applying non-referenced Kubernetes/OpenShift components with deployByDefault=false", func() {
for _, l := range []string{
"k8s-deploybydefault-false-and-not-referenced",
"ocp-deploybydefault-false-and-not-referenced",
} {
Expect(stdout).ShouldNot(ContainSubstring("Creating resource Pod/%s", l))
}
})
By("applying referenced image components", func() {
for _, tag := range []string{
"autobuild-true-and-referenced",
"autobuild-false-and-referenced",
"autobuild-not-set-and-referenced",
} {
Expect(stdout).Should(ContainSubstring("Building & Pushing Image: localhost:5000/odo-dev/node:%s", tag))
}
})
By("automatically applying image components with autoBuild=true", func() {
for _, tag := range []string{
"autobuild-true-and-referenced",
"autobuild-true-and-not-referenced",
} {
Expect(stdout).Should(ContainSubstring("Building & Pushing Image: localhost:5000/odo-dev/node:%s", tag))
}
})
By("automatically applying non-referenced Image components with autoBuild not set", func() {
Expect(stdout).Should(ContainSubstring("Building & Pushing Image: localhost:5000/odo-dev/node:autobuild-not-set-and-not-referenced"))
})
By("not applying non-referenced image components with autoBuild=false", func() {
Expect(stdout).ShouldNot(ContainSubstring("localhost:5000/odo-dev/node:autobuild-false-and-not-referenced"))
})
})
})
})
When("running odo deploy with some components referenced in the Devfile", func() {
var stdout string
When("starting with Devfile with no Deploy command", func() {
BeforeEach(func() {
//TODO (rm3l): we do not support passing a custom deploy command yet. That's why we are manually updating the Devfile to set the default deploy command.
helper.UpdateDevfileContent(filepath.Join(commonVar.Context, "devfile.yaml"), []helper.DevfileUpdater{
helper.DevfileCommandGroupUpdater("deploy", v1alpha2.CompositeCommandType, &v1alpha2.CommandGroup{
Kind: v1alpha2.DeployCommandGroupKind,
IsDefault: pointer.Bool(false),
}),
helper.DevfileCommandGroupUpdater("deploy-with-referenced-components", v1alpha2.CompositeCommandType, &v1alpha2.CommandGroup{
Kind: v1alpha2.DeployCommandGroupKind,
IsDefault: pointer.Bool(true),
}),
})
stdout = helper.Cmd("odo", "deploy").AddEnv("PODMAN_CMD=echo").ShouldPass().Out()
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile-autobuild-deploybydefault-no-deploy-cmd.yaml"),
filepath.Join(commonVar.Context, "devfile.yaml"),
cmpName)
})
It("should create the appropriate resources", func() {
By("applying referenced Kubernetes/OpenShift components", func() {
for _, l := range []string{
"k8s-deploybydefault-true-and-referenced",
"k8s-deploybydefault-false-and-referenced",
"k8s-deploybydefault-not-set-and-referenced",
"ocp-deploybydefault-true-and-referenced",
"ocp-deploybydefault-false-and-referenced",
"ocp-deploybydefault-not-set-and-referenced",
} {
Expect(stdout).Should(ContainSubstring("Creating resource Pod/%s", l))
It("should fail to run odo deploy", func() {
stdout, stderr := helper.Cmd("odo", "deploy").AddEnv("PODMAN_CMD=echo").ShouldFail().OutAndErr()
By("not automatically applying Kubernetes/OpenShift components ", func() {
for _, s := range []string{stdout, stderr} {
Expect(s).ShouldNot(ContainSubstring("Creating resource Pod/"))
}
})
By("automatically applying Kubernetes/OpenShift components with deployByDefault=true", func() {
for _, l := range []string{
"k8s-deploybydefault-true-and-referenced",
"k8s-deploybydefault-true-and-not-referenced",
"ocp-deploybydefault-true-and-referenced",
"ocp-deploybydefault-true-and-not-referenced",
} {
Expect(stdout).Should(ContainSubstring("Creating resource Pod/%s", l))
By("not automatically applying Image components ", func() {
for _, s := range []string{stdout, stderr} {
Expect(s).ShouldNot(ContainSubstring("Building & Pushing Image: localhost:5000/odo-dev/node:"))
}
})
By("automatically applying non-referenced Kubernetes/OpenShift components with deployByDefault not set", func() {
for _, l := range []string{
"k8s-deploybydefault-not-set-and-not-referenced",
"ocp-deploybydefault-not-set-and-not-referenced",
} {
Expect(stdout).Should(ContainSubstring("Creating resource Pod/%s", l))
}
})
By("not applying non-referenced Kubernetes/OpenShift components with deployByDefault=false", func() {
for _, l := range []string{
"k8s-deploybydefault-false-and-not-referenced",
"ocp-deploybydefault-false-and-not-referenced",
} {
Expect(stdout).ShouldNot(ContainSubstring("Creating resource Pod/%s", l))
}
})
By("applying referenced image components", func() {
for _, tag := range []string{
"autobuild-true-and-referenced",
"autobuild-false-and-referenced",
"autobuild-not-set-and-referenced",
} {
Expect(stdout).Should(ContainSubstring("Building & Pushing Image: localhost:5000/odo-dev/node:%s", tag))
}
})
By("automatically applying image components with autoBuild=true", func() {
for _, tag := range []string{
"autobuild-true-and-referenced",
"autobuild-true-and-not-referenced",
} {
Expect(stdout).Should(ContainSubstring("Building & Pushing Image: localhost:5000/odo-dev/node:%s", tag))
}
})
By("automatically applying non-referenced Image components with autoBuild not set", func() {
Expect(stdout).Should(ContainSubstring("Building & Pushing Image: localhost:5000/odo-dev/node:autobuild-not-set-and-not-referenced"))
})
By("not applying non-referenced image components with autoBuild=false", func() {
Expect(stdout).ShouldNot(ContainSubstring("localhost:5000/odo-dev/node:autobuild-false-and-not-referenced"))
By("displaying an error message", func() {
Expect(stderr).Should(ContainSubstring("no deploy command found in devfile"))
})
})
})
})
})

View File

@@ -64,11 +64,11 @@ var _ = Describe("odo deploy interactive command tests", func() {
helper.ExpectString(ctx, "Enter component name")
helper.SendLine(ctx, "my-app")
helper.ExpectString(ctx, "no default deploy command found in devfile")
helper.ExpectString(ctx, "no deploy command found in devfile")
})
Expect(err).To(Not(BeNil()))
Expect(output).To(ContainSubstring("no default deploy command found in devfile"))
Expect(output).To(ContainSubstring("no deploy command found in devfile"))
Expect(helper.ListFilesInDir(commonVar.Context)).To(ContainElements("devfile.yaml"))
})
@@ -98,11 +98,11 @@ var _ = Describe("odo deploy interactive command tests", func() {
helper.ExpectString(ctx, "Enter component name")
helper.SendLine(ctx, "my-app")
helper.ExpectString(ctx, "no default deploy command found in devfile")
helper.ExpectString(ctx, "no deploy command found in devfile")
})
Expect(err).To(Not(BeNil()))
Expect(output).To(ContainSubstring("no default deploy command found in devfile"))
Expect(output).To(ContainSubstring("no deploy command found in devfile"))
Expect(helper.ListFilesInDir(commonVar.Context)).To(ContainElements("devfile.yaml"))
})
@@ -139,7 +139,7 @@ var _ = Describe("odo deploy interactive command tests", func() {
helper.ExpectString(ctx, "Enter component name")
helper.SendLine(ctx, "my-app")
helper.ExpectString(ctx, "no default deploy command found in devfile")
helper.ExpectString(ctx, "no deploy command found in devfile")
})
Expect(err).To(Not(BeNil()))