From 78868b03fda2f6b4ca76365d41eafc1357836d85 Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Tue, 25 Apr 2023 14:55:40 +0200 Subject: [PATCH] Fix 'odo init' integration tests - The test spec was actually not doing what it was supposed to do - Now 'odo init' returns a complete Devfile, where the parent is flattened, because the goal of 'odo init' is to bootstrap a Devfile. Previously, 'odo init' would not download the parent referenced, making it hard to understand the resulting Devfile. --- tests/helper/helper_devfile.go | 19 +++-- tests/integration/cmd_devfile_init_test.go | 87 +++++++++++++++++----- 2 files changed, 80 insertions(+), 26 deletions(-) diff --git a/tests/helper/helper_devfile.go b/tests/helper/helper_devfile.go index 971c895a4b8..8e95939599d 100644 --- a/tests/helper/helper_devfile.go +++ b/tests/helper/helper_devfile.go @@ -70,12 +70,8 @@ func UpdateDevfileContent(path string, handlers []DevfileUpdater) { return } - d, err := parser.ParseDevfile(parser.ParserArgs{ - Path: path, - FlattenedDevfile: pointer.Bool(false), - SetBooleanDefaults: pointer.Bool(false), - }) - Expect(err).NotTo(HaveOccurred()) + var err error + d := ParseDevfileFromPath(path) for _, h := range handlers { err = h(&d) Expect(err).NotTo(HaveOccurred()) @@ -83,3 +79,14 @@ func UpdateDevfileContent(path string, handlers []DevfileUpdater) { err = d.WriteYamlDevfile() Expect(err).NotTo(HaveOccurred()) } + +// ParseDevfileFromPath parses the file at the specified path and returns a Devfile object. +func ParseDevfileFromPath(path string) parser.DevfileObj { + d, err := parser.ParseDevfile(parser.ParserArgs{ + Path: path, + FlattenedDevfile: pointer.Bool(false), + SetBooleanDefaults: pointer.Bool(false), + }) + Expect(err).NotTo(HaveOccurred()) + return d +} diff --git a/tests/integration/cmd_devfile_init_test.go b/tests/integration/cmd_devfile_init_test.go index 78a19b5a4ab..2d950baebe7 100644 --- a/tests/integration/cmd_devfile_init_test.go +++ b/tests/integration/cmd_devfile_init_test.go @@ -3,13 +3,17 @@ package integration import ( "context" "fmt" + "io" + "net/http" "os" "path/filepath" + "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2" + "github.com/devfile/library/v2/pkg/devfile/parser/data/v2/common" + "github.com/google/go-cmp/cmp" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/tidwall/gjson" - "gopkg.in/yaml.v2" "github.com/redhat-developer/odo/pkg/config" envcontext "github.com/redhat-developer/odo/pkg/config/context" @@ -377,30 +381,73 @@ var _ = Describe("odo devfile init command tests", func() { }) When("devfile contains parent URI", func() { - var originalKeyList []string - var srcDevfile string + var childDevfile string + var originalDevfileContent string BeforeEach(func() { - var err error - srcDevfile = helper.GetExamplePath("source", "devfiles", "nodejs", "devfile-with-parent.yaml") - originalDevfileContent, err := os.ReadFile(srcDevfile) + // An issue from the Devfile library causes the parent to not be resolved properly: + // ✗ unable to parse devfile: failed to populateAndParseDevfile: url path to directory or file should contain 'tree' or 'blob'. + // + // Even after using a URL with 'tree'or 'blob', the parser still does not pass. + // This workaround downloads the parent manually and references it via the local filesystem. + srcDir := helper.CreateNewContext() + DeferCleanup(func() { + helper.DeleteDir(srcDir) + }) + parentDevfile := filepath.Join(commonVar.Context, "parent-devfile.yaml") + f, err := os.Create(parentDevfile) + Expect(err).ShouldNot(HaveOccurred()) + resp, err := http.Get("https://github.com/OpenLiberty/application-stack/releases/download/maven-0.7.0/devfile.yaml") + Expect(err).ShouldNot(HaveOccurred()) + defer resp.Body.Close() + _, err = io.Copy(f, resp.Body) + Expect(err).ShouldNot(HaveOccurred()) + childDevfile = filepath.Join(srcDir, "devfile-child.yaml") + helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile-with-parent.yaml"), childDevfile) + helper.ReplaceString(childDevfile, "https://github.com/OpenLiberty/application-stack/releases/download/maven-0.7.0/devfile.yaml", "parent-devfile.yaml") + + b, err := os.ReadFile(childDevfile) Expect(err).To(BeNil()) - var content map[string]interface{} - Expect(yaml.Unmarshal(originalDevfileContent, &content)).To(BeNil()) - for k := range content { - originalKeyList = append(originalKeyList, k) - } + originalDevfileContent = string(b) + + helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", childDevfile).ShouldPass() }) - It("should not replace the original devfile", func() { - helper.Cmd("odo", "init", "--name", "aname", "--devfile-path", srcDevfile).ShouldPass() - devfileContent, err := os.ReadFile(filepath.Join(commonVar.Context, "devfile.yaml")) - Expect(err).To(BeNil()) - var content map[string]interface{} - Expect(yaml.Unmarshal(devfileContent, &content)).To(BeNil()) - for k := range content { - Expect(k).To(BeElementOf(originalKeyList)) - } + It("should create an effective Devfile", func() { + devfilePath := filepath.Join(commonVar.Context, "devfile.yaml") + + By("not replacing the original Devfile", func() { + // Re-read the original Devfile + originalB, err := os.ReadFile(childDevfile) + Expect(err).To(BeNil()) + originalDevfileContentReread := string(originalB) + diff := cmp.Diff(originalDevfileContentReread, originalDevfileContent) + Expect(diff).Should(BeEmpty()) + }) + + By("creating a different Devfile", func() { + b, err := os.ReadFile(filepath.Join(commonVar.Context, "devfile.yaml")) + Expect(err).To(BeNil()) + devfileContent := string(b) + Expect(devfileContent).ShouldNot(BeEquivalentTo(originalDevfileContent)) + }) + + By("creating a Devfile with no reference to the parent other than via attributes", func() { + d := helper.ParseDevfileFromPath(devfilePath) + containerComp, err := d.Data.GetComponents(common.DevfileOptions{ + ComponentOptions: common.ComponentOptions{ + ComponentType: v1alpha2.ContainerComponentType, + }, + }) + Expect(err).ShouldNot(HaveOccurred()) + // It should not have any reference to the parent + Expect(d.Data.GetParent()).Should(BeNil(), "Generated devfile should be effective with no 'parent' key") + Expect(containerComp).Should(HaveLen(1)) + cAttrMap := containerComp[0].Attributes.Strings(&err) + Expect(err).ShouldNot(HaveOccurred()) + Expect(cAttrMap).ShouldNot(BeEmpty()) + Expect(cAttrMap["api.devfile.io/imported-from"]).Should(ContainSubstring("parent-devfile.yaml")) + }) }) })