Fix: odo init overwrites personalized configuration when downloading starter project (#6800)

* Fix personalized configuration overwritten by starter project

Signed-off-by: Parthvi Vala <pvala@redhat.com>

* Update pkg/registry/registry_test.go

Co-authored-by: Armel Soro <armel@rm3l.org>
Signed-off-by: Parthvi Vala <pvala@redhat.com>

* Adding intergration tests for personalizing configurations with odo init

Signed-off-by: Ritu Deshmukh <rideshmu@redhat.com>

Modified changes

Signed-off-by: Ritu Deshmukh <rideshmu@redhat.com>

Update tests/integration/interactive_init_test.go

Co-authored-by: Parthvi Vala <pvala@redhat.com>

Update tests/integration/interactive_init_test.go

Co-authored-by: Parthvi Vala <pvala@redhat.com>

Update interactive_init_test.go

Update interactive_init_test.go

Update interactive_init_test.go

Update tests/integration/interactive_init_test.go

Co-authored-by: Parthvi Vala <pvala@redhat.com>

Update interactive_init_test.go

* Updated changes

Signed-off-by: Ritu Deshmukh <rideshmu@redhat.com>

* Attempt at fixing interactive tests

Signed-off-by: Parthvi Vala <pvala@redhat.com>

* Add multiple devfile version check

Co-authored-by: Armel Soro <asoro@redhat.com>
Signed-off-by: Parthvi Vala <pvala@redhat.com>

---------

Signed-off-by: Parthvi Vala <pvala@redhat.com>
Signed-off-by: Ritu Deshmukh <rideshmu@redhat.com>
Co-authored-by: Armel Soro <armel@rm3l.org>
Co-authored-by: Ritu Deshmukh <rideshmu@redhat.com>
Co-authored-by: Armel Soro <asoro@redhat.com>
This commit is contained in:
Parthvi Vala
2023-05-12 01:36:49 +05:30
committed by GitHub
parent c217741cc7
commit 0cdc2e5542
10 changed files with 122 additions and 36 deletions

View File

@@ -13,7 +13,7 @@ import (
type Client interface {
PullStackFromRegistry(registry string, stack string, destDir string, options library.RegistryOptions) error
DownloadFileInMemory(params dfutil.HTTPRequestParams) ([]byte, error)
DownloadStarterProject(starterProject *devfilev1.StarterProject, decryptedToken string, contextDir string, verbose bool) error
DownloadStarterProject(starterProject *devfilev1.StarterProject, decryptedToken string, contextDir string, verbose bool) (bool, error)
GetDevfileRegistries(registryName string) ([]api.Registry, error)
ListDevfileStacks(ctx context.Context, registryName, devfileFlag, filterFlag string, detailsFlag bool, withDevfileContent bool) (DevfileStackList, error)
}

View File

@@ -54,11 +54,12 @@ func (mr *MockClientMockRecorder) DownloadFileInMemory(params interface{}) *gomo
}
// DownloadStarterProject mocks base method.
func (m *MockClient) DownloadStarterProject(starterProject *v1alpha2.StarterProject, decryptedToken, contextDir string, verbose bool) error {
func (m *MockClient) DownloadStarterProject(starterProject *v1alpha2.StarterProject, decryptedToken, contextDir string, verbose bool) (bool, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "DownloadStarterProject", starterProject, decryptedToken, contextDir, verbose)
ret0, _ := ret[0].(error)
return ret0
ret0, _ := ret[0].(bool)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// DownloadStarterProject indicates an expected call of DownloadStarterProject.

View File

@@ -64,11 +64,11 @@ func (o RegistryClient) DownloadFileInMemory(params dfutil.HTTPRequestParams) ([
// Case 1: If there is devfile in the starterproject, replace all the contents of contextDir with that of the starterproject; warn about this
// Case 2: If there is no devfile, and there is no conflict between the contents of contextDir and starterproject, then copy the contents of the starterproject into contextDir.
// Case 3: If there is no devfile, and there is conflict between the contents of contextDir and starterproject, copy contents of starterproject into a dir named CONFLICT_STARTER_PROJECT; warn about this
func (o RegistryClient) DownloadStarterProject(starterProject *devfilev1.StarterProject, decryptedToken string, contextDir string, verbose bool) error {
func (o RegistryClient) DownloadStarterProject(starterProject *devfilev1.StarterProject, decryptedToken string, contextDir string, verbose bool) (containsDevfile bool, err error) {
// Let the project be downloaded in a temp directory
starterProjectTmpDir, err := o.fsys.TempDir("", "odostarterproject")
if err != nil {
return err
return containsDevfile, err
}
defer func() {
err = o.fsys.RemoveAll(starterProjectTmpDir)
@@ -78,22 +78,21 @@ func (o RegistryClient) DownloadStarterProject(starterProject *devfilev1.Starter
}()
err = DownloadStarterProject(o.fsys, starterProject, decryptedToken, starterProjectTmpDir, verbose)
if err != nil {
return err
return containsDevfile, err
}
// Case 1: If there is devfile in the starterproject, replace all the contents of contextDir with that of the starterproject; warn about this
var containsDevfile bool
if containsDevfile, err = location.DirectoryContainsDevfile(o.fsys, starterProjectTmpDir); err != nil {
return err
return containsDevfile, err
}
if containsDevfile {
fmt.Println()
log.Warning("A Devfile is present inside the starter project; replacing the entire content of the current directory with the starter project")
err = removeDirectoryContents(contextDir, o.fsys)
if err != nil {
return fmt.Errorf("failed to delete contents of the current directory; cause %w", err)
return containsDevfile, fmt.Errorf("failed to delete contents of the current directory; cause %w", err)
}
return util.CopyDirWithFS(starterProjectTmpDir, contextDir, o.fsys)
return containsDevfile, util.CopyDirWithFS(starterProjectTmpDir, contextDir, o.fsys)
}
// Case 2: If there is no devfile, and there is no conflict between the contents of contextDir and starterproject, then copy the contents of the starterproject into contextDir.
@@ -101,29 +100,29 @@ func (o RegistryClient) DownloadStarterProject(starterProject *devfilev1.Starter
var conflictingFiles []string
conflictingFiles, err = getConflictingFiles(starterProjectTmpDir, contextDir, o.fsys)
if err != nil {
return err
return containsDevfile, err
}
// Case 2
if len(conflictingFiles) == 0 {
return util.CopyDirWithFS(starterProjectTmpDir, contextDir, o.fsys)
return containsDevfile, util.CopyDirWithFS(starterProjectTmpDir, contextDir, o.fsys)
}
// Case 3
conflictingDirPath := filepath.Join(contextDir, CONFLICT_DIR_NAME)
err = o.fsys.MkdirAll(conflictingDirPath, 0750)
if err != nil {
return err
return containsDevfile, err
}
err = util.CopyDirWithFS(starterProjectTmpDir, conflictingDirPath, o.fsys)
if err != nil {
return err
return containsDevfile, err
}
fmt.Println()
log.Warningf("There are conflicting files (%s) between starter project and the current directory, hence the starter project has been copied to %s", strings.Join(conflictingFiles, ", "), conflictingDirPath)
return nil
return containsDevfile, nil
}
// removeDirectoryContents attempts to remove dir contents without deleting the directory itself, unlike os.RemoveAll() method

View File

@@ -666,11 +666,12 @@ func TestRegistryClient_DownloadStarterProject(t *testing.T) {
verbose bool
}
tests := []struct {
name string
fields fields
args args
want []string
wantErr bool
name string
fields fields
args args
want []string
wantContainsDevfile bool
wantErr bool
}{
// TODO: Add test cases.
{
@@ -690,8 +691,9 @@ func TestRegistryClient_DownloadStarterProject(t *testing.T) {
},
},
},
want: []string{"devfile.yaml", "docker", filepath.Join("docker", "Dockerfile"), "README.md", "main.go", "go.mod", "someFile.txt"},
wantErr: false,
want: []string{"devfile.yaml", "docker", filepath.Join("docker", "Dockerfile"), "README.md", "main.go", "go.mod", "someFile.txt"},
wantErr: false,
wantContainsDevfile: true,
},
{
name: "Starter project has conflicting files",
@@ -793,8 +795,13 @@ func TestRegistryClient_DownloadStarterProject(t *testing.T) {
preferenceClient: tt.fields.preferenceClient,
kubeClient: tt.fields.kubeClient,
}
if err := o.DownloadStarterProject(tt.args.starterProject, tt.args.decryptedToken, tt.args.contextDir, tt.args.verbose); (err != nil) != tt.wantErr {
t.Errorf("DownloadStarterProject() error = %v, wantErr %v", err, tt.wantErr)
gotContainsDevfile, gotErr := o.DownloadStarterProject(tt.args.starterProject, tt.args.decryptedToken, tt.args.contextDir, tt.args.verbose)
if (gotErr != nil) != tt.wantErr {
t.Errorf("DownloadStarterProject() error = %v, wantErr %v", gotErr, tt.wantErr)
return
}
if tt.wantContainsDevfile != gotContainsDevfile {
t.Errorf("DownloadStarterProject() containsDevfile = %v, want = %v", gotContainsDevfile, tt.wantContainsDevfile)
return
}
var got []string