From 273e38c2514c2550ad9b3b6930bc9b5e60c43319 Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Thu, 28 Apr 2022 17:59:21 +0200 Subject: [PATCH 1/7] Add integration test highlighting the issue The devfile used is the same as devfile-deploy.yaml, except that the the Kubernetes component is referenced via the URI. This is why the same integration test logic is being reused here. --- .../nodejs/devfile-deploy-with-k8s-uri.yaml | 89 +++++++++++++ .../kubernetes/outerloop-deployment.yaml | 23 ++++ .../devfile/cmd_devfile_deploy_test.go | 123 +++++++++++------- 3 files changed, 188 insertions(+), 47 deletions(-) create mode 100644 tests/examples/source/devfiles/nodejs/devfile-deploy-with-k8s-uri.yaml create mode 100644 tests/examples/source/devfiles/nodejs/project/kubernetes/outerloop-deployment.yaml diff --git a/tests/examples/source/devfiles/nodejs/devfile-deploy-with-k8s-uri.yaml b/tests/examples/source/devfiles/nodejs/devfile-deploy-with-k8s-uri.yaml new file mode 100644 index 00000000000..54eb4d90f59 --- /dev/null +++ b/tests/examples/source/devfiles/nodejs/devfile-deploy-with-k8s-uri.yaml @@ -0,0 +1,89 @@ +schemaVersion: 2.2.0 +metadata: + description: Stack with Node.js 16 + displayName: Node.js Runtime + icon: https://nodejs.org/static/images/logos/nodejs-new-pantone-black.svg + language: javascript + name: nodejs-prj1-api-abhz + projectType: nodejs + tags: + - NodeJS + - Express + - ubi8 + version: 1.0.1 + +starterProjects: + - git: + remotes: + origin: https://github.com/odo-devfiles/nodejs-ex.git + name: nodejs-starter + +variables: + CONTAINER_IMAGE: quay.io/unknown-account/myimage + +commands: +- exec: + commandLine: npm install + component: runtime + group: + isDefault: true + kind: build + workingDir: $PROJECT_SOURCE + id: install +- exec: + commandLine: npm start + component: runtime + group: + isDefault: true + kind: run + workingDir: $PROJECT_SOURCE + id: run +- exec: + commandLine: npm run debug + component: runtime + group: + isDefault: true + kind: debug + workingDir: $PROJECT_SOURCE + id: debug +- exec: + commandLine: npm test + component: runtime + group: + isDefault: true + kind: test + workingDir: $PROJECT_SOURCE + id: test +- id: build-image + apply: + component: outerloop-build +- id: deployk8s + apply: + component: outerloop-deploy +- id: deploy + composite: + commands: + - build-image + - deployk8s + group: + kind: deploy + isDefault: true + +components: +- name: runtime + container: + endpoints: + - name: http-3000 + targetPort: 3000 + image: registry.access.redhat.com/ubi8/nodejs-16-minimal:latest + memoryLimit: 1024Mi + mountSources: true + sourceMapping: $PROJECT_SOURCE +- name: outerloop-build + image: + imageName: "{{CONTAINER_IMAGE}}" + dockerfile: + uri: ./Dockerfile +- name: outerloop-deploy + kubernetes: + uri: 'kubernetes/outerloop-deployment.yaml' diff --git a/tests/examples/source/devfiles/nodejs/project/kubernetes/outerloop-deployment.yaml b/tests/examples/source/devfiles/nodejs/project/kubernetes/outerloop-deployment.yaml new file mode 100644 index 00000000000..2a155d1a780 --- /dev/null +++ b/tests/examples/source/devfiles/nodejs/project/kubernetes/outerloop-deployment.yaml @@ -0,0 +1,23 @@ +kind: Deployment +apiVersion: apps/v1 +metadata: + name: my-component +spec: + replicas: 1 + selector: + matchLabels: + app: node-app + template: + metadata: + labels: + app: node-app + spec: + containers: + - name: main + # CONTAINER_IMAGE is a variable defined in Devfile, and it needs to be substituted accordingly. + # See https://github.com/redhat-developer/odo/issues/5451 + image: {{CONTAINER_IMAGE}} + resources: + limits: + memory: "128Mi" + cpu: "500m" diff --git a/tests/integration/devfile/cmd_devfile_deploy_test.go b/tests/integration/devfile/cmd_devfile_deploy_test.go index 4e6b38a90eb..5be778a2673 100644 --- a/tests/integration/devfile/cmd_devfile_deploy_test.go +++ b/tests/integration/devfile/cmd_devfile_deploy_test.go @@ -40,68 +40,97 @@ var _ = Describe("odo devfile deploy command tests", func() { }) }) - When("using a devfile.yaml containing a deploy command", func() { - // from devfile - cmpName := "nodejs-prj1-api-abhz" - deploymentName := "my-component" - BeforeEach(func() { - helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context) - helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile-deploy.yaml"), path.Join(commonVar.Context, "devfile.yaml")) - }) + for _, ctx := range []struct { + title string + devfileName string + setupFunc func() + }{ + { + title: "using a devfile.yaml containing a deploy command", + devfileName: "devfile-deploy.yaml", + setupFunc: nil, + }, + { + title: "using a devfile.yaml containing an outer-loop Kubernetes component referenced via an URI", + devfileName: "devfile-deploy-with-k8s-uri.yaml", + setupFunc: func() { + helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project", "kubernetes"), + filepath.Join(commonVar.Context, "kubernetes")) + }, + }, + } { - When("running odo deploy", func() { - var stdout string + When(ctx.title, func() { + // from devfile + cmpName := "nodejs-prj1-api-abhz" + deploymentName := "my-component" BeforeEach(func() { - stdout = helper.Cmd("odo", "deploy").AddEnv("PODMAN_CMD=echo").ShouldPass().Out() - // An ENV file should have been created indicating current namespace - Expect(helper.VerifyFileExists(".odo/env/env.yaml")).To(BeTrue()) - helper.FileShouldContainSubstring(".odo/env/env.yaml", "Project: "+commonVar.Project) + helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context) + helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", ctx.devfileName), + path.Join(commonVar.Context, "devfile.yaml")) + if ctx.setupFunc != nil { + ctx.setupFunc() + } }) - It("should succeed", func() { - By("building and pushing image to registry", func() { - 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("running odo deploy", func() { + var stdout string + BeforeEach(func() { + stdout = helper.Cmd("odo", "deploy").AddEnv("PODMAN_CMD=echo").ShouldPass().Out() + // An ENV file should have been created indicating current namespace + Expect(helper.VerifyFileExists(".odo/env/env.yaml")).To(BeTrue()) + helper.FileShouldContainSubstring(".odo/env/env.yaml", "Project: "+commonVar.Project) }) - By("deploying a deployment with the built image", func() { - out := commonVar.CliRunner.Run("get", "deployment", deploymentName, "-n", commonVar.Project, "-o", `jsonpath="{.spec.template.spec.containers[0].image}"`).Wait().Out.Contents() - Expect(out).To(ContainSubstring("quay.io/unknown-account/myimage")) + It("should succeed", func() { + By("building and pushing image to registry", func() { + 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")) + }) + By("deploying a deployment with the built image", func() { + out := commonVar.CliRunner.Run("get", "deployment", deploymentName, "-n", + commonVar.Project, "-o", `jsonpath="{.spec.template.spec.containers[0].image}"`).Wait().Out.Contents() + Expect(out).To(ContainSubstring("quay.io/unknown-account/myimage")) + }) }) - }) - It("should run odo dev successfully", func() { - session, _, _, _, err := helper.StartDevMode() - Expect(err).ToNot(HaveOccurred()) - session.Kill() - session.WaitEnd() - }) + It("should run odo dev successfully", func() { + session, _, _, _, err := helper.StartDevMode() + Expect(err).ToNot(HaveOccurred()) + session.Kill() + session.WaitEnd() + }) - When("deleting previous deployment and switching kubeconfig to another namespace", func() { - var otherNS string - BeforeEach(func() { - helper.Cmd("odo", "delete", "component", "--name", cmpName, "-f").ShouldPass() - output := commonVar.CliRunner.Run("get", "deployment", "-n", commonVar.Project).Err.Contents() - Expect(string(output)).To(ContainSubstring("No resources found in " + commonVar.Project + " namespace.")) + When("deleting previous deployment and switching kubeconfig to another namespace", func() { + var otherNS string + BeforeEach(func() { + helper.Cmd("odo", "delete", "component", "--name", cmpName, "-f").ShouldPass() + output := commonVar.CliRunner.Run("get", "deployment", "-n", commonVar.Project).Err.Contents() + Expect(string(output)).To( + ContainSubstring("No resources found in " + commonVar.Project + " namespace.")) - otherNS = commonVar.CliRunner.CreateAndSetRandNamespaceProject() - }) + otherNS = commonVar.CliRunner.CreateAndSetRandNamespaceProject() + }) - AfterEach(func() { - commonVar.CliRunner.DeleteNamespaceProject(otherNS) - }) + AfterEach(func() { + commonVar.CliRunner.DeleteNamespaceProject(otherNS) + }) - It("should run odo deploy on initial namespace", func() { - helper.Cmd("odo", "deploy").AddEnv("PODMAN_CMD=echo").ShouldPass() + It("should run odo deploy on initial namespace", func() { + helper.Cmd("odo", "deploy").AddEnv("PODMAN_CMD=echo").ShouldPass() - output := commonVar.CliRunner.Run("get", "deployment").Err.Contents() - Expect(string(output)).To(ContainSubstring("No resources found in " + otherNS + " namespace.")) + output := commonVar.CliRunner.Run("get", "deployment").Err.Contents() + Expect(string(output)).To( + ContainSubstring("No resources found in " + otherNS + " namespace.")) - output = commonVar.CliRunner.Run("get", "deployment", "-n", commonVar.Project).Out.Contents() - Expect(string(output)).To(ContainSubstring(deploymentName)) - }) + output = commonVar.CliRunner.Run("get", "deployment", "-n", commonVar.Project).Out.Contents() + Expect(string(output)).To(ContainSubstring(deploymentName)) + }) + }) }) }) - }) + } When("using a devfile.yaml containing two deploy commands", func() { BeforeEach(func() { From e42e415012c1e9171315caedaedd7423643a7577 Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Mon, 2 May 2022 12:34:40 +0200 Subject: [PATCH 2/7] Add higher-level function in 'libdevfile' allowing to load component resource manifest and substitute variables This works with both Inlined or Uri resources. Notes: - Ideally, it would make more sense to rely on the same logic used in Devfile to substitute variables (defined in the 'variables' package), but this function is not exported; and the exported ones substitute variables only in the URI name, not in the content itself (it is not fetched), which is actually the issue we are trying to solve here. --- pkg/deploy/deploy.go | 4 +- .../adapters/kubernetes/component/adapter.go | 8 +- pkg/libdevfile/component_kubernetes_utils.go | 17 +- pkg/libdevfile/libdevfile.go | 86 ++++++ pkg/libdevfile/libdevfile_test.go | 271 ++++++++++++++++++ pkg/service/link.go | 33 +-- pkg/service/service.go | 18 +- 7 files changed, 394 insertions(+), 43 deletions(-) diff --git a/pkg/deploy/deploy.go b/pkg/deploy/deploy.go index 489d3065a91..f8cba430797 100644 --- a/pkg/deploy/deploy.go +++ b/pkg/deploy/deploy.go @@ -59,7 +59,7 @@ func (o *deployHandler) ApplyImage(img v1alpha2.Component) error { func (o *deployHandler) ApplyKubernetes(kubernetes v1alpha2.Component) error { // Validate if the GVRs represented by Kubernetes inlined components are supported by the underlying cluster - _, err := service.ValidateResourceExist(o.kubeClient, kubernetes, o.path) + _, err := service.ValidateResourceExist(o.kubeClient, o.devfileObj, kubernetes, o.path) if err != nil { return err } @@ -75,7 +75,7 @@ func (o *deployHandler) ApplyKubernetes(kubernetes v1alpha2.Component) error { odolabels.SetProjectType(annotations, component.GetComponentTypeFromDevfileMetadata(o.devfileObj.Data.GetMetadata())) // Get the Kubernetes component - u, err := libdevfile.GetK8sComponentAsUnstructured(kubernetes.Kubernetes, o.path, devfilefs.DefaultFs{}) + u, err := libdevfile.GetK8sComponentAsUnstructured(o.devfileObj, kubernetes.Kubernetes, o.path, devfilefs.DefaultFs{}) if err != nil { return err } diff --git a/pkg/devfile/adapters/kubernetes/component/adapter.go b/pkg/devfile/adapters/kubernetes/component/adapter.go index cb4ef5c6def..69acebfc0b9 100644 --- a/pkg/devfile/adapters/kubernetes/component/adapter.go +++ b/pkg/devfile/adapters/kubernetes/component/adapter.go @@ -196,13 +196,13 @@ func (a Adapter) Push(parameters common.PushParameters) (err error) { } // validate if the GVRs represented by Kubernetes inlined components are supported by the underlying cluster - err = service.ValidateResourcesExist(a.Client, k8sComponents, a.Context) + err = service.ValidateResourcesExist(a.Client, a.Devfile, k8sComponents, a.Context) if err != nil { return err } // create the Kubernetes objects from the manifest and delete the ones not in the devfile - err = service.PushKubernetesResources(a.Client, k8sComponents, labels, annotations, a.Context) + err = service.PushKubernetesResources(a.Client, a.Devfile, k8sComponents, labels, annotations, a.Context) if err != nil { return fmt.Errorf("failed to create service(s) associated with the component: %w", err) } @@ -246,14 +246,14 @@ func (a Adapter) Push(parameters common.PushParameters) (err error) { // Update all services with owner references err = a.Client.TryWithBlockOwnerDeletion(ownerReference, func(ownerRef metav1.OwnerReference) error { - return service.UpdateServicesWithOwnerReferences(a.Client, k8sComponents, ownerRef, a.Context) + return service.UpdateServicesWithOwnerReferences(a.Client, a.Devfile, k8sComponents, ownerRef, a.Context) }) if err != nil { return err } // create the Kubernetes objects from the manifest and delete the ones not in the devfile - needRestart, err := service.PushLinks(a.Client, k8sComponents, labels, a.deployment, a.Context) + needRestart, err := service.PushLinks(a.Client, a.Devfile, k8sComponents, labels, a.deployment, a.Context) if err != nil { return fmt.Errorf("failed to create service(s) associated with the component: %w", err) } diff --git a/pkg/libdevfile/component_kubernetes_utils.go b/pkg/libdevfile/component_kubernetes_utils.go index 9fded29bf00..1fba174472f 100644 --- a/pkg/libdevfile/component_kubernetes_utils.go +++ b/pkg/libdevfile/component_kubernetes_utils.go @@ -6,19 +6,16 @@ import ( "github.com/devfile/library/pkg/devfile/parser/data/v2/common" devfilefs "github.com/devfile/library/pkg/testingutil/filesystem" "github.com/ghodss/yaml" - "github.com/redhat-developer/odo/pkg/util" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) // GetK8sComponentAsUnstructured parses the Inlined/URI K8s of the devfile K8s component -func GetK8sComponentAsUnstructured(component *v1alpha2.KubernetesComponent, context string, fs devfilefs.Filesystem) (unstructured.Unstructured, error) { - strCRD := component.Inlined - var err error - if component.Uri != "" { - strCRD, err = util.GetDataFromURI(component.Uri, context, fs) - if err != nil { - return unstructured.Unstructured{}, err - } +func GetK8sComponentAsUnstructured(devfileObj parser.DevfileObj, component *v1alpha2.KubernetesComponent, + context string, fs devfilefs.Filesystem) (unstructured.Unstructured, error) { + + strCRD, err := GetComponentResourceManifestContentWithVariablesResolved(devfileObj, component, context, fs) + if err != nil { + return unstructured.Unstructured{}, err } // convert the YAML definition into map[string]interface{} since it's needed to create dynamic resource @@ -40,7 +37,7 @@ func ListKubernetesComponents(devfileObj parser.DevfileObj, path string) (list [ var u unstructured.Unstructured for _, kComponent := range components { if kComponent.Kubernetes != nil { - u, err = GetK8sComponentAsUnstructured(kComponent.Kubernetes, path, devfilefs.DefaultFs{}) + u, err = GetK8sComponentAsUnstructured(devfileObj, kComponent.Kubernetes, path, devfilefs.DefaultFs{}) if err != nil { return } diff --git a/pkg/libdevfile/libdevfile.go b/pkg/libdevfile/libdevfile.go index 42befb90065..a22e9e9a3c0 100644 --- a/pkg/libdevfile/libdevfile.go +++ b/pkg/libdevfile/libdevfile.go @@ -2,11 +2,17 @@ package libdevfile import ( "fmt" + "regexp" + "strings" "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2" + "github.com/devfile/api/v2/pkg/validation/variables" "github.com/devfile/library/pkg/devfile/parser" "github.com/devfile/library/pkg/devfile/parser/data" "github.com/devfile/library/pkg/devfile/parser/data/v2/common" + devfilefs "github.com/devfile/library/pkg/testingutil/filesystem" + + "github.com/redhat-developer/odo/pkg/util" ) type Handler interface { @@ -193,3 +199,83 @@ func GetEndpointsFromDevfile(devfileObj parser.DevfileObj, ignoreExposures []v1a } return endpoints, nil } + +// GetComponentResourceManifestContentWithVariablesResolved returns the full content of either a Kubernetes or an Openshift +// Devfile component, either Inlined or referenced via a URI. +// No matter how the component is defined, it returns +// the content with all variables substituted using the global variables map defined in `devfileObj`. +// An error is returned if the content references an invalid variable key not defined in the Devfile object. +func GetComponentResourceManifestContentWithVariablesResolved(devfileObj parser.DevfileObj, devfileCmp interface{}, + context string, fs devfilefs.Filesystem) (string, error) { + + var content, uri string + switch devfileCmp := devfileCmp.(type) { + case v1alpha2.Component: + componentType, err := common.GetComponentType(devfileCmp) + if err != nil { + return "", err + } + switch componentType { + case v1alpha2.KubernetesComponentType: + return GetComponentResourceManifestContentWithVariablesResolved(devfileObj, devfileCmp.Kubernetes, context, fs) + + case v1alpha2.OpenshiftComponentType: + return GetComponentResourceManifestContentWithVariablesResolved(devfileObj, devfileCmp.Openshift, context, fs) + + default: + return "", fmt.Errorf("unexpected component type %s", componentType) + } + case *v1alpha2.KubernetesComponent: + content = devfileCmp.Inlined + if devfileCmp.Uri != "" { + uri = devfileCmp.Uri + } + + case *v1alpha2.OpenshiftComponent: + content = devfileCmp.Inlined + if devfileCmp.Uri != "" { + uri = devfileCmp.Uri + } + default: + return "", fmt.Errorf("unexpected type for %v", devfileCmp) + } + + if uri == "" { + return substituteVariables(devfileObj.Data.GetDevfileWorkspaceSpec().Variables, content) + } + + return loadResourceManifestFromUriAndResolveVariables(devfileObj, uri, context, fs) +} + +func loadResourceManifestFromUriAndResolveVariables(devfileObj parser.DevfileObj, uri string, + context string, fs devfilefs.Filesystem) (string, error) { + content, err := util.GetDataFromURI(uri, context, fs) + if err != nil { + return content, err + } + return substituteVariables(devfileObj.Data.GetDevfileWorkspaceSpec().Variables, content) +} + +// substituteVariables validates the string for a global variable in the given `devfileObj` and replaces it. +// An error is returned if the string references an invalid variable key not defined in the Devfile object. +// +//Inspired from variables.validateAndReplaceDataWithVariable, which is unfortunately not exported +func substituteVariables(devfileVars map[string]string, val string) (string, error) { + // example of the regex: {{variable}} / {{ variable }} + matches := regexp.MustCompile(`\{\{\s*(.*?)\s*\}\}`).FindAllStringSubmatch(val, -1) + var invalidKeys []string + for _, match := range matches { + varValue, ok := devfileVars[match[1]] + if !ok { + invalidKeys = append(invalidKeys, match[1]) + } else { + val = strings.Replace(val, match[0], varValue, -1) + } + } + + if len(invalidKeys) > 0 { + return val, &variables.InvalidKeysError{Keys: invalidKeys} + } + + return val, nil +} diff --git a/pkg/libdevfile/libdevfile_test.go b/pkg/libdevfile/libdevfile_test.go index f6cc1ac8308..4ad1c1bd1f5 100644 --- a/pkg/libdevfile/libdevfile_test.go +++ b/pkg/libdevfile/libdevfile_test.go @@ -1,12 +1,14 @@ package libdevfile import ( + "os" "reflect" "testing" "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2" "github.com/devfile/library/pkg/devfile/parser" "github.com/devfile/library/pkg/devfile/parser/data" + devfileFileSystem "github.com/devfile/library/pkg/testingutil/filesystem" "github.com/golang/mock/gomock" "github.com/redhat-developer/odo/pkg/libdevfile/generator" "k8s.io/utils/pointer" @@ -436,3 +438,272 @@ func TestGetEndpointsFromDevfile(t *testing.T) { }) } } + +func TestGetComponentResourceManifestContentWithVariablesResolved(t *testing.T) { + fakeFs := devfileFileSystem.NewFakeFs() + for _, tt := range []struct { + name string + setupFunc func() error + devfileObjFunc func() (parser.DevfileObj, interface{}) + ctx string + wantErr bool + want string + }{ + { + name: "Container Component", + devfileObjFunc: func() (parser.DevfileObj, interface{}) { + devfileData, _ := data.NewDevfileData(string(data.APISchemaVersion220)) + cmp := generator.GetContainerComponent(generator.ContainerComponentParams{ + Name: "container-1", + }) + _ = devfileData.AddComponents([]v1alpha2.Component{cmp}) + return parser.DevfileObj{ + Data: devfileData, + }, cmp + }, + wantErr: true, + }, + { + name: "Image Component", + devfileObjFunc: func() (parser.DevfileObj, interface{}) { + devfileData, _ := data.NewDevfileData(string(data.APISchemaVersion220)) + cmp := generator.GetImageComponent(generator.ImageComponentParams{ + Name: "image-1", + }) + _ = devfileData.AddComponents([]v1alpha2.Component{cmp}) + return parser.DevfileObj{ + Data: devfileData, + }, cmp + }, + wantErr: true, + }, + { + name: "Unknown Component", + devfileObjFunc: func() (parser.DevfileObj, interface{}) { + return parser.DevfileObj{}, "unexpected-string-type" + }, + wantErr: true, + }, + { + name: "Kubernetes Component - Inlined with no variables", + devfileObjFunc: func() (parser.DevfileObj, interface{}) { + devfileData, _ := data.NewDevfileData(string(data.APISchemaVersion220)) + cmp := generator.GetKubernetesComponent(generator.KubernetesComponentParams{ + Name: "my-k8s-1", + Kubernetes: &v1alpha2.KubernetesComponent{ + K8sLikeComponent: v1alpha2.K8sLikeComponent{ + K8sLikeComponentLocation: v1alpha2.K8sLikeComponentLocation{ + Inlined: "some-text-inlined", + }, + }, + }, + }) + _ = devfileData.AddComponents([]v1alpha2.Component{cmp}) + return parser.DevfileObj{ + Data: devfileData, + }, cmp + }, + wantErr: false, + want: "some-text-inlined", + }, + { + name: "Kubernetes Component - Inlined with variables", + devfileObjFunc: func() (parser.DevfileObj, interface{}) { + devfileData, _ := data.NewDevfileData(string(data.APISchemaVersion220)) + cmp := generator.GetKubernetesComponent(generator.KubernetesComponentParams{ + Name: "my-k8s-1", + Kubernetes: &v1alpha2.KubernetesComponent{ + K8sLikeComponent: v1alpha2.K8sLikeComponent{ + K8sLikeComponentLocation: v1alpha2.K8sLikeComponentLocation{ + Inlined: "image: {{MY_CONTAINER_IMAGE}}", + }, + }, + }, + }) + _ = devfileData.AddComponents([]v1alpha2.Component{cmp}) + s := v1alpha2.DevWorkspaceTemplateSpec{ + DevWorkspaceTemplateSpecContent: v1alpha2.DevWorkspaceTemplateSpecContent{ + Variables: map[string]string{ + "MY_CONTAINER_IMAGE": "quay.io/unknown-account/my-image:1.2.3", + }, + }, + } + devfileData.SetDevfileWorkspaceSpec(s) + return parser.DevfileObj{ + Data: devfileData, + }, cmp + }, + wantErr: false, + want: "image: quay.io/unknown-account/my-image:1.2.3", + }, + { + name: "Kubernetes Component - Inlined with unknown variables", + devfileObjFunc: func() (parser.DevfileObj, interface{}) { + devfileData, _ := data.NewDevfileData(string(data.APISchemaVersion220)) + cmp := generator.GetKubernetesComponent(generator.KubernetesComponentParams{ + Name: "my-k8s-1", + Kubernetes: &v1alpha2.KubernetesComponent{ + K8sLikeComponent: v1alpha2.K8sLikeComponent{ + K8sLikeComponentLocation: v1alpha2.K8sLikeComponentLocation{ + Inlined: "image: {{MY_CONTAINER_IMAGE}}:{{ MY_CONTAINER_IMAGE_VERSION_UNKNOWN }}", + }, + }, + }, + }) + _ = devfileData.AddComponents([]v1alpha2.Component{cmp}) + s := v1alpha2.DevWorkspaceTemplateSpec{ + DevWorkspaceTemplateSpecContent: v1alpha2.DevWorkspaceTemplateSpecContent{ + Variables: map[string]string{ + "MY_CONTAINER_IMAGE": "quay.io/unknown-account/my-image", + }, + }, + } + devfileData.SetDevfileWorkspaceSpec(s) + return parser.DevfileObj{ + Data: devfileData, + }, cmp + }, + wantErr: true, + want: "image: quay.io/unknown-account/my-image:{{ MY_CONTAINER_IMAGE_VERSION_UNKNOWN }}", + }, + { + name: "Kubernetes Component - non-existing external file", + devfileObjFunc: func() (parser.DevfileObj, interface{}) { + devfileData, _ := data.NewDevfileData(string(data.APISchemaVersion220)) + cmp := generator.GetKubernetesComponent(generator.KubernetesComponentParams{ + Name: "my-k8s-1", + Kubernetes: &v1alpha2.KubernetesComponent{ + K8sLikeComponent: v1alpha2.K8sLikeComponent{ + K8sLikeComponentLocation: v1alpha2.K8sLikeComponentLocation{ + Uri: "kubernetes/my-external-file-with-should-not-exist", + }, + }, + }, + }) + _ = devfileData.AddComponents([]v1alpha2.Component{cmp}) + return parser.DevfileObj{ + Data: devfileData, + }, cmp + }, + wantErr: true, + }, + { + name: "Kubernetes Component - URI with no variables", + setupFunc: func() error { + return fakeFs.WriteFile("kubernetes/my-external-file", + []byte("some-text-with-no-variables"), + os.ModePerm) + }, + devfileObjFunc: func() (parser.DevfileObj, interface{}) { + devfileData, _ := data.NewDevfileData(string(data.APISchemaVersion220)) + cmp := generator.GetKubernetesComponent(generator.KubernetesComponentParams{ + Name: "my-k8s-1", + Kubernetes: &v1alpha2.KubernetesComponent{ + K8sLikeComponent: v1alpha2.K8sLikeComponent{ + K8sLikeComponentLocation: v1alpha2.K8sLikeComponentLocation{ + Uri: "kubernetes/my-external-file", + }, + }, + }, + }) + _ = devfileData.AddComponents([]v1alpha2.Component{cmp}) + return parser.DevfileObj{ + Data: devfileData, + }, cmp + }, + wantErr: false, + want: "some-text-with-no-variables", + }, + { + name: "Kubernetes Component - URI with variables", + setupFunc: func() error { + return fakeFs.WriteFile("kubernetes/my-deployment.yaml", + []byte("image: {{ MY_CONTAINER_IMAGE }}:{{MY_CONTAINER_IMAGE_VERSION}}"), + os.ModePerm) + }, + devfileObjFunc: func() (parser.DevfileObj, interface{}) { + devfileData, _ := data.NewDevfileData(string(data.APISchemaVersion220)) + cmp := generator.GetKubernetesComponent(generator.KubernetesComponentParams{ + Name: "my-k8s-1", + Kubernetes: &v1alpha2.KubernetesComponent{ + K8sLikeComponent: v1alpha2.K8sLikeComponent{ + K8sLikeComponentLocation: v1alpha2.K8sLikeComponentLocation{ + Uri: "kubernetes/my-deployment.yaml", + }, + }, + }, + }) + _ = devfileData.AddComponents([]v1alpha2.Component{cmp}) + s := v1alpha2.DevWorkspaceTemplateSpec{ + DevWorkspaceTemplateSpecContent: v1alpha2.DevWorkspaceTemplateSpecContent{ + Variables: map[string]string{ + "MY_CONTAINER_IMAGE": "quay.io/unknown-account/my-image", + "MY_CONTAINER_IMAGE_VERSION": "1.2.3", + }, + }, + } + devfileData.SetDevfileWorkspaceSpec(s) + return parser.DevfileObj{ + Data: devfileData, + }, cmp + }, + wantErr: false, + want: "image: quay.io/unknown-account/my-image:1.2.3", + }, + { + name: "Kubernetes Component - URI with unknown variables", + setupFunc: func() error { + return fakeFs.WriteFile("kubernetes/my-external-file.yaml", + []byte("image: {{MY_CONTAINER_IMAGE}}:{{ MY_CONTAINER_IMAGE_VERSION_UNKNOWN }}"), + os.ModePerm) + }, + devfileObjFunc: func() (parser.DevfileObj, interface{}) { + devfileData, _ := data.NewDevfileData(string(data.APISchemaVersion220)) + cmp := generator.GetKubernetesComponent(generator.KubernetesComponentParams{ + Name: "my-k8s-1", + Kubernetes: &v1alpha2.KubernetesComponent{ + K8sLikeComponent: v1alpha2.K8sLikeComponent{ + K8sLikeComponentLocation: v1alpha2.K8sLikeComponentLocation{ + Uri: "kubernetes/my-external-file.yaml", + }, + }, + }, + }) + _ = devfileData.AddComponents([]v1alpha2.Component{cmp}) + s := v1alpha2.DevWorkspaceTemplateSpec{ + DevWorkspaceTemplateSpecContent: v1alpha2.DevWorkspaceTemplateSpecContent{ + Variables: map[string]string{ + "MY_CONTAINER_IMAGE": "quay.io/unknown-account/my-image", + }, + }, + } + devfileData.SetDevfileWorkspaceSpec(s) + return parser.DevfileObj{ + Data: devfileData, + }, cmp + }, + wantErr: true, + want: "image: quay.io/unknown-account/my-image:{{ MY_CONTAINER_IMAGE_VERSION_UNKNOWN }}", + }, + } { + t.Run(tt.name, func(t *testing.T) { + if tt.setupFunc != nil { + if err := tt.setupFunc(); err != nil { + t.Errorf("setup function returned an error: %v", err) + return + } + } + devfileObj, devfileCmp := tt.devfileObjFunc() + got, err := GetComponentResourceManifestContentWithVariablesResolved(devfileObj, devfileCmp, tt.ctx, fakeFs) + if (err != nil) != tt.wantErr { + t.Errorf("GetComponentResourceManifestContentWithVariablesResolved() error = %v, wantErr %v", + err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("GetComponentResourceManifestContentWithVariablesResolved() got = %v, want %v", + got, tt.want) + } + }) + } +} diff --git a/pkg/service/link.go b/pkg/service/link.go index 37007efa648..5a772ffdd26 100644 --- a/pkg/service/link.go +++ b/pkg/service/link.go @@ -5,7 +5,8 @@ import ( "fmt" "strings" - "github.com/redhat-developer/odo/pkg/util" + "github.com/devfile/library/pkg/devfile/parser" + "github.com/redhat-developer/odo/pkg/libdevfile" devfile "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2" "github.com/devfile/library/pkg/devfile/generator" @@ -32,7 +33,7 @@ import ( // PushLinks updates Link(s) from Kubernetes Inlined component in a devfile by creating new ones or removing old ones // returns true if the component needs to be restarted (when a link has been created or deleted) // if service binding operator is not present, it will call pushLinksWithoutOperator to create the links without it. -func PushLinks(client kclient.ClientInterface, k8sComponents []devfile.Component, labels map[string]string, deployment *v1.Deployment, context string) (bool, error) { +func PushLinks(client kclient.ClientInterface, devfileObj parser.DevfileObj, k8sComponents []devfile.Component, labels map[string]string, deployment *v1.Deployment, context string) (bool, error) { serviceBindingSupport, err := client.IsServiceBindingSupported() if err != nil { return false, err @@ -40,15 +41,15 @@ func PushLinks(client kclient.ClientInterface, k8sComponents []devfile.Component if !serviceBindingSupport { klog.V(4).Info("Service Binding Operator is not installed on cluster. Service Binding will be created by odo using SB library.") - return pushLinksWithoutOperator(client, k8sComponents, labels, deployment, context) + return pushLinksWithoutOperator(client, devfileObj, k8sComponents, labels, deployment, context) } - return pushLinksWithOperator(client, k8sComponents, labels, deployment, context) + return pushLinksWithOperator(client, devfileObj, k8sComponents, labels, deployment, context) } // pushLinksWithOperator creates links or deletes links (if service binding operator is installed) between components and services // returns true if the component needs to be restarted (a secret was generated and added to the deployment) -func pushLinksWithOperator(client kclient.ClientInterface, k8sComponents []devfile.Component, labels map[string]string, deployment *v1.Deployment, context string) (bool, error) { +func pushLinksWithOperator(client kclient.ClientInterface, devfileObj parser.DevfileObj, k8sComponents []devfile.Component, labels map[string]string, deployment *v1.Deployment, context string) (bool, error) { ownerReference := generator.GetOwnerReference(deployment) deployed, err := ListDeployedServices(client, labels) @@ -65,14 +66,12 @@ func pushLinksWithOperator(client kclient.ClientInterface, k8sComponents []devfi restartNeeded := false // create an object on the kubernetes cluster for all the Kubernetes Inlined components + var strCRD string for _, c := range k8sComponents { // get the string representation of the YAML definition of a CRD - strCRD := c.Kubernetes.Inlined - if c.Kubernetes.Uri != "" { - strCRD, err = util.GetDataFromURI(c.Kubernetes.Uri, context, devfilefs.DefaultFs{}) - if err != nil { - return false, err - } + strCRD, err = libdevfile.GetComponentResourceManifestContentWithVariablesResolved(devfileObj, c.Kubernetes, context, devfilefs.DefaultFs{}) + if err != nil { + return false, err } // convert the YAML definition into map[string]interface{} since it's needed to create dynamic resource @@ -127,7 +126,7 @@ func pushLinksWithOperator(client kclient.ClientInterface, k8sComponents []devfi // pushLinksWithoutOperator creates links or deletes links (if service binding operator is not installed) between components and services // returns true if the component needs to be restarted (a secret was generated and added to the deployment) -func pushLinksWithoutOperator(client kclient.ClientInterface, k8sComponents []devfile.Component, labels map[string]string, deployment *v1.Deployment, context string) (bool, error) { +func pushLinksWithoutOperator(client kclient.ClientInterface, devfileObj parser.DevfileObj, k8sComponents []devfile.Component, labels map[string]string, deployment *v1.Deployment, context string) (bool, error) { // check csv support before proceeding csvSupport, err := client.IsCSVSupported() @@ -151,14 +150,12 @@ func pushLinksWithoutOperator(client kclient.ClientInterface, k8sComponents []de localLinksMap := make(map[string]string) // create an object on the kubernetes cluster for all the Kubernetes Inlined components + var strCRD string for _, c := range k8sComponents { // get the string representation of the YAML definition of a CRD - strCRD := c.Kubernetes.Inlined - if c.Kubernetes.Uri != "" { - strCRD, err = util.GetDataFromURI(c.Kubernetes.Uri, context, devfilefs.DefaultFs{}) - if err != nil { - return false, err - } + strCRD, err = libdevfile.GetComponentResourceManifestContentWithVariablesResolved(devfileObj, c.Kubernetes, context, devfilefs.DefaultFs{}) + if err != nil { + return false, err } // convert the YAML definition into map[string]interface{} since it's needed to create dynamic resource diff --git a/pkg/service/service.go b/pkg/service/service.go index 2c5e3fb938b..0a76b2183b8 100644 --- a/pkg/service/service.go +++ b/pkg/service/service.go @@ -154,7 +154,7 @@ func listDevfileLinks(devfileObj parser.DevfileObj, context string, fs devfilefs } var services []string for _, c := range components { - u, err := libdevfile.GetK8sComponentAsUnstructured(c.Kubernetes, context, fs) + u, err := libdevfile.GetK8sComponentAsUnstructured(devfileObj, c.Kubernetes, context, fs) if err != nil { return nil, err } @@ -185,7 +185,7 @@ func listDevfileLinks(devfileObj parser.DevfileObj, context string, fs devfilefs } // PushKubernetesResources updates service(s) from Kubernetes Inlined component in a devfile by creating new ones or removing old ones -func PushKubernetesResources(client kclient.ClientInterface, k8sComponents []devfile.Component, labels map[string]string, annotations map[string]string, context string) error { +func PushKubernetesResources(client kclient.ClientInterface, devfileObj parser.DevfileObj, k8sComponents []devfile.Component, labels map[string]string, annotations map[string]string, context string) error { // check csv support before proceeding csvSupported, err := client.IsCSVSupported() if err != nil { @@ -209,7 +209,7 @@ func PushKubernetesResources(client kclient.ClientInterface, k8sComponents []dev // create an object on the kubernetes cluster for all the Kubernetes Inlined components for _, c := range k8sComponents { - u, er := libdevfile.GetK8sComponentAsUnstructured(c.Kubernetes, context, devfilefs.DefaultFs{}) + u, er := libdevfile.GetK8sComponentAsUnstructured(devfileObj, c.Kubernetes, context, devfilefs.DefaultFs{}) if er != nil { return er } @@ -327,10 +327,10 @@ func ListDeployedServices(client kclient.ClientInterface, labels map[string]stri // UpdateServicesWithOwnerReferences adds an owner reference to an inlined Kubernetes resource (except service binding objects) // if not already present in the list of owner references -func UpdateServicesWithOwnerReferences(client kclient.ClientInterface, k8sComponents []devfile.Component, ownerReference metav1.OwnerReference, context string) error { +func UpdateServicesWithOwnerReferences(client kclient.ClientInterface, devfileObj parser.DevfileObj, k8sComponents []devfile.Component, ownerReference metav1.OwnerReference, context string) error { for _, c := range k8sComponents { // get the string representation of the YAML definition of a CRD - u, err := libdevfile.GetK8sComponentAsUnstructured(c.Kubernetes, context, devfilefs.DefaultFs{}) + u, err := libdevfile.GetK8sComponentAsUnstructured(devfileObj, c.Kubernetes, context, devfilefs.DefaultFs{}) if err != nil { return err } @@ -398,14 +398,14 @@ func createOperatorService(client kclient.ClientInterface, u unstructured.Unstru } // ValidateResourcesExist validates if the Kubernetes inlined components are installed on the cluster -func ValidateResourcesExist(client kclient.ClientInterface, k8sComponents []devfile.Component, context string) error { +func ValidateResourcesExist(client kclient.ClientInterface, devfileObj parser.DevfileObj, k8sComponents []devfile.Component, context string) error { if len(k8sComponents) == 0 { return nil } var unsupportedResources []string for _, c := range k8sComponents { - kindErr, err := ValidateResourceExist(client, c, context) + kindErr, err := ValidateResourceExist(client, devfileObj, c, context) if err != nil { if kindErr != "" { unsupportedResources = append(unsupportedResources, kindErr) @@ -422,9 +422,9 @@ func ValidateResourcesExist(client kclient.ClientInterface, k8sComponents []devf return nil } -func ValidateResourceExist(client kclient.ClientInterface, k8sComponent devfile.Component, context string) (kindErr string, err error) { +func ValidateResourceExist(client kclient.ClientInterface, devfileObj parser.DevfileObj, k8sComponent devfile.Component, context string) (kindErr string, err error) { // get the string representation of the YAML definition of a CRD - u, err := libdevfile.GetK8sComponentAsUnstructured(k8sComponent.Kubernetes, context, devfilefs.DefaultFs{}) + u, err := libdevfile.GetK8sComponentAsUnstructured(devfileObj, k8sComponent.Kubernetes, context, devfilefs.DefaultFs{}) if err != nil { return "", err } From 0c03bdfd91b56d3057abb5068b09dbef98506a23 Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Mon, 2 May 2022 16:58:43 +0200 Subject: [PATCH 3/7] Switch to using 'uri' Kubernetes components in test Devfiles This seems to be a much more realistic case when referencing external Kubernetes manifests. Notes: Some tests, like for `odo deploy`, still test 'Inlined' manifests. --- pkg/component/delete/delete_test.go | 12 ++-- ...l => devfile-deploy-with-k8s-inlined.yaml} | 23 ++++++- ...evfile-deploy-with-multiple-resources.yaml | 4 ++ .../devfiles/nodejs/devfile-deploy.yaml | 23 +------ ...roject_source-in-docker-build-context.yaml | 38 +---------- .../devfiles/nodejs/devfile-with-link.yaml | 65 +------------------ .../devfiles/nodejs/devfile-with-pod.yaml | 25 +------ .../devfile-with-two-deploy-commands.yaml | 23 +------ ...h-image-component-and-no-buildContext.yaml | 37 +---------- .../outerloop-deploy.yaml} | 2 +- .../outerloop-deploy.yaml | 18 +++++ .../outerloop-service.yaml | 15 +++++ .../kubernetes/devfile-with-link/myredis.yaml | 41 ++++++++++++ .../devfile-with-link/redis-link.yaml | 20 ++++++ .../devfile-with-pod/etcdcluster.yaml | 9 +++ .../kubernetes/devfile-with-pod/nginx.yaml | 12 ++++ .../outerloop-deploy.yaml | 21 ++++++ .../outerloop-deploy.yaml | 18 +++++ .../outerloop-service.yaml | 15 +++++ .../devfile/cmd_devfile_build_images_test.go | 7 ++ .../devfile/cmd_devfile_deploy_test.go | 34 ++++++---- .../devfile/cmd_devfile_init_test.go | 2 + .../devfile/cmd_devfile_list_test.go | 2 + 23 files changed, 245 insertions(+), 221 deletions(-) rename tests/examples/source/devfiles/nodejs/{devfile-deploy-with-k8s-uri.yaml => devfile-deploy-with-k8s-inlined.yaml} (77%) rename tests/examples/source/devfiles/nodejs/project/kubernetes/{outerloop-deployment.yaml => devfile-deploy/outerloop-deploy.yaml} (95%) create mode 100644 tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-outerloop-project_source-in-docker-build-context/outerloop-deploy.yaml create mode 100644 tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-outerloop-project_source-in-docker-build-context/outerloop-service.yaml create mode 100644 tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-link/myredis.yaml create mode 100644 tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-link/redis-link.yaml create mode 100644 tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-pod/etcdcluster.yaml create mode 100644 tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-pod/nginx.yaml create mode 100644 tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-two-deploy-commands/outerloop-deploy.yaml create mode 100644 tests/examples/source/devfiles/nodejs/project/kubernetes/issue-5600-devfile-with-image-component-and-no-buildContext/outerloop-deploy.yaml create mode 100644 tests/examples/source/devfiles/nodejs/project/kubernetes/issue-5600-devfile-with-image-component-and-no-buildContext/outerloop-service.yaml diff --git a/pkg/component/delete/delete_test.go b/pkg/component/delete/delete_test.go index f1548d35ef6..637be50f825 100644 --- a/pkg/component/delete/delete_test.go +++ b/pkg/component/delete/delete_test.go @@ -324,7 +324,7 @@ func TestDeleteComponentClient_ListResourcesToDeleteFromDevfile(t *testing.T) { }, }, args: args{ - devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy.yaml"), + devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy-with-k8s-inlined.yaml"), appName: appName, }, wantIsInnerLoopDeployed: true, @@ -371,7 +371,7 @@ func TestDeleteComponentClient_ListResourcesToDeleteFromDevfile(t *testing.T) { }, }, args: args{ - devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy.yaml"), + devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy-with-k8s-inlined.yaml"), appName: appName, }, wantIsInnerLoopDeployed: false, @@ -388,7 +388,7 @@ func TestDeleteComponentClient_ListResourcesToDeleteFromDevfile(t *testing.T) { }, }, args: args{ - devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy.yaml"), + devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy-with-k8s-inlined.yaml"), appName: appName, }, wantIsInnerLoopDeployed: false, @@ -406,7 +406,7 @@ func TestDeleteComponentClient_ListResourcesToDeleteFromDevfile(t *testing.T) { }, }, args: args{ - devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy.yaml"), + devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy-with-k8s-inlined.yaml"), appName: appName, }, wantIsInnerLoopDeployed: true, @@ -427,7 +427,7 @@ func TestDeleteComponentClient_ListResourcesToDeleteFromDevfile(t *testing.T) { }, }, args: args{ - devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy.yaml"), + devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy-with-k8s-inlined.yaml"), appName: appName, }, wantIsInnerLoopDeployed: true, @@ -487,7 +487,7 @@ func TestDeleteComponentClient_ExecutePreStopEvents(t *testing.T) { }, }, args: args{ - devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy.yaml"), + devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy-with-k8s-inlined.yaml"), appName: appName, }, wantErr: false, diff --git a/tests/examples/source/devfiles/nodejs/devfile-deploy-with-k8s-uri.yaml b/tests/examples/source/devfiles/nodejs/devfile-deploy-with-k8s-inlined.yaml similarity index 77% rename from tests/examples/source/devfiles/nodejs/devfile-deploy-with-k8s-uri.yaml rename to tests/examples/source/devfiles/nodejs/devfile-deploy-with-k8s-inlined.yaml index 54eb4d90f59..8cf0f27dd47 100644 --- a/tests/examples/source/devfiles/nodejs/devfile-deploy-with-k8s-uri.yaml +++ b/tests/examples/source/devfiles/nodejs/devfile-deploy-with-k8s-inlined.yaml @@ -86,4 +86,25 @@ components: uri: ./Dockerfile - name: outerloop-deploy kubernetes: - uri: 'kubernetes/outerloop-deployment.yaml' + inlined: | + kind: Deployment + apiVersion: apps/v1 + metadata: + name: my-component + spec: + replicas: 1 + selector: + matchLabels: + app: node-app + template: + metadata: + labels: + app: node-app + spec: + containers: + - name: main + image: {{CONTAINER_IMAGE}} + resources: + limits: + memory: "128Mi" + cpu: "500m" diff --git a/tests/examples/source/devfiles/nodejs/devfile-deploy-with-multiple-resources.yaml b/tests/examples/source/devfiles/nodejs/devfile-deploy-with-multiple-resources.yaml index 870a49e3dbc..5fbab94291f 100644 --- a/tests/examples/source/devfiles/nodejs/devfile-deploy-with-multiple-resources.yaml +++ b/tests/examples/source/devfiles/nodejs/devfile-deploy-with-multiple-resources.yaml @@ -69,6 +69,8 @@ components: - name: outerloop-deploy kubernetes: + # TODO(rm3l): Move this as a URI by default once https://github.com/redhat-developer/odo/issues/5637 is fixed + # Also consider keeping an "Inlined" version for testing inlined: | kind: Deployment apiVersion: apps/v1 @@ -93,6 +95,8 @@ components: cpu: "500m" - name: outerloop-deploy-2 kubernetes: + # TODO(rm3l): Move this as a URI by default once https://github.com/redhat-developer/odo/issues/5637 is fixed + # Also consider keeping an "Inlined" version for testing inlined: | apiVersion: v1 kind: Service diff --git a/tests/examples/source/devfiles/nodejs/devfile-deploy.yaml b/tests/examples/source/devfiles/nodejs/devfile-deploy.yaml index ada31e2b5ca..d8424156eb3 100644 --- a/tests/examples/source/devfiles/nodejs/devfile-deploy.yaml +++ b/tests/examples/source/devfiles/nodejs/devfile-deploy.yaml @@ -65,28 +65,7 @@ components: - name: outerloop-deploy kubernetes: - inlined: | - kind: Deployment - apiVersion: apps/v1 - metadata: - name: my-component - spec: - replicas: 1 - selector: - matchLabels: - app: node-app - template: - metadata: - labels: - app: node-app - spec: - containers: - - name: main - image: {{CONTAINER_IMAGE}} - resources: - limits: - memory: "128Mi" - cpu: "500m" + uri: kubernetes/devfile-deploy/outerloop-deploy.yaml metadata: description: Stack with Node.js 14 displayName: Node.js Runtime diff --git a/tests/examples/source/devfiles/nodejs/devfile-outerloop-project_source-in-docker-build-context.yaml b/tests/examples/source/devfiles/nodejs/devfile-outerloop-project_source-in-docker-build-context.yaml index 71bd0b76cf9..2b5a004a34f 100644 --- a/tests/examples/source/devfiles/nodejs/devfile-outerloop-project_source-in-docker-build-context.yaml +++ b/tests/examples/source/devfiles/nodejs/devfile-outerloop-project_source-in-docker-build-context.yaml @@ -58,41 +58,7 @@ components: buildContext: ${PROJECT_SOURCE} - name: outerloop-deploy kubernetes: - inlined: | - kind: Deployment - apiVersion: apps/v1 - metadata: - name: devfile-nodejs-deploy - spec: - replicas: 1 - selector: - matchLabels: - app: devfile-nodejs-deploy - template: - metadata: - labels: - app: devfile-nodejs-deploy - spec: - containers: - - name: main - image: "{{CONTAINER_IMAGE}}" - resources: {} + uri: kubernetes/devfile-outerloop-project_source-in-docker-build-context/outerloop-deploy.yaml - name: outerloop-service kubernetes: - inlined: | - apiVersion: v1 - kind: Service - metadata: - labels: - app: devfile-nodejs-deploy - name: devfile-nodejs-deploy - spec: - ports: - - name: http-3000 - port: 3000 - protocol: TCP - targetPort: 3000 - selector: - app: devfile-nodejs-deploy - type: LoadBalancer - + uri: kubernetes/devfile-outerloop-project_source-in-docker-build-context/outerloop-service.yaml diff --git a/tests/examples/source/devfiles/nodejs/devfile-with-link.yaml b/tests/examples/source/devfiles/nodejs/devfile-with-link.yaml index 6e7cae607ca..2079621ba3c 100644 --- a/tests/examples/source/devfiles/nodejs/devfile-with-link.yaml +++ b/tests/examples/source/devfiles/nodejs/devfile-with-link.yaml @@ -42,71 +42,10 @@ components: sourceMapping: /project name: runtime - kubernetes: - inlined: | - apiVersion: redis.redis.opstreelabs.in/v1beta1 - kind: Redis - metadata: - name: myredis - annotations: - service.binding/name: path={.metadata.name} - spec: - redisExporter: - enabled: true - image: 'quay.io/opstree/redis-exporter:1.0' - imagePullPolicy: Always - resources: - requests: - cpu: 100m - memory: 128Mi - limits: - cpu: 100m - memory: 128Mi - kubernetesConfig: - image: 'quay.io/opstree/redis:v6.2' - imagePullPolicy: IfNotPresent - resources: - requests: - cpu: 101m - memory: 128Mi - limits: - cpu: 101m - memory: 128Mi - redisSecret: - name: redis-secret - key: password - serviceType: LoadBalancer - redisConfig: {} - storage: - volumeClaimTemplate: - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi + uri: kubernetes/devfile-with-link/myredis.yaml name: myredis - kubernetes: - inlined: | - apiVersion: binding.operators.coreos.com/v1alpha1 - kind: ServiceBinding - metadata: - creationTimestamp: null - name: redis-link - spec: - application: - group: apps - name: api-app - resource: deployments - version: v1 - bindAsFiles: true - detectBindingResources: true - services: - - group: redis.redis.opstreelabs.in - kind: Redis - name: myredis - version: v1beta1 - status: - secret: "" + uri: kubernetes/devfile-with-link/redis-link.yaml name: redis-link metadata: description: Stack with Node.js 14 diff --git a/tests/examples/source/devfiles/nodejs/devfile-with-pod.yaml b/tests/examples/source/devfiles/nodejs/devfile-with-pod.yaml index dd6409a6a1d..f704739b523 100644 --- a/tests/examples/source/devfiles/nodejs/devfile-with-pod.yaml +++ b/tests/examples/source/devfiles/nodejs/devfile-with-pod.yaml @@ -24,31 +24,10 @@ components: sourceMapping: /project name: runtime - kubernetes: - inlined: | - apiVersion: etcd.database.coreos.com/v1beta2 - kind: EtcdCluster - metadata: - annotations: - etcd.database.coreos.com/scope: clusterwide - name: etcdcluster - spec: - size: 3 - version: 3.2.13 + uri: kubernetes/devfile-with-pod/etcdcluster.yaml name: etcdcluster - kubernetes: - inlined: | - apiVersion: v1 - kind: Pod - metadata: - labels: - name: nginx - name: nginx - spec: - containers: - - image: quay.io/bitnami/nginx - name: nginx - ports: - - containerPort: 80 + uri: kubernetes/devfile-with-pod/nginx.yaml name: nginx commands: - exec: diff --git a/tests/examples/source/devfiles/nodejs/devfile-with-two-deploy-commands.yaml b/tests/examples/source/devfiles/nodejs/devfile-with-two-deploy-commands.yaml index ec4b66c45ec..09a8e348618 100644 --- a/tests/examples/source/devfiles/nodejs/devfile-with-two-deploy-commands.yaml +++ b/tests/examples/source/devfiles/nodejs/devfile-with-two-deploy-commands.yaml @@ -72,28 +72,7 @@ components: - name: outerloop-deploy kubernetes: - inlined: | - kind: Deployment - apiVersion: apps/v1 - metadata: - name: my-component - spec: - replicas: 1 - selector: - matchLabels: - app: node-app - template: - metadata: - labels: - app: node-app - spec: - containers: - - name: main - image: {{CONTAINER_IMAGE}} - resources: - limits: - memory: "128Mi" - cpu: "500m" + uri: kubernetes/devfile-with-two-deploy-commands/outerloop-deploy.yaml metadata: description: Stack with Node.js 14 displayName: Node.js Runtime diff --git a/tests/examples/source/devfiles/nodejs/issue-5600-devfile-with-image-component-and-no-buildContext.yaml b/tests/examples/source/devfiles/nodejs/issue-5600-devfile-with-image-component-and-no-buildContext.yaml index bd00d831918..559a0301e7d 100644 --- a/tests/examples/source/devfiles/nodejs/issue-5600-devfile-with-image-component-and-no-buildContext.yaml +++ b/tests/examples/source/devfiles/nodejs/issue-5600-devfile-with-image-component-and-no-buildContext.yaml @@ -48,43 +48,10 @@ components: imageName: localhost:5000/devfile-nodejs-deploy:0.1.0 name: prod-image - kubernetes: - inlined: | - kind: Deployment - apiVersion: apps/v1 - metadata: - name: devfile-nodejs-deploy - spec: - replicas: 1 - selector: - matchLabels: - app: devfile-nodejs-deploy - template: - metadata: - labels: - app: devfile-nodejs-deploy - spec: - containers: - - name: main - image: "localhost:5000/devfile-nodejs-deploy:0.1.0" - resources: {} + uri: kubernetes/issue-5600-devfile-with-image-component-and-no-buildContext/outerloop-deploy.yaml name: outerloop-deploy - kubernetes: - inlined: | - apiVersion: v1 - kind: Service - metadata: - labels: - app: devfile-nodejs-deploy - name: devfile-nodejs-deploy - spec: - ports: - - name: http-3000 - port: 3000 - protocol: TCP - targetPort: 3000 - selector: - app: devfile-nodejs-deploy - type: LoadBalancer + uri: kubernetes/issue-5600-devfile-with-image-component-and-no-buildContext/outerloop-service.yaml name: outerloop-service metadata: language: javascript diff --git a/tests/examples/source/devfiles/nodejs/project/kubernetes/outerloop-deployment.yaml b/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-deploy/outerloop-deploy.yaml similarity index 95% rename from tests/examples/source/devfiles/nodejs/project/kubernetes/outerloop-deployment.yaml rename to tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-deploy/outerloop-deploy.yaml index 2a155d1a780..5ac9de29bbc 100644 --- a/tests/examples/source/devfiles/nodejs/project/kubernetes/outerloop-deployment.yaml +++ b/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-deploy/outerloop-deploy.yaml @@ -20,4 +20,4 @@ spec: resources: limits: memory: "128Mi" - cpu: "500m" + cpu: "500m" \ No newline at end of file diff --git a/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-outerloop-project_source-in-docker-build-context/outerloop-deploy.yaml b/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-outerloop-project_source-in-docker-build-context/outerloop-deploy.yaml new file mode 100644 index 00000000000..c73a309e8e0 --- /dev/null +++ b/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-outerloop-project_source-in-docker-build-context/outerloop-deploy.yaml @@ -0,0 +1,18 @@ +kind: Deployment +apiVersion: apps/v1 +metadata: + name: devfile-nodejs-deploy +spec: + replicas: 1 + selector: + matchLabels: + app: devfile-nodejs-deploy + template: + metadata: + labels: + app: devfile-nodejs-deploy + spec: + containers: + - name: main + image: "{{CONTAINER_IMAGE}}" + resources: {} \ No newline at end of file diff --git a/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-outerloop-project_source-in-docker-build-context/outerloop-service.yaml b/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-outerloop-project_source-in-docker-build-context/outerloop-service.yaml new file mode 100644 index 00000000000..4c6ec53b676 --- /dev/null +++ b/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-outerloop-project_source-in-docker-build-context/outerloop-service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app: devfile-nodejs-deploy + name: devfile-nodejs-deploy +spec: + ports: + - name: http-3000 + port: 3000 + protocol: TCP + targetPort: 3000 + selector: + app: devfile-nodejs-deploy + type: LoadBalancer \ No newline at end of file diff --git a/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-link/myredis.yaml b/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-link/myredis.yaml new file mode 100644 index 00000000000..46f6251385f --- /dev/null +++ b/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-link/myredis.yaml @@ -0,0 +1,41 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: Redis +metadata: + name: myredis + annotations: + service.binding/name: path={.metadata.name} +spec: + redisExporter: + enabled: true + image: 'quay.io/opstree/redis-exporter:1.0' + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + kubernetesConfig: + image: 'quay.io/opstree/redis:v6.2' + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisSecret: + name: redis-secret + key: password + serviceType: LoadBalancer + redisConfig: {} + storage: + volumeClaimTemplate: + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-link/redis-link.yaml b/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-link/redis-link.yaml new file mode 100644 index 00000000000..c4868d07b93 --- /dev/null +++ b/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-link/redis-link.yaml @@ -0,0 +1,20 @@ +apiVersion: binding.operators.coreos.com/v1alpha1 +kind: ServiceBinding +metadata: + creationTimestamp: null + name: redis-link +spec: + application: + group: apps + name: api-app + resource: deployments + version: v1 + bindAsFiles: true + detectBindingResources: true + services: + - group: redis.redis.opstreelabs.in + kind: Redis + name: myredis + version: v1beta1 +status: + secret: "" \ No newline at end of file diff --git a/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-pod/etcdcluster.yaml b/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-pod/etcdcluster.yaml new file mode 100644 index 00000000000..68aef654216 --- /dev/null +++ b/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-pod/etcdcluster.yaml @@ -0,0 +1,9 @@ +apiVersion: etcd.database.coreos.com/v1beta2 +kind: EtcdCluster +metadata: + annotations: + etcd.database.coreos.com/scope: clusterwide + name: etcdcluster +spec: + size: 3 + version: 3.2.13 \ No newline at end of file diff --git a/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-pod/nginx.yaml b/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-pod/nginx.yaml new file mode 100644 index 00000000000..67239bd5025 --- /dev/null +++ b/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-pod/nginx.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + labels: + name: nginx + name: nginx +spec: + containers: + - image: quay.io/bitnami/nginx + name: nginx + ports: + - containerPort: 80 \ No newline at end of file diff --git a/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-two-deploy-commands/outerloop-deploy.yaml b/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-two-deploy-commands/outerloop-deploy.yaml new file mode 100644 index 00000000000..68b4e32eccb --- /dev/null +++ b/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-two-deploy-commands/outerloop-deploy.yaml @@ -0,0 +1,21 @@ +kind: Deployment +apiVersion: apps/v1 +metadata: + name: my-component +spec: + replicas: 1 + selector: + matchLabels: + app: node-app + template: + metadata: + labels: + app: node-app + spec: + containers: + - name: main + image: {{CONTAINER_IMAGE}} + resources: + limits: + memory: "128Mi" + cpu: "500m" \ No newline at end of file diff --git a/tests/examples/source/devfiles/nodejs/project/kubernetes/issue-5600-devfile-with-image-component-and-no-buildContext/outerloop-deploy.yaml b/tests/examples/source/devfiles/nodejs/project/kubernetes/issue-5600-devfile-with-image-component-and-no-buildContext/outerloop-deploy.yaml new file mode 100644 index 00000000000..bfa919341c8 --- /dev/null +++ b/tests/examples/source/devfiles/nodejs/project/kubernetes/issue-5600-devfile-with-image-component-and-no-buildContext/outerloop-deploy.yaml @@ -0,0 +1,18 @@ +kind: Deployment +apiVersion: apps/v1 +metadata: + name: devfile-nodejs-deploy +spec: + replicas: 1 + selector: + matchLabels: + app: devfile-nodejs-deploy + template: + metadata: + labels: + app: devfile-nodejs-deploy + spec: + containers: + - name: main + image: "localhost:5000/devfile-nodejs-deploy:0.1.0" + resources: {} \ No newline at end of file diff --git a/tests/examples/source/devfiles/nodejs/project/kubernetes/issue-5600-devfile-with-image-component-and-no-buildContext/outerloop-service.yaml b/tests/examples/source/devfiles/nodejs/project/kubernetes/issue-5600-devfile-with-image-component-and-no-buildContext/outerloop-service.yaml new file mode 100644 index 00000000000..4c6ec53b676 --- /dev/null +++ b/tests/examples/source/devfiles/nodejs/project/kubernetes/issue-5600-devfile-with-image-component-and-no-buildContext/outerloop-service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app: devfile-nodejs-deploy + name: devfile-nodejs-deploy +spec: + ports: + - name: http-3000 + port: 3000 + protocol: TCP + targetPort: 3000 + selector: + app: devfile-nodejs-deploy + type: LoadBalancer \ No newline at end of file diff --git a/tests/integration/devfile/cmd_devfile_build_images_test.go b/tests/integration/devfile/cmd_devfile_build_images_test.go index c49b2537de5..29d785a6da2 100644 --- a/tests/integration/devfile/cmd_devfile_build_images_test.go +++ b/tests/integration/devfile/cmd_devfile_build_images_test.go @@ -79,6 +79,9 @@ var _ = Describe("odo devfile build-images command tests", func() { BeforeEach(func() { helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context) + helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project", "kubernetes", + "devfile-outerloop-project_source-in-docker-build-context"), + filepath.Join(commonVar.Context, "kubernetes", "devfile-outerloop-project_source-in-docker-build-context")) helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", helper.GetExamplePath("source", "devfiles", "nodejs", @@ -121,6 +124,10 @@ var _ = Describe("odo devfile build-images command tests", func() { BeforeEach(func() { helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context) + helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project", "kubernetes", + "issue-5600-devfile-with-image-component-and-no-buildContext"), + filepath.Join(commonVar.Context, "kubernetes", + "issue-5600-devfile-with-image-component-and-no-buildContext")) helper.CopyExampleDevFile( filepath.Join("source", "devfiles", "nodejs", "issue-5600-devfile-with-image-component-and-no-buildContext.yaml"), diff --git a/tests/integration/devfile/cmd_devfile_deploy_test.go b/tests/integration/devfile/cmd_devfile_deploy_test.go index 5be778a2673..2bb71328ef3 100644 --- a/tests/integration/devfile/cmd_devfile_deploy_test.go +++ b/tests/integration/devfile/cmd_devfile_deploy_test.go @@ -40,7 +40,7 @@ var _ = Describe("odo devfile deploy command tests", func() { }) }) - for _, ctx := range []struct { + for _, testCtx := range []struct { title string devfileName string setupFunc func() @@ -48,28 +48,27 @@ var _ = Describe("odo devfile deploy command tests", func() { { title: "using a devfile.yaml containing a deploy command", devfileName: "devfile-deploy.yaml", - setupFunc: nil, - }, - { - title: "using a devfile.yaml containing an outer-loop Kubernetes component referenced via an URI", - devfileName: "devfile-deploy-with-k8s-uri.yaml", setupFunc: func() { - helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project", "kubernetes"), - filepath.Join(commonVar.Context, "kubernetes")) + helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project", "kubernetes", "devfile-deploy"), + filepath.Join(commonVar.Context, "kubernetes", "devfile-deploy")) }, }, + { + title: "using a devfile.yaml containing an outer-loop Kubernetes component inlined", + devfileName: "devfile-deploy-with-k8s-inlined.yaml", + }, } { - When(ctx.title, func() { + When(testCtx.title, func() { // from devfile cmpName := "nodejs-prj1-api-abhz" deploymentName := "my-component" BeforeEach(func() { helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context) - helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", ctx.devfileName), + helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", testCtx.devfileName), path.Join(commonVar.Context, "devfile.yaml")) - if ctx.setupFunc != nil { - ctx.setupFunc() + if testCtx.setupFunc != nil { + testCtx.setupFunc() } }) @@ -135,6 +134,8 @@ var _ = Describe("odo devfile deploy command tests", func() { When("using a devfile.yaml containing two deploy commands", func() { BeforeEach(func() { helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context) + helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project", "kubernetes", "devfile-with-two-deploy-commands"), + filepath.Join(commonVar.Context, "kubernetes", "devfile-with-two-deploy-commands")) helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile-with-two-deploy-commands.yaml"), path.Join(commonVar.Context, "devfile.yaml")) }) It("should run odo deploy", func() { @@ -153,6 +154,8 @@ var _ = Describe("odo devfile deploy command tests", func() { When("recording telemetry data", func() { BeforeEach(func() { helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context) + helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project", "kubernetes", "devfile-deploy"), + filepath.Join(commonVar.Context, "kubernetes", "devfile-deploy")) helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile-deploy.yaml"), path.Join(commonVar.Context, "devfile.yaml")) helper.EnableTelemetryDebug() helper.Cmd("odo", "deploy").AddEnv("PODMAN_CMD=echo").ShouldPass() @@ -176,6 +179,9 @@ var _ = Describe("odo devfile deploy command tests", func() { BeforeEach(func() { helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context) + helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project", "kubernetes", + "devfile-outerloop-project_source-in-docker-build-context"), + filepath.Join(commonVar.Context, "kubernetes", "devfile-outerloop-project_source-in-docker-build-context")) helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", helper.GetExamplePath("source", "devfiles", "nodejs", @@ -220,6 +226,10 @@ var _ = Describe("odo devfile deploy command tests", func() { BeforeEach(func() { helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context) + helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project", "kubernetes", + "issue-5600-devfile-with-image-component-and-no-buildContext"), + filepath.Join(commonVar.Context, "kubernetes", + "issue-5600-devfile-with-image-component-and-no-buildContext")) helper.CopyExampleDevFile( filepath.Join("source", "devfiles", "nodejs", "issue-5600-devfile-with-image-component-and-no-buildContext.yaml"), diff --git a/tests/integration/devfile/cmd_devfile_init_test.go b/tests/integration/devfile/cmd_devfile_init_test.go index 482ac1e655e..49985e7b284 100644 --- a/tests/integration/devfile/cmd_devfile_init_test.go +++ b/tests/integration/devfile/cmd_devfile_init_test.go @@ -268,6 +268,8 @@ var _ = Describe("odo devfile init command tests", func() { var out string BeforeEach(func() { helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile-deploy.yaml"), devfilePath) + helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project", "kubernetes", "devfile-deploy"), + filepath.Join(commonVar.Context, "kubernetes", "devfile-deploy")) out = helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", devfilePath).ShouldPass().Out() }) It("should show information about both `odo dev`, and `odo deploy`", func() { diff --git a/tests/integration/devfile/cmd_devfile_list_test.go b/tests/integration/devfile/cmd_devfile_list_test.go index 6e8b28fefcb..618d8365f1a 100644 --- a/tests/integration/devfile/cmd_devfile_list_test.go +++ b/tests/integration/devfile/cmd_devfile_list_test.go @@ -32,6 +32,8 @@ var _ = Describe("odo list with devfile", func() { BeforeEach(func() { helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context) helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile-deploy.yaml"), path.Join(commonVar.Context, "devfile.yaml")) + helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project", "kubernetes", "devfile-deploy"), + filepath.Join(commonVar.Context, "kubernetes", "devfile-deploy")) helper.Chdir(commonVar.Context) var err error devSession, _, _, _, err = helper.StartDevMode() From 514c90fbf3dde5bb73b2f1f15758d7b8b8913342 Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Tue, 3 May 2022 16:19:48 +0200 Subject: [PATCH 4/7] Pass the component name to 'GetComponentResourceManifestContentWithVariablesResolved' As suggested in review, this makes more sense now that we are passing the entire devfile object --- pkg/deploy/deploy.go | 2 +- pkg/libdevfile/command_apply.go | 2 +- pkg/libdevfile/component_kubernetes_utils.go | 6 +- pkg/libdevfile/errors.go | 12 +- pkg/libdevfile/libdevfile.go | 66 ++++---- pkg/libdevfile/libdevfile_test.go | 155 +++++++++++++------ pkg/service/link.go | 4 +- pkg/service/service.go | 8 +- 8 files changed, 163 insertions(+), 92 deletions(-) diff --git a/pkg/deploy/deploy.go b/pkg/deploy/deploy.go index f8cba430797..54aee991f17 100644 --- a/pkg/deploy/deploy.go +++ b/pkg/deploy/deploy.go @@ -75,7 +75,7 @@ func (o *deployHandler) ApplyKubernetes(kubernetes v1alpha2.Component) error { odolabels.SetProjectType(annotations, component.GetComponentTypeFromDevfileMetadata(o.devfileObj.Data.GetMetadata())) // Get the Kubernetes component - u, err := libdevfile.GetK8sComponentAsUnstructured(o.devfileObj, kubernetes.Kubernetes, o.path, devfilefs.DefaultFs{}) + u, err := libdevfile.GetK8sComponentAsUnstructured(o.devfileObj, kubernetes.Name, o.path, devfilefs.DefaultFs{}) if err != nil { return err } diff --git a/pkg/libdevfile/command_apply.go b/pkg/libdevfile/command_apply.go index 4b702011e84..cfcfb83d547 100644 --- a/pkg/libdevfile/command_apply.go +++ b/pkg/libdevfile/command_apply.go @@ -37,7 +37,7 @@ func (o *applyCommand) Execute(handler Handler) error { } if len(devfileComponents) != 1 { - return NewComponentsWithSameNameError() + return NewComponentsWithSameNameError(o.command.Apply.Component) } component, err := newComponent(o.devfileObj, devfileComponents[0]) diff --git a/pkg/libdevfile/component_kubernetes_utils.go b/pkg/libdevfile/component_kubernetes_utils.go index 1fba174472f..9107884f7ed 100644 --- a/pkg/libdevfile/component_kubernetes_utils.go +++ b/pkg/libdevfile/component_kubernetes_utils.go @@ -10,10 +10,10 @@ import ( ) // GetK8sComponentAsUnstructured parses the Inlined/URI K8s of the devfile K8s component -func GetK8sComponentAsUnstructured(devfileObj parser.DevfileObj, component *v1alpha2.KubernetesComponent, +func GetK8sComponentAsUnstructured(devfileObj parser.DevfileObj, componentName string, context string, fs devfilefs.Filesystem) (unstructured.Unstructured, error) { - strCRD, err := GetComponentResourceManifestContentWithVariablesResolved(devfileObj, component, context, fs) + strCRD, err := GetComponentResourceManifestContentWithVariablesResolved(devfileObj, componentName, context, fs) if err != nil { return unstructured.Unstructured{}, err } @@ -37,7 +37,7 @@ func ListKubernetesComponents(devfileObj parser.DevfileObj, path string) (list [ var u unstructured.Unstructured for _, kComponent := range components { if kComponent.Kubernetes != nil { - u, err = GetK8sComponentAsUnstructured(devfileObj, kComponent.Kubernetes, path, devfilefs.DefaultFs{}) + u, err = GetK8sComponentAsUnstructured(devfileObj, kComponent.Name, path, devfilefs.DefaultFs{}) if err != nil { return } diff --git a/pkg/libdevfile/errors.go b/pkg/libdevfile/errors.go index f1dd26d7073..5e63c22ebdc 100644 --- a/pkg/libdevfile/errors.go +++ b/pkg/libdevfile/errors.go @@ -64,14 +64,18 @@ func (e ComponentNotExistError) Error() string { return fmt.Sprintf("component %q does not exists", e.name) } -type ComponentsWithSameNameError struct{} +type ComponentsWithSameNameError struct { + name string +} -func NewComponentsWithSameNameError() ComponentsWithSameNameError { - return ComponentsWithSameNameError{} +func NewComponentsWithSameNameError(name string) ComponentsWithSameNameError { + return ComponentsWithSameNameError{ + name: name, + } } func (e ComponentsWithSameNameError) Error() string { - return "more than one component with the same name, should not happen" + return fmt.Sprintf("more than one component with the same name (%q), should not happen", e.name) } // ComponentTypeNotFoundError is returned when no component with the specified type has been found in Devfile diff --git a/pkg/libdevfile/libdevfile.go b/pkg/libdevfile/libdevfile.go index a22e9e9a3c0..eb1e2efad4f 100644 --- a/pkg/libdevfile/libdevfile.go +++ b/pkg/libdevfile/libdevfile.go @@ -202,49 +202,53 @@ func GetEndpointsFromDevfile(devfileObj parser.DevfileObj, ignoreExposures []v1a // GetComponentResourceManifestContentWithVariablesResolved returns the full content of either a Kubernetes or an Openshift // Devfile component, either Inlined or referenced via a URI. -// No matter how the component is defined, it returns -// the content with all variables substituted using the global variables map defined in `devfileObj`. +// No matter how the component is defined, it returns the content with all variables substituted +// using the global variables map defined in `devfileObj`. // An error is returned if the content references an invalid variable key not defined in the Devfile object. -func GetComponentResourceManifestContentWithVariablesResolved(devfileObj parser.DevfileObj, devfileCmp interface{}, +func GetComponentResourceManifestContentWithVariablesResolved(devfileObj parser.DevfileObj, devfileCmpName string, context string, fs devfilefs.Filesystem) (string, error) { - var content, uri string - switch devfileCmp := devfileCmp.(type) { - case v1alpha2.Component: - componentType, err := common.GetComponentType(devfileCmp) - if err != nil { - return "", err - } - switch componentType { - case v1alpha2.KubernetesComponentType: - return GetComponentResourceManifestContentWithVariablesResolved(devfileObj, devfileCmp.Kubernetes, context, fs) + components, err := devfileObj.Data.GetComponents(common.DevfileOptions{FilterByName: devfileCmpName}) + if err != nil { + return "", err + } - case v1alpha2.OpenshiftComponentType: - return GetComponentResourceManifestContentWithVariablesResolved(devfileObj, devfileCmp.Openshift, context, fs) + if len(components) == 0 { + return "", NewComponentNotExistError(devfileCmpName) + } - default: - return "", fmt.Errorf("unexpected component type %s", componentType) - } - case *v1alpha2.KubernetesComponent: - content = devfileCmp.Inlined - if devfileCmp.Uri != "" { - uri = devfileCmp.Uri + if len(components) != 1 { + return "", NewComponentsWithSameNameError(devfileCmpName) + } + + devfileCmp := components[0] + componentType, err := common.GetComponentType(devfileCmp) + if err != nil { + return "", err + } + + var content, uri string + switch componentType { + case v1alpha2.KubernetesComponentType: + content = devfileCmp.Kubernetes.Inlined + if devfileCmp.Kubernetes.Uri != "" { + uri = devfileCmp.Kubernetes.Uri } - case *v1alpha2.OpenshiftComponent: - content = devfileCmp.Inlined - if devfileCmp.Uri != "" { - uri = devfileCmp.Uri + case v1alpha2.OpenshiftComponentType: + content = devfileCmp.Openshift.Inlined + if devfileCmp.Openshift.Uri != "" { + uri = devfileCmp.Openshift.Uri } + default: - return "", fmt.Errorf("unexpected type for %v", devfileCmp) + return "", fmt.Errorf("unexpected component type %s", componentType) } - if uri == "" { - return substituteVariables(devfileObj.Data.GetDevfileWorkspaceSpec().Variables, content) + if uri != "" { + return loadResourceManifestFromUriAndResolveVariables(devfileObj, uri, context, fs) } - - return loadResourceManifestFromUriAndResolveVariables(devfileObj, uri, context, fs) + return substituteVariables(devfileObj.Data.GetDevfileWorkspaceSpec().Variables, content) } func loadResourceManifestFromUriAndResolveVariables(devfileObj parser.DevfileObj, uri string, diff --git a/pkg/libdevfile/libdevfile_test.go b/pkg/libdevfile/libdevfile_test.go index 4ad1c1bd1f5..28f9c96f72c 100644 --- a/pkg/libdevfile/libdevfile_test.go +++ b/pkg/libdevfile/libdevfile_test.go @@ -441,55 +441,99 @@ func TestGetEndpointsFromDevfile(t *testing.T) { func TestGetComponentResourceManifestContentWithVariablesResolved(t *testing.T) { fakeFs := devfileFileSystem.NewFakeFs() + cmpName := "my-cmp-1" for _, tt := range []struct { name string setupFunc func() error - devfileObjFunc func() (parser.DevfileObj, interface{}) - ctx string + devfileObjFunc func() parser.DevfileObj wantErr bool want string }{ { - name: "Container Component", - devfileObjFunc: func() (parser.DevfileObj, interface{}) { + name: "Missing Component", + devfileObjFunc: func() parser.DevfileObj { devfileData, _ := data.NewDevfileData(string(data.APISchemaVersion220)) cmp := generator.GetContainerComponent(generator.ContainerComponentParams{ - Name: "container-1", + Name: "a-different-component", }) - _ = devfileData.AddComponents([]v1alpha2.Component{cmp}) + s := v1alpha2.DevWorkspaceTemplateSpec{ + DevWorkspaceTemplateSpecContent: v1alpha2.DevWorkspaceTemplateSpecContent{ + Components: []v1alpha2.Component{cmp}, + }, + } + devfileData.SetDevfileWorkspaceSpec(s) return parser.DevfileObj{ Data: devfileData, - }, cmp + } }, wantErr: true, }, { - name: "Image Component", - devfileObjFunc: func() (parser.DevfileObj, interface{}) { + name: "Multiple Components with the same name", + devfileObjFunc: func() parser.DevfileObj { devfileData, _ := data.NewDevfileData(string(data.APISchemaVersion220)) - cmp := generator.GetImageComponent(generator.ImageComponentParams{ - Name: "image-1", + cmp1 := generator.GetContainerComponent(generator.ContainerComponentParams{ + Name: cmpName, }) - _ = devfileData.AddComponents([]v1alpha2.Component{cmp}) + cmp2 := generator.GetImageComponent(generator.ImageComponentParams{ + Name: cmpName, + }) + s := v1alpha2.DevWorkspaceTemplateSpec{ + DevWorkspaceTemplateSpecContent: v1alpha2.DevWorkspaceTemplateSpecContent{ + Components: []v1alpha2.Component{cmp1, cmp2}, + }, + } + devfileData.SetDevfileWorkspaceSpec(s) return parser.DevfileObj{ Data: devfileData, - }, cmp + } }, wantErr: true, }, { - name: "Unknown Component", - devfileObjFunc: func() (parser.DevfileObj, interface{}) { - return parser.DevfileObj{}, "unexpected-string-type" + name: "Container Component", + devfileObjFunc: func() parser.DevfileObj { + devfileData, _ := data.NewDevfileData(string(data.APISchemaVersion220)) + cmp := generator.GetContainerComponent(generator.ContainerComponentParams{ + Name: cmpName, + }) + s := v1alpha2.DevWorkspaceTemplateSpec{ + DevWorkspaceTemplateSpecContent: v1alpha2.DevWorkspaceTemplateSpecContent{ + Components: []v1alpha2.Component{cmp}, + }, + } + devfileData.SetDevfileWorkspaceSpec(s) + return parser.DevfileObj{ + Data: devfileData, + } + }, + wantErr: true, + }, + { + name: "Image Component", + devfileObjFunc: func() parser.DevfileObj { + devfileData, _ := data.NewDevfileData(string(data.APISchemaVersion220)) + cmp := generator.GetImageComponent(generator.ImageComponentParams{ + Name: cmpName, + }) + s := v1alpha2.DevWorkspaceTemplateSpec{ + DevWorkspaceTemplateSpecContent: v1alpha2.DevWorkspaceTemplateSpecContent{ + Components: []v1alpha2.Component{cmp}, + }, + } + devfileData.SetDevfileWorkspaceSpec(s) + return parser.DevfileObj{ + Data: devfileData, + } }, wantErr: true, }, { name: "Kubernetes Component - Inlined with no variables", - devfileObjFunc: func() (parser.DevfileObj, interface{}) { + devfileObjFunc: func() parser.DevfileObj { devfileData, _ := data.NewDevfileData(string(data.APISchemaVersion220)) cmp := generator.GetKubernetesComponent(generator.KubernetesComponentParams{ - Name: "my-k8s-1", + Name: cmpName, Kubernetes: &v1alpha2.KubernetesComponent{ K8sLikeComponent: v1alpha2.K8sLikeComponent{ K8sLikeComponentLocation: v1alpha2.K8sLikeComponentLocation{ @@ -498,20 +542,25 @@ func TestGetComponentResourceManifestContentWithVariablesResolved(t *testing.T) }, }, }) - _ = devfileData.AddComponents([]v1alpha2.Component{cmp}) + s := v1alpha2.DevWorkspaceTemplateSpec{ + DevWorkspaceTemplateSpecContent: v1alpha2.DevWorkspaceTemplateSpecContent{ + Components: []v1alpha2.Component{cmp}, + }, + } + devfileData.SetDevfileWorkspaceSpec(s) return parser.DevfileObj{ Data: devfileData, - }, cmp + } }, wantErr: false, want: "some-text-inlined", }, { name: "Kubernetes Component - Inlined with variables", - devfileObjFunc: func() (parser.DevfileObj, interface{}) { + devfileObjFunc: func() parser.DevfileObj { devfileData, _ := data.NewDevfileData(string(data.APISchemaVersion220)) cmp := generator.GetKubernetesComponent(generator.KubernetesComponentParams{ - Name: "my-k8s-1", + Name: cmpName, Kubernetes: &v1alpha2.KubernetesComponent{ K8sLikeComponent: v1alpha2.K8sLikeComponent{ K8sLikeComponentLocation: v1alpha2.K8sLikeComponentLocation{ @@ -520,28 +569,28 @@ func TestGetComponentResourceManifestContentWithVariablesResolved(t *testing.T) }, }, }) - _ = devfileData.AddComponents([]v1alpha2.Component{cmp}) s := v1alpha2.DevWorkspaceTemplateSpec{ DevWorkspaceTemplateSpecContent: v1alpha2.DevWorkspaceTemplateSpecContent{ Variables: map[string]string{ "MY_CONTAINER_IMAGE": "quay.io/unknown-account/my-image:1.2.3", }, + Components: []v1alpha2.Component{cmp}, }, } devfileData.SetDevfileWorkspaceSpec(s) return parser.DevfileObj{ Data: devfileData, - }, cmp + } }, wantErr: false, want: "image: quay.io/unknown-account/my-image:1.2.3", }, { name: "Kubernetes Component - Inlined with unknown variables", - devfileObjFunc: func() (parser.DevfileObj, interface{}) { + devfileObjFunc: func() parser.DevfileObj { devfileData, _ := data.NewDevfileData(string(data.APISchemaVersion220)) cmp := generator.GetKubernetesComponent(generator.KubernetesComponentParams{ - Name: "my-k8s-1", + Name: cmpName, Kubernetes: &v1alpha2.KubernetesComponent{ K8sLikeComponent: v1alpha2.K8sLikeComponent{ K8sLikeComponentLocation: v1alpha2.K8sLikeComponentLocation{ @@ -550,28 +599,28 @@ func TestGetComponentResourceManifestContentWithVariablesResolved(t *testing.T) }, }, }) - _ = devfileData.AddComponents([]v1alpha2.Component{cmp}) s := v1alpha2.DevWorkspaceTemplateSpec{ DevWorkspaceTemplateSpecContent: v1alpha2.DevWorkspaceTemplateSpecContent{ Variables: map[string]string{ "MY_CONTAINER_IMAGE": "quay.io/unknown-account/my-image", }, + Components: []v1alpha2.Component{cmp}, }, } devfileData.SetDevfileWorkspaceSpec(s) return parser.DevfileObj{ Data: devfileData, - }, cmp + } }, wantErr: true, want: "image: quay.io/unknown-account/my-image:{{ MY_CONTAINER_IMAGE_VERSION_UNKNOWN }}", }, { name: "Kubernetes Component - non-existing external file", - devfileObjFunc: func() (parser.DevfileObj, interface{}) { + devfileObjFunc: func() parser.DevfileObj { devfileData, _ := data.NewDevfileData(string(data.APISchemaVersion220)) cmp := generator.GetKubernetesComponent(generator.KubernetesComponentParams{ - Name: "my-k8s-1", + Name: cmpName, Kubernetes: &v1alpha2.KubernetesComponent{ K8sLikeComponent: v1alpha2.K8sLikeComponent{ K8sLikeComponentLocation: v1alpha2.K8sLikeComponentLocation{ @@ -580,10 +629,15 @@ func TestGetComponentResourceManifestContentWithVariablesResolved(t *testing.T) }, }, }) - _ = devfileData.AddComponents([]v1alpha2.Component{cmp}) + s := v1alpha2.DevWorkspaceTemplateSpec{ + DevWorkspaceTemplateSpecContent: v1alpha2.DevWorkspaceTemplateSpecContent{ + Components: []v1alpha2.Component{cmp}, + }, + } + devfileData.SetDevfileWorkspaceSpec(s) return parser.DevfileObj{ Data: devfileData, - }, cmp + } }, wantErr: true, }, @@ -594,10 +648,10 @@ func TestGetComponentResourceManifestContentWithVariablesResolved(t *testing.T) []byte("some-text-with-no-variables"), os.ModePerm) }, - devfileObjFunc: func() (parser.DevfileObj, interface{}) { + devfileObjFunc: func() parser.DevfileObj { devfileData, _ := data.NewDevfileData(string(data.APISchemaVersion220)) cmp := generator.GetKubernetesComponent(generator.KubernetesComponentParams{ - Name: "my-k8s-1", + Name: cmpName, Kubernetes: &v1alpha2.KubernetesComponent{ K8sLikeComponent: v1alpha2.K8sLikeComponent{ K8sLikeComponentLocation: v1alpha2.K8sLikeComponentLocation{ @@ -606,10 +660,15 @@ func TestGetComponentResourceManifestContentWithVariablesResolved(t *testing.T) }, }, }) - _ = devfileData.AddComponents([]v1alpha2.Component{cmp}) + s := v1alpha2.DevWorkspaceTemplateSpec{ + DevWorkspaceTemplateSpecContent: v1alpha2.DevWorkspaceTemplateSpecContent{ + Components: []v1alpha2.Component{cmp}, + }, + } + devfileData.SetDevfileWorkspaceSpec(s) return parser.DevfileObj{ Data: devfileData, - }, cmp + } }, wantErr: false, want: "some-text-with-no-variables", @@ -621,10 +680,10 @@ func TestGetComponentResourceManifestContentWithVariablesResolved(t *testing.T) []byte("image: {{ MY_CONTAINER_IMAGE }}:{{MY_CONTAINER_IMAGE_VERSION}}"), os.ModePerm) }, - devfileObjFunc: func() (parser.DevfileObj, interface{}) { + devfileObjFunc: func() parser.DevfileObj { devfileData, _ := data.NewDevfileData(string(data.APISchemaVersion220)) cmp := generator.GetKubernetesComponent(generator.KubernetesComponentParams{ - Name: "my-k8s-1", + Name: cmpName, Kubernetes: &v1alpha2.KubernetesComponent{ K8sLikeComponent: v1alpha2.K8sLikeComponent{ K8sLikeComponentLocation: v1alpha2.K8sLikeComponentLocation{ @@ -633,19 +692,19 @@ func TestGetComponentResourceManifestContentWithVariablesResolved(t *testing.T) }, }, }) - _ = devfileData.AddComponents([]v1alpha2.Component{cmp}) s := v1alpha2.DevWorkspaceTemplateSpec{ DevWorkspaceTemplateSpecContent: v1alpha2.DevWorkspaceTemplateSpecContent{ Variables: map[string]string{ "MY_CONTAINER_IMAGE": "quay.io/unknown-account/my-image", "MY_CONTAINER_IMAGE_VERSION": "1.2.3", }, + Components: []v1alpha2.Component{cmp}, }, } devfileData.SetDevfileWorkspaceSpec(s) return parser.DevfileObj{ Data: devfileData, - }, cmp + } }, wantErr: false, want: "image: quay.io/unknown-account/my-image:1.2.3", @@ -657,10 +716,10 @@ func TestGetComponentResourceManifestContentWithVariablesResolved(t *testing.T) []byte("image: {{MY_CONTAINER_IMAGE}}:{{ MY_CONTAINER_IMAGE_VERSION_UNKNOWN }}"), os.ModePerm) }, - devfileObjFunc: func() (parser.DevfileObj, interface{}) { + devfileObjFunc: func() parser.DevfileObj { devfileData, _ := data.NewDevfileData(string(data.APISchemaVersion220)) cmp := generator.GetKubernetesComponent(generator.KubernetesComponentParams{ - Name: "my-k8s-1", + Name: cmpName, Kubernetes: &v1alpha2.KubernetesComponent{ K8sLikeComponent: v1alpha2.K8sLikeComponent{ K8sLikeComponentLocation: v1alpha2.K8sLikeComponentLocation{ @@ -669,18 +728,18 @@ func TestGetComponentResourceManifestContentWithVariablesResolved(t *testing.T) }, }, }) - _ = devfileData.AddComponents([]v1alpha2.Component{cmp}) s := v1alpha2.DevWorkspaceTemplateSpec{ DevWorkspaceTemplateSpecContent: v1alpha2.DevWorkspaceTemplateSpecContent{ Variables: map[string]string{ "MY_CONTAINER_IMAGE": "quay.io/unknown-account/my-image", }, + Components: []v1alpha2.Component{cmp}, }, } devfileData.SetDevfileWorkspaceSpec(s) return parser.DevfileObj{ Data: devfileData, - }, cmp + } }, wantErr: true, want: "image: quay.io/unknown-account/my-image:{{ MY_CONTAINER_IMAGE_VERSION_UNKNOWN }}", @@ -693,8 +752,12 @@ func TestGetComponentResourceManifestContentWithVariablesResolved(t *testing.T) return } } - devfileObj, devfileCmp := tt.devfileObjFunc() - got, err := GetComponentResourceManifestContentWithVariablesResolved(devfileObj, devfileCmp, tt.ctx, fakeFs) + if tt.devfileObjFunc == nil { + t.Error("devfileObjFunc function not defined for test case") + return + } + + got, err := GetComponentResourceManifestContentWithVariablesResolved(tt.devfileObjFunc(), cmpName, "", fakeFs) if (err != nil) != tt.wantErr { t.Errorf("GetComponentResourceManifestContentWithVariablesResolved() error = %v, wantErr %v", err, tt.wantErr) diff --git a/pkg/service/link.go b/pkg/service/link.go index 5a772ffdd26..3887c7a2043 100644 --- a/pkg/service/link.go +++ b/pkg/service/link.go @@ -69,7 +69,7 @@ func pushLinksWithOperator(client kclient.ClientInterface, devfileObj parser.Dev var strCRD string for _, c := range k8sComponents { // get the string representation of the YAML definition of a CRD - strCRD, err = libdevfile.GetComponentResourceManifestContentWithVariablesResolved(devfileObj, c.Kubernetes, context, devfilefs.DefaultFs{}) + strCRD, err = libdevfile.GetComponentResourceManifestContentWithVariablesResolved(devfileObj, c.Name, context, devfilefs.DefaultFs{}) if err != nil { return false, err } @@ -153,7 +153,7 @@ func pushLinksWithoutOperator(client kclient.ClientInterface, devfileObj parser. var strCRD string for _, c := range k8sComponents { // get the string representation of the YAML definition of a CRD - strCRD, err = libdevfile.GetComponentResourceManifestContentWithVariablesResolved(devfileObj, c.Kubernetes, context, devfilefs.DefaultFs{}) + strCRD, err = libdevfile.GetComponentResourceManifestContentWithVariablesResolved(devfileObj, c.Name, context, devfilefs.DefaultFs{}) if err != nil { return false, err } diff --git a/pkg/service/service.go b/pkg/service/service.go index 0a76b2183b8..8b6c864f158 100644 --- a/pkg/service/service.go +++ b/pkg/service/service.go @@ -154,7 +154,7 @@ func listDevfileLinks(devfileObj parser.DevfileObj, context string, fs devfilefs } var services []string for _, c := range components { - u, err := libdevfile.GetK8sComponentAsUnstructured(devfileObj, c.Kubernetes, context, fs) + u, err := libdevfile.GetK8sComponentAsUnstructured(devfileObj, c.Name, context, fs) if err != nil { return nil, err } @@ -209,7 +209,7 @@ func PushKubernetesResources(client kclient.ClientInterface, devfileObj parser.D // create an object on the kubernetes cluster for all the Kubernetes Inlined components for _, c := range k8sComponents { - u, er := libdevfile.GetK8sComponentAsUnstructured(devfileObj, c.Kubernetes, context, devfilefs.DefaultFs{}) + u, er := libdevfile.GetK8sComponentAsUnstructured(devfileObj, c.Name, context, devfilefs.DefaultFs{}) if er != nil { return er } @@ -330,7 +330,7 @@ func ListDeployedServices(client kclient.ClientInterface, labels map[string]stri func UpdateServicesWithOwnerReferences(client kclient.ClientInterface, devfileObj parser.DevfileObj, k8sComponents []devfile.Component, ownerReference metav1.OwnerReference, context string) error { for _, c := range k8sComponents { // get the string representation of the YAML definition of a CRD - u, err := libdevfile.GetK8sComponentAsUnstructured(devfileObj, c.Kubernetes, context, devfilefs.DefaultFs{}) + u, err := libdevfile.GetK8sComponentAsUnstructured(devfileObj, c.Name, context, devfilefs.DefaultFs{}) if err != nil { return err } @@ -424,7 +424,7 @@ func ValidateResourcesExist(client kclient.ClientInterface, devfileObj parser.De func ValidateResourceExist(client kclient.ClientInterface, devfileObj parser.DevfileObj, k8sComponent devfile.Component, context string) (kindErr string, err error) { // get the string representation of the YAML definition of a CRD - u, err := libdevfile.GetK8sComponentAsUnstructured(devfileObj, k8sComponent.Kubernetes, context, devfilefs.DefaultFs{}) + u, err := libdevfile.GetK8sComponentAsUnstructured(devfileObj, k8sComponent.Name, context, devfilefs.DefaultFs{}) if err != nil { return "", err } From 46d941194ec536a8a3f14aafd83c01ca84597251 Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Tue, 3 May 2022 16:30:47 +0200 Subject: [PATCH 5/7] Rename 'GetComponentResourceManifestContentWithVariablesResolved' with 'GetK8sManifestWithVariablesSubstituted' Previous name was a bit long ^^ --- pkg/libdevfile/component_kubernetes_utils.go | 2 +- pkg/libdevfile/libdevfile.go | 4 ++-- pkg/libdevfile/libdevfile_test.go | 8 ++++---- pkg/service/link.go | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pkg/libdevfile/component_kubernetes_utils.go b/pkg/libdevfile/component_kubernetes_utils.go index 9107884f7ed..7a715545055 100644 --- a/pkg/libdevfile/component_kubernetes_utils.go +++ b/pkg/libdevfile/component_kubernetes_utils.go @@ -13,7 +13,7 @@ import ( func GetK8sComponentAsUnstructured(devfileObj parser.DevfileObj, componentName string, context string, fs devfilefs.Filesystem) (unstructured.Unstructured, error) { - strCRD, err := GetComponentResourceManifestContentWithVariablesResolved(devfileObj, componentName, context, fs) + strCRD, err := GetK8sManifestWithVariablesSubstituted(devfileObj, componentName, context, fs) if err != nil { return unstructured.Unstructured{}, err } diff --git a/pkg/libdevfile/libdevfile.go b/pkg/libdevfile/libdevfile.go index eb1e2efad4f..9a3ff5ce0a7 100644 --- a/pkg/libdevfile/libdevfile.go +++ b/pkg/libdevfile/libdevfile.go @@ -200,12 +200,12 @@ func GetEndpointsFromDevfile(devfileObj parser.DevfileObj, ignoreExposures []v1a return endpoints, nil } -// GetComponentResourceManifestContentWithVariablesResolved returns the full content of either a Kubernetes or an Openshift +// GetK8sManifestWithVariablesSubstituted returns the full content of either a Kubernetes or an Openshift // Devfile component, either Inlined or referenced via a URI. // No matter how the component is defined, it returns the content with all variables substituted // using the global variables map defined in `devfileObj`. // An error is returned if the content references an invalid variable key not defined in the Devfile object. -func GetComponentResourceManifestContentWithVariablesResolved(devfileObj parser.DevfileObj, devfileCmpName string, +func GetK8sManifestWithVariablesSubstituted(devfileObj parser.DevfileObj, devfileCmpName string, context string, fs devfilefs.Filesystem) (string, error) { components, err := devfileObj.Data.GetComponents(common.DevfileOptions{FilterByName: devfileCmpName}) diff --git a/pkg/libdevfile/libdevfile_test.go b/pkg/libdevfile/libdevfile_test.go index 28f9c96f72c..436c797d2ad 100644 --- a/pkg/libdevfile/libdevfile_test.go +++ b/pkg/libdevfile/libdevfile_test.go @@ -439,7 +439,7 @@ func TestGetEndpointsFromDevfile(t *testing.T) { } } -func TestGetComponentResourceManifestContentWithVariablesResolved(t *testing.T) { +func TestGetK8sManifestWithVariablesSubstituted(t *testing.T) { fakeFs := devfileFileSystem.NewFakeFs() cmpName := "my-cmp-1" for _, tt := range []struct { @@ -757,14 +757,14 @@ func TestGetComponentResourceManifestContentWithVariablesResolved(t *testing.T) return } - got, err := GetComponentResourceManifestContentWithVariablesResolved(tt.devfileObjFunc(), cmpName, "", fakeFs) + got, err := GetK8sManifestWithVariablesSubstituted(tt.devfileObjFunc(), cmpName, "", fakeFs) if (err != nil) != tt.wantErr { - t.Errorf("GetComponentResourceManifestContentWithVariablesResolved() error = %v, wantErr %v", + t.Errorf("GetK8sManifestWithVariablesSubstituted() error = %v, wantErr %v", err, tt.wantErr) return } if got != tt.want { - t.Errorf("GetComponentResourceManifestContentWithVariablesResolved() got = %v, want %v", + t.Errorf("GetK8sManifestWithVariablesSubstituted() got = %v, want %v", got, tt.want) } }) diff --git a/pkg/service/link.go b/pkg/service/link.go index 3887c7a2043..ab55a841669 100644 --- a/pkg/service/link.go +++ b/pkg/service/link.go @@ -69,7 +69,7 @@ func pushLinksWithOperator(client kclient.ClientInterface, devfileObj parser.Dev var strCRD string for _, c := range k8sComponents { // get the string representation of the YAML definition of a CRD - strCRD, err = libdevfile.GetComponentResourceManifestContentWithVariablesResolved(devfileObj, c.Name, context, devfilefs.DefaultFs{}) + strCRD, err = libdevfile.GetK8sManifestWithVariablesSubstituted(devfileObj, c.Name, context, devfilefs.DefaultFs{}) if err != nil { return false, err } @@ -153,7 +153,7 @@ func pushLinksWithoutOperator(client kclient.ClientInterface, devfileObj parser. var strCRD string for _, c := range k8sComponents { // get the string representation of the YAML definition of a CRD - strCRD, err = libdevfile.GetComponentResourceManifestContentWithVariablesResolved(devfileObj, c.Name, context, devfilefs.DefaultFs{}) + strCRD, err = libdevfile.GetK8sManifestWithVariablesSubstituted(devfileObj, c.Name, context, devfilefs.DefaultFs{}) if err != nil { return false, err } From 951ec8cd8892d08a0ba86ac05a8bd63a73fa0f64 Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Tue, 3 May 2022 17:12:21 +0200 Subject: [PATCH 6/7] Remove extra parentheses in error string returned by 'ComponentsWithSameNameError#Error', as suggested in review --- pkg/libdevfile/errors.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/libdevfile/errors.go b/pkg/libdevfile/errors.go index 5e63c22ebdc..753cac6629d 100644 --- a/pkg/libdevfile/errors.go +++ b/pkg/libdevfile/errors.go @@ -75,7 +75,7 @@ func NewComponentsWithSameNameError(name string) ComponentsWithSameNameError { } func (e ComponentsWithSameNameError) Error() string { - return fmt.Sprintf("more than one component with the same name (%q), should not happen", e.name) + return fmt.Sprintf("more than one component with the same name %q, should not happen", e.name) } // ComponentTypeNotFoundError is returned when no component with the specified type has been found in Devfile From 614bc60e2915bad5e60dd2964006869fedc71dca Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Wed, 4 May 2022 16:21:54 +0200 Subject: [PATCH 7/7] Revert "Switch to using 'uri' Kubernetes components in test Devfiles" This reverts commit df1f19ed959b8c82aa17ac3cf12c343305789149. This will be done in a separate PR, with ideally changes that should allow to use the same set of tests for testing both Inlined and URI-referenced manifests. --- pkg/component/delete/delete_test.go | 12 ++-- ....yaml => devfile-deploy-with-k8s-uri.yaml} | 23 +------ ...evfile-deploy-with-multiple-resources.yaml | 4 -- .../devfiles/nodejs/devfile-deploy.yaml | 23 ++++++- ...roject_source-in-docker-build-context.yaml | 38 ++++++++++- .../devfiles/nodejs/devfile-with-link.yaml | 65 ++++++++++++++++++- .../devfiles/nodejs/devfile-with-pod.yaml | 25 ++++++- .../devfile-with-two-deploy-commands.yaml | 23 ++++++- ...h-image-component-and-no-buildContext.yaml | 37 ++++++++++- .../outerloop-deploy.yaml | 18 ----- .../outerloop-service.yaml | 15 ----- .../kubernetes/devfile-with-link/myredis.yaml | 41 ------------ .../devfile-with-link/redis-link.yaml | 20 ------ .../devfile-with-pod/etcdcluster.yaml | 9 --- .../kubernetes/devfile-with-pod/nginx.yaml | 12 ---- .../outerloop-deploy.yaml | 21 ------ .../outerloop-deploy.yaml | 18 ----- .../outerloop-service.yaml | 15 ----- ...-deploy.yaml => outerloop-deployment.yaml} | 2 +- .../devfile/cmd_devfile_build_images_test.go | 7 -- .../devfile/cmd_devfile_deploy_test.go | 34 ++++------ .../devfile/cmd_devfile_init_test.go | 2 - .../devfile/cmd_devfile_list_test.go | 2 - 23 files changed, 221 insertions(+), 245 deletions(-) rename tests/examples/source/devfiles/nodejs/{devfile-deploy-with-k8s-inlined.yaml => devfile-deploy-with-k8s-uri.yaml} (77%) delete mode 100644 tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-outerloop-project_source-in-docker-build-context/outerloop-deploy.yaml delete mode 100644 tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-outerloop-project_source-in-docker-build-context/outerloop-service.yaml delete mode 100644 tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-link/myredis.yaml delete mode 100644 tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-link/redis-link.yaml delete mode 100644 tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-pod/etcdcluster.yaml delete mode 100644 tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-pod/nginx.yaml delete mode 100644 tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-two-deploy-commands/outerloop-deploy.yaml delete mode 100644 tests/examples/source/devfiles/nodejs/project/kubernetes/issue-5600-devfile-with-image-component-and-no-buildContext/outerloop-deploy.yaml delete mode 100644 tests/examples/source/devfiles/nodejs/project/kubernetes/issue-5600-devfile-with-image-component-and-no-buildContext/outerloop-service.yaml rename tests/examples/source/devfiles/nodejs/project/kubernetes/{devfile-deploy/outerloop-deploy.yaml => outerloop-deployment.yaml} (95%) diff --git a/pkg/component/delete/delete_test.go b/pkg/component/delete/delete_test.go index 637be50f825..f1548d35ef6 100644 --- a/pkg/component/delete/delete_test.go +++ b/pkg/component/delete/delete_test.go @@ -324,7 +324,7 @@ func TestDeleteComponentClient_ListResourcesToDeleteFromDevfile(t *testing.T) { }, }, args: args{ - devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy-with-k8s-inlined.yaml"), + devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy.yaml"), appName: appName, }, wantIsInnerLoopDeployed: true, @@ -371,7 +371,7 @@ func TestDeleteComponentClient_ListResourcesToDeleteFromDevfile(t *testing.T) { }, }, args: args{ - devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy-with-k8s-inlined.yaml"), + devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy.yaml"), appName: appName, }, wantIsInnerLoopDeployed: false, @@ -388,7 +388,7 @@ func TestDeleteComponentClient_ListResourcesToDeleteFromDevfile(t *testing.T) { }, }, args: args{ - devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy-with-k8s-inlined.yaml"), + devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy.yaml"), appName: appName, }, wantIsInnerLoopDeployed: false, @@ -406,7 +406,7 @@ func TestDeleteComponentClient_ListResourcesToDeleteFromDevfile(t *testing.T) { }, }, args: args{ - devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy-with-k8s-inlined.yaml"), + devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy.yaml"), appName: appName, }, wantIsInnerLoopDeployed: true, @@ -427,7 +427,7 @@ func TestDeleteComponentClient_ListResourcesToDeleteFromDevfile(t *testing.T) { }, }, args: args{ - devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy-with-k8s-inlined.yaml"), + devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy.yaml"), appName: appName, }, wantIsInnerLoopDeployed: true, @@ -487,7 +487,7 @@ func TestDeleteComponentClient_ExecutePreStopEvents(t *testing.T) { }, }, args: args{ - devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy-with-k8s-inlined.yaml"), + devfileObj: odoTestingUtil.GetTestDevfileObjFromFile("devfile-deploy.yaml"), appName: appName, }, wantErr: false, diff --git a/tests/examples/source/devfiles/nodejs/devfile-deploy-with-k8s-inlined.yaml b/tests/examples/source/devfiles/nodejs/devfile-deploy-with-k8s-uri.yaml similarity index 77% rename from tests/examples/source/devfiles/nodejs/devfile-deploy-with-k8s-inlined.yaml rename to tests/examples/source/devfiles/nodejs/devfile-deploy-with-k8s-uri.yaml index 8cf0f27dd47..54eb4d90f59 100644 --- a/tests/examples/source/devfiles/nodejs/devfile-deploy-with-k8s-inlined.yaml +++ b/tests/examples/source/devfiles/nodejs/devfile-deploy-with-k8s-uri.yaml @@ -86,25 +86,4 @@ components: uri: ./Dockerfile - name: outerloop-deploy kubernetes: - inlined: | - kind: Deployment - apiVersion: apps/v1 - metadata: - name: my-component - spec: - replicas: 1 - selector: - matchLabels: - app: node-app - template: - metadata: - labels: - app: node-app - spec: - containers: - - name: main - image: {{CONTAINER_IMAGE}} - resources: - limits: - memory: "128Mi" - cpu: "500m" + uri: 'kubernetes/outerloop-deployment.yaml' diff --git a/tests/examples/source/devfiles/nodejs/devfile-deploy-with-multiple-resources.yaml b/tests/examples/source/devfiles/nodejs/devfile-deploy-with-multiple-resources.yaml index 5fbab94291f..870a49e3dbc 100644 --- a/tests/examples/source/devfiles/nodejs/devfile-deploy-with-multiple-resources.yaml +++ b/tests/examples/source/devfiles/nodejs/devfile-deploy-with-multiple-resources.yaml @@ -69,8 +69,6 @@ components: - name: outerloop-deploy kubernetes: - # TODO(rm3l): Move this as a URI by default once https://github.com/redhat-developer/odo/issues/5637 is fixed - # Also consider keeping an "Inlined" version for testing inlined: | kind: Deployment apiVersion: apps/v1 @@ -95,8 +93,6 @@ components: cpu: "500m" - name: outerloop-deploy-2 kubernetes: - # TODO(rm3l): Move this as a URI by default once https://github.com/redhat-developer/odo/issues/5637 is fixed - # Also consider keeping an "Inlined" version for testing inlined: | apiVersion: v1 kind: Service diff --git a/tests/examples/source/devfiles/nodejs/devfile-deploy.yaml b/tests/examples/source/devfiles/nodejs/devfile-deploy.yaml index d8424156eb3..ada31e2b5ca 100644 --- a/tests/examples/source/devfiles/nodejs/devfile-deploy.yaml +++ b/tests/examples/source/devfiles/nodejs/devfile-deploy.yaml @@ -65,7 +65,28 @@ components: - name: outerloop-deploy kubernetes: - uri: kubernetes/devfile-deploy/outerloop-deploy.yaml + inlined: | + kind: Deployment + apiVersion: apps/v1 + metadata: + name: my-component + spec: + replicas: 1 + selector: + matchLabels: + app: node-app + template: + metadata: + labels: + app: node-app + spec: + containers: + - name: main + image: {{CONTAINER_IMAGE}} + resources: + limits: + memory: "128Mi" + cpu: "500m" metadata: description: Stack with Node.js 14 displayName: Node.js Runtime diff --git a/tests/examples/source/devfiles/nodejs/devfile-outerloop-project_source-in-docker-build-context.yaml b/tests/examples/source/devfiles/nodejs/devfile-outerloop-project_source-in-docker-build-context.yaml index 2b5a004a34f..71bd0b76cf9 100644 --- a/tests/examples/source/devfiles/nodejs/devfile-outerloop-project_source-in-docker-build-context.yaml +++ b/tests/examples/source/devfiles/nodejs/devfile-outerloop-project_source-in-docker-build-context.yaml @@ -58,7 +58,41 @@ components: buildContext: ${PROJECT_SOURCE} - name: outerloop-deploy kubernetes: - uri: kubernetes/devfile-outerloop-project_source-in-docker-build-context/outerloop-deploy.yaml + inlined: | + kind: Deployment + apiVersion: apps/v1 + metadata: + name: devfile-nodejs-deploy + spec: + replicas: 1 + selector: + matchLabels: + app: devfile-nodejs-deploy + template: + metadata: + labels: + app: devfile-nodejs-deploy + spec: + containers: + - name: main + image: "{{CONTAINER_IMAGE}}" + resources: {} - name: outerloop-service kubernetes: - uri: kubernetes/devfile-outerloop-project_source-in-docker-build-context/outerloop-service.yaml + inlined: | + apiVersion: v1 + kind: Service + metadata: + labels: + app: devfile-nodejs-deploy + name: devfile-nodejs-deploy + spec: + ports: + - name: http-3000 + port: 3000 + protocol: TCP + targetPort: 3000 + selector: + app: devfile-nodejs-deploy + type: LoadBalancer + diff --git a/tests/examples/source/devfiles/nodejs/devfile-with-link.yaml b/tests/examples/source/devfiles/nodejs/devfile-with-link.yaml index 2079621ba3c..6e7cae607ca 100644 --- a/tests/examples/source/devfiles/nodejs/devfile-with-link.yaml +++ b/tests/examples/source/devfiles/nodejs/devfile-with-link.yaml @@ -42,10 +42,71 @@ components: sourceMapping: /project name: runtime - kubernetes: - uri: kubernetes/devfile-with-link/myredis.yaml + inlined: | + apiVersion: redis.redis.opstreelabs.in/v1beta1 + kind: Redis + metadata: + name: myredis + annotations: + service.binding/name: path={.metadata.name} + spec: + redisExporter: + enabled: true + image: 'quay.io/opstree/redis-exporter:1.0' + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + kubernetesConfig: + image: 'quay.io/opstree/redis:v6.2' + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisSecret: + name: redis-secret + key: password + serviceType: LoadBalancer + redisConfig: {} + storage: + volumeClaimTemplate: + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi name: myredis - kubernetes: - uri: kubernetes/devfile-with-link/redis-link.yaml + inlined: | + apiVersion: binding.operators.coreos.com/v1alpha1 + kind: ServiceBinding + metadata: + creationTimestamp: null + name: redis-link + spec: + application: + group: apps + name: api-app + resource: deployments + version: v1 + bindAsFiles: true + detectBindingResources: true + services: + - group: redis.redis.opstreelabs.in + kind: Redis + name: myredis + version: v1beta1 + status: + secret: "" name: redis-link metadata: description: Stack with Node.js 14 diff --git a/tests/examples/source/devfiles/nodejs/devfile-with-pod.yaml b/tests/examples/source/devfiles/nodejs/devfile-with-pod.yaml index f704739b523..dd6409a6a1d 100644 --- a/tests/examples/source/devfiles/nodejs/devfile-with-pod.yaml +++ b/tests/examples/source/devfiles/nodejs/devfile-with-pod.yaml @@ -24,10 +24,31 @@ components: sourceMapping: /project name: runtime - kubernetes: - uri: kubernetes/devfile-with-pod/etcdcluster.yaml + inlined: | + apiVersion: etcd.database.coreos.com/v1beta2 + kind: EtcdCluster + metadata: + annotations: + etcd.database.coreos.com/scope: clusterwide + name: etcdcluster + spec: + size: 3 + version: 3.2.13 name: etcdcluster - kubernetes: - uri: kubernetes/devfile-with-pod/nginx.yaml + inlined: | + apiVersion: v1 + kind: Pod + metadata: + labels: + name: nginx + name: nginx + spec: + containers: + - image: quay.io/bitnami/nginx + name: nginx + ports: + - containerPort: 80 name: nginx commands: - exec: diff --git a/tests/examples/source/devfiles/nodejs/devfile-with-two-deploy-commands.yaml b/tests/examples/source/devfiles/nodejs/devfile-with-two-deploy-commands.yaml index 09a8e348618..ec4b66c45ec 100644 --- a/tests/examples/source/devfiles/nodejs/devfile-with-two-deploy-commands.yaml +++ b/tests/examples/source/devfiles/nodejs/devfile-with-two-deploy-commands.yaml @@ -72,7 +72,28 @@ components: - name: outerloop-deploy kubernetes: - uri: kubernetes/devfile-with-two-deploy-commands/outerloop-deploy.yaml + inlined: | + kind: Deployment + apiVersion: apps/v1 + metadata: + name: my-component + spec: + replicas: 1 + selector: + matchLabels: + app: node-app + template: + metadata: + labels: + app: node-app + spec: + containers: + - name: main + image: {{CONTAINER_IMAGE}} + resources: + limits: + memory: "128Mi" + cpu: "500m" metadata: description: Stack with Node.js 14 displayName: Node.js Runtime diff --git a/tests/examples/source/devfiles/nodejs/issue-5600-devfile-with-image-component-and-no-buildContext.yaml b/tests/examples/source/devfiles/nodejs/issue-5600-devfile-with-image-component-and-no-buildContext.yaml index 559a0301e7d..bd00d831918 100644 --- a/tests/examples/source/devfiles/nodejs/issue-5600-devfile-with-image-component-and-no-buildContext.yaml +++ b/tests/examples/source/devfiles/nodejs/issue-5600-devfile-with-image-component-and-no-buildContext.yaml @@ -48,10 +48,43 @@ components: imageName: localhost:5000/devfile-nodejs-deploy:0.1.0 name: prod-image - kubernetes: - uri: kubernetes/issue-5600-devfile-with-image-component-and-no-buildContext/outerloop-deploy.yaml + inlined: | + kind: Deployment + apiVersion: apps/v1 + metadata: + name: devfile-nodejs-deploy + spec: + replicas: 1 + selector: + matchLabels: + app: devfile-nodejs-deploy + template: + metadata: + labels: + app: devfile-nodejs-deploy + spec: + containers: + - name: main + image: "localhost:5000/devfile-nodejs-deploy:0.1.0" + resources: {} name: outerloop-deploy - kubernetes: - uri: kubernetes/issue-5600-devfile-with-image-component-and-no-buildContext/outerloop-service.yaml + inlined: | + apiVersion: v1 + kind: Service + metadata: + labels: + app: devfile-nodejs-deploy + name: devfile-nodejs-deploy + spec: + ports: + - name: http-3000 + port: 3000 + protocol: TCP + targetPort: 3000 + selector: + app: devfile-nodejs-deploy + type: LoadBalancer name: outerloop-service metadata: language: javascript diff --git a/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-outerloop-project_source-in-docker-build-context/outerloop-deploy.yaml b/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-outerloop-project_source-in-docker-build-context/outerloop-deploy.yaml deleted file mode 100644 index c73a309e8e0..00000000000 --- a/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-outerloop-project_source-in-docker-build-context/outerloop-deploy.yaml +++ /dev/null @@ -1,18 +0,0 @@ -kind: Deployment -apiVersion: apps/v1 -metadata: - name: devfile-nodejs-deploy -spec: - replicas: 1 - selector: - matchLabels: - app: devfile-nodejs-deploy - template: - metadata: - labels: - app: devfile-nodejs-deploy - spec: - containers: - - name: main - image: "{{CONTAINER_IMAGE}}" - resources: {} \ No newline at end of file diff --git a/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-outerloop-project_source-in-docker-build-context/outerloop-service.yaml b/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-outerloop-project_source-in-docker-build-context/outerloop-service.yaml deleted file mode 100644 index 4c6ec53b676..00000000000 --- a/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-outerloop-project_source-in-docker-build-context/outerloop-service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - app: devfile-nodejs-deploy - name: devfile-nodejs-deploy -spec: - ports: - - name: http-3000 - port: 3000 - protocol: TCP - targetPort: 3000 - selector: - app: devfile-nodejs-deploy - type: LoadBalancer \ No newline at end of file diff --git a/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-link/myredis.yaml b/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-link/myredis.yaml deleted file mode 100644 index 46f6251385f..00000000000 --- a/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-link/myredis.yaml +++ /dev/null @@ -1,41 +0,0 @@ -apiVersion: redis.redis.opstreelabs.in/v1beta1 -kind: Redis -metadata: - name: myredis - annotations: - service.binding/name: path={.metadata.name} -spec: - redisExporter: - enabled: true - image: 'quay.io/opstree/redis-exporter:1.0' - imagePullPolicy: Always - resources: - requests: - cpu: 100m - memory: 128Mi - limits: - cpu: 100m - memory: 128Mi - kubernetesConfig: - image: 'quay.io/opstree/redis:v6.2' - imagePullPolicy: IfNotPresent - resources: - requests: - cpu: 101m - memory: 128Mi - limits: - cpu: 101m - memory: 128Mi - redisSecret: - name: redis-secret - key: password - serviceType: LoadBalancer - redisConfig: {} - storage: - volumeClaimTemplate: - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi \ No newline at end of file diff --git a/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-link/redis-link.yaml b/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-link/redis-link.yaml deleted file mode 100644 index c4868d07b93..00000000000 --- a/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-link/redis-link.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: binding.operators.coreos.com/v1alpha1 -kind: ServiceBinding -metadata: - creationTimestamp: null - name: redis-link -spec: - application: - group: apps - name: api-app - resource: deployments - version: v1 - bindAsFiles: true - detectBindingResources: true - services: - - group: redis.redis.opstreelabs.in - kind: Redis - name: myredis - version: v1beta1 -status: - secret: "" \ No newline at end of file diff --git a/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-pod/etcdcluster.yaml b/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-pod/etcdcluster.yaml deleted file mode 100644 index 68aef654216..00000000000 --- a/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-pod/etcdcluster.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: etcd.database.coreos.com/v1beta2 -kind: EtcdCluster -metadata: - annotations: - etcd.database.coreos.com/scope: clusterwide - name: etcdcluster -spec: - size: 3 - version: 3.2.13 \ No newline at end of file diff --git a/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-pod/nginx.yaml b/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-pod/nginx.yaml deleted file mode 100644 index 67239bd5025..00000000000 --- a/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-pod/nginx.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - labels: - name: nginx - name: nginx -spec: - containers: - - image: quay.io/bitnami/nginx - name: nginx - ports: - - containerPort: 80 \ No newline at end of file diff --git a/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-two-deploy-commands/outerloop-deploy.yaml b/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-two-deploy-commands/outerloop-deploy.yaml deleted file mode 100644 index 68b4e32eccb..00000000000 --- a/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-with-two-deploy-commands/outerloop-deploy.yaml +++ /dev/null @@ -1,21 +0,0 @@ -kind: Deployment -apiVersion: apps/v1 -metadata: - name: my-component -spec: - replicas: 1 - selector: - matchLabels: - app: node-app - template: - metadata: - labels: - app: node-app - spec: - containers: - - name: main - image: {{CONTAINER_IMAGE}} - resources: - limits: - memory: "128Mi" - cpu: "500m" \ No newline at end of file diff --git a/tests/examples/source/devfiles/nodejs/project/kubernetes/issue-5600-devfile-with-image-component-and-no-buildContext/outerloop-deploy.yaml b/tests/examples/source/devfiles/nodejs/project/kubernetes/issue-5600-devfile-with-image-component-and-no-buildContext/outerloop-deploy.yaml deleted file mode 100644 index bfa919341c8..00000000000 --- a/tests/examples/source/devfiles/nodejs/project/kubernetes/issue-5600-devfile-with-image-component-and-no-buildContext/outerloop-deploy.yaml +++ /dev/null @@ -1,18 +0,0 @@ -kind: Deployment -apiVersion: apps/v1 -metadata: - name: devfile-nodejs-deploy -spec: - replicas: 1 - selector: - matchLabels: - app: devfile-nodejs-deploy - template: - metadata: - labels: - app: devfile-nodejs-deploy - spec: - containers: - - name: main - image: "localhost:5000/devfile-nodejs-deploy:0.1.0" - resources: {} \ No newline at end of file diff --git a/tests/examples/source/devfiles/nodejs/project/kubernetes/issue-5600-devfile-with-image-component-and-no-buildContext/outerloop-service.yaml b/tests/examples/source/devfiles/nodejs/project/kubernetes/issue-5600-devfile-with-image-component-and-no-buildContext/outerloop-service.yaml deleted file mode 100644 index 4c6ec53b676..00000000000 --- a/tests/examples/source/devfiles/nodejs/project/kubernetes/issue-5600-devfile-with-image-component-and-no-buildContext/outerloop-service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - app: devfile-nodejs-deploy - name: devfile-nodejs-deploy -spec: - ports: - - name: http-3000 - port: 3000 - protocol: TCP - targetPort: 3000 - selector: - app: devfile-nodejs-deploy - type: LoadBalancer \ No newline at end of file diff --git a/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-deploy/outerloop-deploy.yaml b/tests/examples/source/devfiles/nodejs/project/kubernetes/outerloop-deployment.yaml similarity index 95% rename from tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-deploy/outerloop-deploy.yaml rename to tests/examples/source/devfiles/nodejs/project/kubernetes/outerloop-deployment.yaml index 5ac9de29bbc..2a155d1a780 100644 --- a/tests/examples/source/devfiles/nodejs/project/kubernetes/devfile-deploy/outerloop-deploy.yaml +++ b/tests/examples/source/devfiles/nodejs/project/kubernetes/outerloop-deployment.yaml @@ -20,4 +20,4 @@ spec: resources: limits: memory: "128Mi" - cpu: "500m" \ No newline at end of file + cpu: "500m" diff --git a/tests/integration/devfile/cmd_devfile_build_images_test.go b/tests/integration/devfile/cmd_devfile_build_images_test.go index 29d785a6da2..c49b2537de5 100644 --- a/tests/integration/devfile/cmd_devfile_build_images_test.go +++ b/tests/integration/devfile/cmd_devfile_build_images_test.go @@ -79,9 +79,6 @@ var _ = Describe("odo devfile build-images command tests", func() { BeforeEach(func() { helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context) - helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project", "kubernetes", - "devfile-outerloop-project_source-in-docker-build-context"), - filepath.Join(commonVar.Context, "kubernetes", "devfile-outerloop-project_source-in-docker-build-context")) helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", helper.GetExamplePath("source", "devfiles", "nodejs", @@ -124,10 +121,6 @@ var _ = Describe("odo devfile build-images command tests", func() { BeforeEach(func() { helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context) - helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project", "kubernetes", - "issue-5600-devfile-with-image-component-and-no-buildContext"), - filepath.Join(commonVar.Context, "kubernetes", - "issue-5600-devfile-with-image-component-and-no-buildContext")) helper.CopyExampleDevFile( filepath.Join("source", "devfiles", "nodejs", "issue-5600-devfile-with-image-component-and-no-buildContext.yaml"), diff --git a/tests/integration/devfile/cmd_devfile_deploy_test.go b/tests/integration/devfile/cmd_devfile_deploy_test.go index 2bb71328ef3..5be778a2673 100644 --- a/tests/integration/devfile/cmd_devfile_deploy_test.go +++ b/tests/integration/devfile/cmd_devfile_deploy_test.go @@ -40,7 +40,7 @@ var _ = Describe("odo devfile deploy command tests", func() { }) }) - for _, testCtx := range []struct { + for _, ctx := range []struct { title string devfileName string setupFunc func() @@ -48,27 +48,28 @@ var _ = Describe("odo devfile deploy command tests", func() { { title: "using a devfile.yaml containing a deploy command", devfileName: "devfile-deploy.yaml", - setupFunc: func() { - helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project", "kubernetes", "devfile-deploy"), - filepath.Join(commonVar.Context, "kubernetes", "devfile-deploy")) - }, + setupFunc: nil, }, { - title: "using a devfile.yaml containing an outer-loop Kubernetes component inlined", - devfileName: "devfile-deploy-with-k8s-inlined.yaml", + title: "using a devfile.yaml containing an outer-loop Kubernetes component referenced via an URI", + devfileName: "devfile-deploy-with-k8s-uri.yaml", + setupFunc: func() { + helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project", "kubernetes"), + filepath.Join(commonVar.Context, "kubernetes")) + }, }, } { - When(testCtx.title, func() { + When(ctx.title, func() { // from devfile cmpName := "nodejs-prj1-api-abhz" deploymentName := "my-component" BeforeEach(func() { helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context) - helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", testCtx.devfileName), + helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", ctx.devfileName), path.Join(commonVar.Context, "devfile.yaml")) - if testCtx.setupFunc != nil { - testCtx.setupFunc() + if ctx.setupFunc != nil { + ctx.setupFunc() } }) @@ -134,8 +135,6 @@ var _ = Describe("odo devfile deploy command tests", func() { When("using a devfile.yaml containing two deploy commands", func() { BeforeEach(func() { helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context) - helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project", "kubernetes", "devfile-with-two-deploy-commands"), - filepath.Join(commonVar.Context, "kubernetes", "devfile-with-two-deploy-commands")) helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile-with-two-deploy-commands.yaml"), path.Join(commonVar.Context, "devfile.yaml")) }) It("should run odo deploy", func() { @@ -154,8 +153,6 @@ var _ = Describe("odo devfile deploy command tests", func() { When("recording telemetry data", func() { BeforeEach(func() { helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context) - helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project", "kubernetes", "devfile-deploy"), - filepath.Join(commonVar.Context, "kubernetes", "devfile-deploy")) helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile-deploy.yaml"), path.Join(commonVar.Context, "devfile.yaml")) helper.EnableTelemetryDebug() helper.Cmd("odo", "deploy").AddEnv("PODMAN_CMD=echo").ShouldPass() @@ -179,9 +176,6 @@ var _ = Describe("odo devfile deploy command tests", func() { BeforeEach(func() { helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context) - helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project", "kubernetes", - "devfile-outerloop-project_source-in-docker-build-context"), - filepath.Join(commonVar.Context, "kubernetes", "devfile-outerloop-project_source-in-docker-build-context")) helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", helper.GetExamplePath("source", "devfiles", "nodejs", @@ -226,10 +220,6 @@ var _ = Describe("odo devfile deploy command tests", func() { BeforeEach(func() { helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context) - helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project", "kubernetes", - "issue-5600-devfile-with-image-component-and-no-buildContext"), - filepath.Join(commonVar.Context, "kubernetes", - "issue-5600-devfile-with-image-component-and-no-buildContext")) helper.CopyExampleDevFile( filepath.Join("source", "devfiles", "nodejs", "issue-5600-devfile-with-image-component-and-no-buildContext.yaml"), diff --git a/tests/integration/devfile/cmd_devfile_init_test.go b/tests/integration/devfile/cmd_devfile_init_test.go index 49985e7b284..482ac1e655e 100644 --- a/tests/integration/devfile/cmd_devfile_init_test.go +++ b/tests/integration/devfile/cmd_devfile_init_test.go @@ -268,8 +268,6 @@ var _ = Describe("odo devfile init command tests", func() { var out string BeforeEach(func() { helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile-deploy.yaml"), devfilePath) - helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project", "kubernetes", "devfile-deploy"), - filepath.Join(commonVar.Context, "kubernetes", "devfile-deploy")) out = helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", devfilePath).ShouldPass().Out() }) It("should show information about both `odo dev`, and `odo deploy`", func() { diff --git a/tests/integration/devfile/cmd_devfile_list_test.go b/tests/integration/devfile/cmd_devfile_list_test.go index 618d8365f1a..6e8b28fefcb 100644 --- a/tests/integration/devfile/cmd_devfile_list_test.go +++ b/tests/integration/devfile/cmd_devfile_list_test.go @@ -32,8 +32,6 @@ var _ = Describe("odo list with devfile", func() { BeforeEach(func() { helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context) helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile-deploy.yaml"), path.Join(commonVar.Context, "devfile.yaml")) - helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project", "kubernetes", "devfile-deploy"), - filepath.Join(commonVar.Context, "kubernetes", "devfile-deploy")) helper.Chdir(commonVar.Context) var err error devSession, _, _, _, err = helper.StartDevMode()