diff --git a/pkg/devfile/parser/parse.go b/pkg/devfile/parser/parse.go index 0800c92d..826543f9 100644 --- a/pkg/devfile/parser/parse.go +++ b/pkg/devfile/parser/parse.go @@ -416,7 +416,7 @@ func parseFromURI(importReference v1.ImportReference, curDevfileCtx devfileCtx.D return DevfileObj{}, err } destDir := path.Dir(curDevfileCtx.GetAbsPath()) - err = getStackFromGit(urlComponents, destDir) + err = getResourcesFromGit(urlComponents, destDir) if err != nil { return DevfileObj{}, err } @@ -427,9 +427,20 @@ func parseFromURI(importReference v1.ImportReference, curDevfileCtx devfileCtx.D if err != nil { return DevfileObj{}, err } - u.Path = path.Join(path.Dir(u.Path), uri) + u.Path = path.Join(u.Path, uri) newUri = u.String() d.Ctx = devfileCtx.NewURLDevfileCtx(newUri) + if strings.Contains(newUri, "raw.githubusercontent.com") { + urlComponents, err := util.GetGitUrlComponentsFromRaw(newUri) + if err != nil { + return DevfileObj{}, err + } + destDir := path.Dir(curDevfileCtx.GetAbsPath()) + err = getResourcesFromGit(urlComponents, destDir) + if err != nil { + return DevfileObj{}, err + } + } } importReference.Uri = newUri newResolveCtx := resolveCtx.appendNode(importReference) @@ -437,8 +448,8 @@ func parseFromURI(importReference v1.ImportReference, curDevfileCtx devfileCtx.D return populateAndParseDevfile(d, newResolveCtx, tool, true) } -func getStackFromGit(gitUrlComponents map[string]string, destDir string) error { - stackDir, err := ioutil.TempDir(os.TempDir(), fmt.Sprintf("stack-git")) +func getResourcesFromGit(gitUrlComponents map[string]string, destDir string) error { + stackDir, err := ioutil.TempDir(os.TempDir(), fmt.Sprintf("git-resources")) if err != nil { return fmt.Errorf("failed to create dir: %s, error: %v", stackDir, err) } @@ -474,7 +485,7 @@ func parseFromRegistry(importReference v1.ImportReference, resolveCtx *resolutio } newResolveCtx := resolveCtx.appendNode(importReference) - err = getStackFromRegistry(id, registryURL, destDir) + err = getResourcesFromRegistry(id, registryURL, destDir) if err != nil { return DevfileObj{}, err } @@ -492,7 +503,7 @@ func parseFromRegistry(importReference v1.ImportReference, resolveCtx *resolutio importReference.RegistryUrl = registryURL newResolveCtx := resolveCtx.appendNode(importReference) - err := getStackFromRegistry(id, registryURL, destDir) + err := getResourcesFromRegistry(id, registryURL, destDir) if err != nil { return DevfileObj{}, err } @@ -520,8 +531,8 @@ func getDevfileFromRegistry(id, registryURL, version string, httpTimeout *int) ( return util.HTTPGetRequest(param, 0) } -func getStackFromRegistry(id, registryURL, destDir string) error { - stackDir, err := ioutil.TempDir(os.TempDir(), fmt.Sprintf("stack-%s", id)) +func getResourcesFromRegistry(id, registryURL, destDir string) error { + stackDir, err := ioutil.TempDir(os.TempDir(), fmt.Sprintf("registry-resources-%s", id)) if err != nil { return fmt.Errorf("failed to create dir: %s, error: %v", stackDir, err) } diff --git a/pkg/devfile/parser/parse_test.go b/pkg/devfile/parser/parse_test.go index a337751f..de1fbc73 100644 --- a/pkg/devfile/parser/parse_test.go +++ b/pkg/devfile/parser/parse_test.go @@ -3073,7 +3073,7 @@ func Test_parseParentAndPlugin_RecursivelyReference(t *testing.T) { } err := parseParentAndPlugin(devFileObj, &resolutionContextTree{}, tool) - // devfile has an cycle in references: main devfile -> uri: http://127.0.0.1:8080 -> name: testcrd, namespace: defaultnamespace -> uri: http://127.0.0.1:8090 -> uri: http://127.0.0.1:8080 + // devfile has a cycle in references: main devfile -> uri: http://127.0.0.1:8080 -> name: testcrd, namespace: defaultnamespace -> uri: http://127.0.0.1:8090 -> uri: http://127.0.0.1:8080 expectedErr := fmt.Sprintf("devfile has an cycle in references: main devfile -> uri: %s%s -> name: %s, namespace: %s -> uri: %s%s -> uri: %s%s", httpPrefix, uri1, name, namespace, httpPrefix, uri2, httpPrefix, uri1) // Unexpected error @@ -3860,62 +3860,11 @@ func Test_parseFromRegistry(t *testing.T) { }, } - wantDevfile := DevfileObj{ - Data: &v2.DevfileV2{ - Devfile: v1.Devfile{ - DevfileHeader: devfilepkg.DevfileHeader{ - SchemaVersion: schemaVersion, - }, - DevWorkspaceTemplateSpec: v1.DevWorkspaceTemplateSpec{ - DevWorkspaceTemplateSpecContent: v1.DevWorkspaceTemplateSpecContent{ - Components: []v1.Component{ - { - Name: "runtime2", - ComponentUnion: v1.ComponentUnion{ - Volume: &v1.VolumeComponent{ - Volume: v1.Volume{ - Size: "500Mi", - }, - }, - }, - }, - }, - }, - }, - }, - }, - } - - latestWantDevfile := DevfileObj{ - Data: &v2.DevfileV2{ - Devfile: v1.Devfile{ - DevfileHeader: devfilepkg.DevfileHeader{ - SchemaVersion: schemaVersion, - }, - DevWorkspaceTemplateSpec: v1.DevWorkspaceTemplateSpec{ - DevWorkspaceTemplateSpecContent: v1.DevWorkspaceTemplateSpecContent{ - Components: []v1.Component{ - { - Name: "runtime-latest", - ComponentUnion: v1.ComponentUnion{ - Volume: &v1.VolumeComponent{ - Volume: v1.Volume{ - Size: "500Mi", - }, - }, - }, - }, - }, - }, - }, - }, - }, - } - invalidURLErr := "the provided registryURL: .* is not a valid URL" URLNotFoundErr := "failed to retrieve .*, 404: Not Found" missingRegistryURLErr := "failed to fetch from registry, registry URL is not provided" invalidRegistryURLErr := "Get .* dial tcp: lookup http: .*" + resourceDownloadErr := "failed to pull stack from registry .*" testServer := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var data []byte @@ -3968,8 +3917,7 @@ func Test_parseFromRegistry(t *testing.T) { wantErr *string }{ { - name: "should fail if provided registryUrl does not have protocol prefix", - wantDevFile: wantDevfile, + name: "should fail if provided registryUrl does not have protocol prefix", importReference: v1.ImportReference{ ImportReferenceUnion: v1.ImportReferenceUnion{ Id: registryId, @@ -3988,8 +3936,7 @@ func Test_parseFromRegistry(t *testing.T) { }, }, { - name: "should be able to parse from registry URL defined in tool", - wantDevFile: wantDevfile, + name: "should be able to parse from registry URL defined in tool", importReference: v1.ImportReference{ ImportReferenceUnion: v1.ImportReferenceUnion{ Id: registryId, @@ -4000,8 +3947,7 @@ func Test_parseFromRegistry(t *testing.T) { }, }, { - name: "should be able to parse from provided registryUrl with latest version specified", - wantDevFile: latestWantDevfile, + name: "should be able to parse from provided registryUrl with latest version specified", importReference: v1.ImportReference{ ImportReferenceUnion: v1.ImportReferenceUnion{ Id: registryId, @@ -4010,6 +3956,27 @@ func Test_parseFromRegistry(t *testing.T) { RegistryUrl: stagingRegistry, }, }, + { + name: "should be able to parse from provided registryUrl with version specified", + importReference: v1.ImportReference{ + ImportReferenceUnion: v1.ImportReferenceUnion{ + Id: registryId, + }, + Version: "2.0.0", + RegistryUrl: stagingRegistry, + }, + }, + { + name: "should fail if provided registryUrl cannot download resources", + importReference: v1.ImportReference{ + ImportReferenceUnion: v1.ImportReferenceUnion{ + Id: registryId, + }, + Version: "latest", + RegistryUrl: httpPrefix + registry, + }, + wantErr: &resourceDownloadErr, + }, { name: "should fail if version does not exist", importReference: v1.ImportReference{ @@ -4053,19 +4020,9 @@ func Test_parseFromRegistry(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - gotErr := false - got, err := parseFromRegistry(tt.importReference, &resolutionContextTree{}, tt.tool) - if err != nil { - gotErr = true - } + _, err := parseFromRegistry(tt.importReference, &resolutionContextTree{}, tt.tool) if (err != nil) != (tt.wantErr != nil) { t.Errorf("Test_parseFromRegistry() unexpected error: %v, wantErr %v", err, tt.wantErr) - } else if strings.Contains(tt.name, "should be able to parse") { - if !reflect.DeepEqual(gotErr, false) { - t.Errorf("Got error: %t, want error: %t", gotErr, false) - } - } else if err == nil && !reflect.DeepEqual(got.Data, tt.wantDevFile.Data) { - t.Errorf("Test_parseFromRegistry() error: wanted: %v, got: %v, difference at %v", tt.wantDevFile, got, pretty.Compare(tt.wantDevFile, got)) } else if err != nil { assert.Regexp(t, *tt.wantErr, err.Error(), "Test_parseFromRegistry(): Error message should match") } diff --git a/pkg/util/util_test.go b/pkg/util/util_test.go index c8c1b1e0..da51a8b5 100644 --- a/pkg/util/util_test.go +++ b/pkg/util/util_test.go @@ -1040,25 +1040,32 @@ func TestGetGitUrlComponentsFromRaw(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - gotErr := false _, err := GetGitUrlComponentsFromRaw(tt.url) - if err != nil { - gotErr = true - } - - if !reflect.DeepEqual(gotErr, tt.wantErr) { - t.Errorf("Got error: %t, want error: %t", gotErr, tt.wantErr) + if (err != nil) != tt.wantErr { + t.Errorf("Expected error: %t, got error: %t", tt.wantErr, err) } }) } } func TestCloneGitRepo(t *testing.T) { + // Create temp dir and temp file + tempDir, err := ioutil.TempDir("", "") + if err != nil { + t.Errorf("Failed to create temp dir: %s, error: %v", tempDir, err) + } + defer os.RemoveAll(tempDir) + invalidGitUrl := map[string]string{ "username": "devfile", "project": "nonexistent", "branch": "nonexistent", } + validGitUrl := map[string]string{ + "username": "devfile", + "project": "library", + "branch": "main", + } tests := []struct { name string @@ -1072,18 +1079,19 @@ func TestCloneGitRepo(t *testing.T) { destDir: filepath.Join(os.TempDir(), "nonexistent"), wantErr: true, }, + { + name: "should be able to clone valid git url", + gitUrlComponents: validGitUrl, + destDir: tempDir, + wantErr: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - gotErr := false err := CloneGitRepo(tt.gitUrlComponents, tt.destDir) - if err != nil { - gotErr = true - } - - if !reflect.DeepEqual(gotErr, tt.wantErr) { - t.Errorf("Got error: %t, want error: %t", gotErr, tt.wantErr) + if (err != nil) != tt.wantErr { + t.Errorf("Expected error: %t, got error: %t", tt.wantErr, err) } }) } @@ -1155,8 +1163,11 @@ func TestCopyAllDirFiles(t *testing.T) { fs.MkdirAll("/path/to/dest", 0755) fs.WriteFile("/path/to/src/devfile.yaml", []byte(""), 0755) fs.WriteFile("/path/to/src/file.txt", []byte(""), 0755) + fs.WriteFile("/path/to/src/subdir/devfile.yaml", []byte(""), 0755) + fs.WriteFile("/path/to/src/subdir/file.txt", []byte(""), 0755) srcDir := "/path/to/src" + srcSubDir := "/path/to/src/subdir" destDir := "/path/to/dest" missingDir := "/invalid/path/to/dir" @@ -1172,6 +1183,12 @@ func TestCopyAllDirFiles(t *testing.T) { destDir: destDir, wantErr: false, }, + { + name: "should be able to copy subdir files to destination path", + srcDir: srcSubDir, + destDir: destDir, + wantErr: false, + }, { name: "should fail if source path is invalid", srcDir: missingDir, @@ -1182,14 +1199,9 @@ func TestCopyAllDirFiles(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - gotErr := false err := copyAllDirFilesOnFS(tt.srcDir, tt.destDir, fs) - if err != nil { - gotErr = true - } - - if !reflect.DeepEqual(gotErr, tt.wantErr) { - t.Errorf("Got error: %t, want error: %t", gotErr, tt.wantErr) + if (err != nil) != tt.wantErr { + t.Errorf("Expected error: %t, got error: %t", tt.wantErr, err) } }) }