diff --git a/artifactory/commands/transferconfig/transferconfig.go b/artifactory/commands/transferconfig/transferconfig.go index 796e99c86..ddc6ce01c 100644 --- a/artifactory/commands/transferconfig/transferconfig.go +++ b/artifactory/commands/transferconfig/transferconfig.go @@ -14,6 +14,7 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/generic" "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/transferconfig/configxmlutils" commandsUtils "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils" + "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils/precheckrunner" "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" "github.com/jfrog/jfrog-cli-core/v2/common/commands" "github.com/jfrog/jfrog-cli-core/v2/utils/config" @@ -212,7 +213,7 @@ func (tcc *TransferConfigCommand) runPreChecks() error { return err } - return tcc.NewPreChecksRunner(remoteRepositories).Run(context.Background(), tcc.TargetServerDetails) + return tcc.NewPreChecksRunner(selectedRepos, remoteRepositories).Run(context.Background(), tcc.TargetServerDetails) } func (tcc *TransferConfigCommand) printWarnings() (err error) { @@ -296,16 +297,17 @@ func (tcc *TransferConfigCommand) verifyConfigImportPlugin() error { } // Creates the Pre-checks runner for the config import command -func (tcc *TransferConfigCommand) NewPreChecksRunner(remoteRepositories []interface{}) (runner *commandsUtils.PreCheckRunner) { - runner = commandsUtils.NewPreChecksRunner() +func (tcc *TransferConfigCommand) NewPreChecksRunner(selectedRepos map[utils.RepoType][]services.RepositoryDetails, remoteRepositories []interface{}) (runner *precheckrunner.PreCheckRunner) { + runner = precheckrunner.NewPreChecksRunner() // Add pre-checks here - runner.AddCheck(commandsUtils.NewRemoteRepositoryCheck(&tcc.TargetArtifactoryManager, remoteRepositories)) + runner.AddCheck(precheckrunner.NewRepositoryNamingCheck(selectedRepos)) + runner.AddCheck(precheckrunner.NewRemoteRepositoryCheck(&tcc.TargetArtifactoryManager, remoteRepositories)) return } -func (tcc *TransferConfigCommand) getEncryptedItems(selectedSourceRepos map[utils.RepoType][]string) (configXml string, remoteRepositories []interface{}, err error) { +func (tcc *TransferConfigCommand) getEncryptedItems(selectedSourceRepos map[utils.RepoType][]services.RepositoryDetails) (configXml string, remoteRepositories []interface{}, err error) { reactivateKeyEncryption, err := tcc.DeactivateKeyEncryption() if err != nil { return "", nil, err @@ -324,10 +326,10 @@ func (tcc *TransferConfigCommand) getEncryptedItems(selectedSourceRepos map[util } // Get all remote repositories from the source Artifactory server. - if remoteRepositoryNames, ok := selectedSourceRepos[utils.Remote]; ok && len(remoteRepositoryNames) > 0 { - remoteRepositories = make([]interface{}, len(remoteRepositoryNames)) - for i, repoName := range remoteRepositoryNames { - if err = tcc.SourceArtifactoryManager.GetRepository(repoName, &remoteRepositories[i]); err != nil { + if remoteRepositoriesDetails, ok := selectedSourceRepos[utils.Remote]; ok && len(remoteRepositoriesDetails) > 0 { + remoteRepositories = make([]interface{}, len(remoteRepositoriesDetails)) + for i, remoteRepositoryDetails := range remoteRepositoriesDetails { + if err = tcc.SourceArtifactoryManager.GetRepository(remoteRepositoryDetails.Key, &remoteRepositories[i]); err != nil { return } } diff --git a/artifactory/commands/transferconfig/transferconfig_test.go b/artifactory/commands/transferconfig/transferconfig_test.go index 443183196..6c229f860 100644 --- a/artifactory/commands/transferconfig/transferconfig_test.go +++ b/artifactory/commands/transferconfig/transferconfig_test.go @@ -95,7 +95,7 @@ func TestGetConfigXml(t *testing.T) { // Test get config xml transferConfigCmd := createTransferConfigCommand(t, serverDetails, nil) - configXml, _, err := transferConfigCmd.getEncryptedItems(make(map[utils.RepoType][]string)) + configXml, _, err := transferConfigCmd.getEncryptedItems(make(map[utils.RepoType][]services.RepositoryDetails)) assert.NoError(t, err) assert.Equal(t, "", configXml) } diff --git a/artifactory/commands/transferconfigmerge/transferconfigmerge.go b/artifactory/commands/transferconfigmerge/transferconfigmerge.go index fa3171c8c..ea1c0d273 100644 --- a/artifactory/commands/transferconfigmerge/transferconfigmerge.go +++ b/artifactory/commands/transferconfigmerge/transferconfigmerge.go @@ -53,7 +53,7 @@ func (tcmc *TransferConfigMergeCommand) SetExcludeProjectsPatterns(excludeProjec type mergeEntities struct { projectsToTransfer []accessServices.Project - reposToTransfer map[utils.RepoType][]string + reposToTransfer map[utils.RepoType][]services.RepositoryDetails } type Conflict struct { @@ -243,8 +243,8 @@ func compareProjects(sourceProject, targetProject accessServices.Project) (*Conf }, nil } -func (tcmc *TransferConfigMergeCommand) mergeRepositories(conflicts *[]Conflict) (reposToTransfer map[utils.RepoType][]string, err error) { - reposToTransfer = make(map[utils.RepoType][]string) +func (tcmc *TransferConfigMergeCommand) mergeRepositories(conflicts *[]Conflict) (reposToTransfer map[utils.RepoType][]services.RepositoryDetails, err error) { + reposToTransfer = make(map[utils.RepoType][]services.RepositoryDetails) sourceRepos, err := tcmc.SourceArtifactoryManager.GetAllRepositories() if err != nil { return @@ -286,7 +286,7 @@ func (tcmc *TransferConfigMergeCommand) mergeRepositories(conflicts *[]Conflict) } } else { repoType := utils.RepoTypeFromString(sourceRepo.Type) - reposToTransfer[repoType] = append(reposToTransfer[repoType], sourceRepo.Key) + reposToTransfer[repoType] = append(reposToTransfer[repoType], sourceRepo) } } return @@ -351,7 +351,7 @@ func (tcmc *TransferConfigMergeCommand) transferProjectsToTarget(reposToTransfer return } -func (tcmc *TransferConfigMergeCommand) decryptAndGetAllRemoteRepositories(remoteRepositoryNames []string) (remoteRepositories []interface{}, err error) { +func (tcmc *TransferConfigMergeCommand) decryptAndGetAllRemoteRepositories(remoteRepositoriesDetails []services.RepositoryDetails) (remoteRepositories []interface{}, err error) { // Decrypt source Artifactory to get remote repositories with raw text passwords reactivateKeyEncryption, err := tcmc.DeactivateKeyEncryption() if err != nil { @@ -362,7 +362,11 @@ func (tcmc *TransferConfigMergeCommand) decryptAndGetAllRemoteRepositories(remot err = reactivationErr } }() - return tcmc.GetAllRemoteRepositories(remoteRepositoryNames) + var remoteRepositoryKeys []string + for _, remoteRepositoryDetails := range remoteRepositoriesDetails { + remoteRepositoryKeys = append(remoteRepositoryKeys, remoteRepositoryDetails.Key) + } + return tcmc.GetAllRemoteRepositories(remoteRepositoryKeys) } type projectsMapper struct { diff --git a/artifactory/commands/transferfiles/longpropertycheck.go b/artifactory/commands/transferfiles/longpropertycheck.go index 6b067bf40..d3135b08c 100644 --- a/artifactory/commands/transferfiles/longpropertycheck.go +++ b/artifactory/commands/transferfiles/longpropertycheck.go @@ -9,6 +9,7 @@ import ( "github.com/jfrog/gofrog/parallel" "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/transferfiles/api" cmdutils "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils" + "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils/precheckrunner" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" "github.com/jfrog/jfrog-cli-core/v2/utils/progressbar" "github.com/jfrog/jfrog-client-go/artifactory" @@ -67,7 +68,7 @@ func (lpc *LongPropertyCheck) Name() string { return longPropertyCheckName } -func (lpc *LongPropertyCheck) ExecuteCheck(args cmdutils.RunArguments) (passed bool, err error) { +func (lpc *LongPropertyCheck) ExecuteCheck(args precheckrunner.RunArguments) (passed bool, err error) { // Init producer consumer lpc.producerConsumer = parallel.NewRunner(threadCount, maxThreadCapacity, false) lpc.filesChan = make(chan FileWithLongProperty, threadCount) @@ -111,7 +112,7 @@ func (lpc *LongPropertyCheck) ExecuteCheck(args cmdutils.RunArguments) (passed b // Search for long properties in the server and create a search task to find the files that contains them // Returns the number of long properties found -func (lpc *LongPropertyCheck) longPropertiesTaskProducer(progress *progressbar.TasksProgressBar, args cmdutils.RunArguments) int { +func (lpc *LongPropertyCheck) longPropertiesTaskProducer(progress *progressbar.TasksProgressBar, args precheckrunner.RunArguments) int { // Init serviceManager, err := createTransferServiceManager(args.Context, args.ServerDetails) if err != nil { @@ -173,7 +174,7 @@ func getSearchAllPropertiesQuery(pageNumber int) string { // Create a task that fetch from the server the files with the given property. // We keep only the files that are at the requested repos and pass them at the files channel -func createSearchPropertyTask(property Property, repos []string, args cmdutils.RunArguments, filesChan chan FileWithLongProperty, progress *progressbar.TasksProgressBar) parallel.TaskFunc { +func createSearchPropertyTask(property Property, repos []string, args precheckrunner.RunArguments, filesChan chan FileWithLongProperty, progress *progressbar.TasksProgressBar) parallel.TaskFunc { return func(threadId int) (err error) { serviceManager, err := createTransferServiceManager(args.Context, args.ServerDetails) if err != nil { diff --git a/artifactory/commands/transferfiles/longpropertycheck_test.go b/artifactory/commands/transferfiles/longpropertycheck_test.go index 9acb698b0..0519dbbca 100644 --- a/artifactory/commands/transferfiles/longpropertycheck_test.go +++ b/artifactory/commands/transferfiles/longpropertycheck_test.go @@ -2,21 +2,22 @@ package transferfiles import ( "encoding/json" + "io" + "net/http" + "net/http/httptest" + "strings" + "sync" + "testing" + "github.com/jfrog/gofrog/parallel" "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/transferfiles/api" - "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils" + "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils/precheckrunner" commonTests "github.com/jfrog/jfrog-cli-core/v2/common/tests" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-client-go/artifactory" servicesUtils "github.com/jfrog/jfrog-client-go/artifactory/services/utils" clientutils "github.com/jfrog/jfrog-client-go/utils" "github.com/stretchr/testify/assert" - "io" - "net/http" - "net/http/httptest" - "strings" - "sync" - "testing" ) var ( @@ -82,7 +83,7 @@ func testGetLongProperties(t *testing.T, serverProperties, expectedLongPropertie longPropertyCheck := NewLongPropertyCheck([]string{}) longPropertyCheck.filesChan = make(chan FileWithLongProperty, threadCount) - count := longPropertyCheck.longPropertiesTaskProducer(nil, utils.RunArguments{Context: nil, ServerDetails: serverDetails}) + count := longPropertyCheck.longPropertiesTaskProducer(nil, precheckrunner.RunArguments{Context: nil, ServerDetails: serverDetails}) assert.Len(t, expectedLongProperties, count) } @@ -119,7 +120,7 @@ func testSearchPropertyInFilesTask(t *testing.T, prop Property, specificRepos [] wait.Done() }() - task := createSearchPropertyTask(prop, specificRepos, utils.RunArguments{Context: nil, ServerDetails: serverDetails}, filesChan, nil) + task := createSearchPropertyTask(prop, specificRepos, precheckrunner.RunArguments{Context: nil, ServerDetails: serverDetails}, filesChan, nil) assert.NoError(t, task(0)) close(filesChan) wait.Wait() @@ -170,7 +171,7 @@ func testSearchPropertiesInFiles(t *testing.T, properties []Property, specificRe waitCollection.Done() }() - longPropertyCheck.longPropertiesTaskProducer(nil, utils.RunArguments{Context: nil, ServerDetails: serverDetails}) + longPropertyCheck.longPropertiesTaskProducer(nil, precheckrunner.RunArguments{Context: nil, ServerDetails: serverDetails}) longPropertyCheck.producerConsumer.Done() longPropertyCheck.producerConsumer.Run() close(longPropertyCheck.filesChan) @@ -201,7 +202,7 @@ func testLongPropertyCheckWithStubServer(t *testing.T, serverProperties []Proper defer testServer.Close() longPropertyCheck := NewLongPropertyCheck(specificRepos) - passed, err := longPropertyCheck.ExecuteCheck(utils.RunArguments{Context: nil, ServerDetails: serverDetails}) + passed, err := longPropertyCheck.ExecuteCheck(precheckrunner.RunArguments{Context: nil, ServerDetails: serverDetails}) assert.NoError(t, err) assert.Equal(t, shouldPass, passed) } diff --git a/artifactory/commands/transferfiles/transfer.go b/artifactory/commands/transferfiles/transfer.go index 740f036ae..5c50505d5 100644 --- a/artifactory/commands/transferfiles/transfer.go +++ b/artifactory/commands/transferfiles/transfer.go @@ -13,7 +13,7 @@ import ( "time" "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/transferfiles/state" - commandsUtils "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils" + "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils/precheckrunner" "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" @@ -292,7 +292,7 @@ func (tdc *TransferFilesCommand) initStorageInfoManagers() error { } // Creates the Pre-checks runner for the data transfer command -func (tdc *TransferFilesCommand) NewTransferDataPreChecksRunner() (runner *commandsUtils.PreCheckRunner, err error) { +func (tdc *TransferFilesCommand) NewTransferDataPreChecksRunner() (runner *precheckrunner.PreCheckRunner, err error) { // Get relevant repos serviceManager, err := createTransferServiceManager(tdc.context, tdc.sourceServerDetails) if err != nil { @@ -307,7 +307,7 @@ func (tdc *TransferFilesCommand) NewTransferDataPreChecksRunner() (runner *comma return } - runner = commandsUtils.NewPreChecksRunner() + runner = precheckrunner.NewPreChecksRunner() // Add pre checks here runner.AddCheck(NewLongPropertyCheck(append(localRepos, federatedRepos...))) diff --git a/artifactory/commands/utils/checkrunner.go b/artifactory/commands/utils/precheckrunner/checkrunner.go similarity index 99% rename from artifactory/commands/utils/checkrunner.go rename to artifactory/commands/utils/precheckrunner/checkrunner.go index 263a0a01a..eca8a5e2e 100644 --- a/artifactory/commands/utils/checkrunner.go +++ b/artifactory/commands/utils/precheckrunner/checkrunner.go @@ -1,4 +1,4 @@ -package utils +package precheckrunner import ( "context" diff --git a/artifactory/commands/utils/checkrunner_test.go b/artifactory/commands/utils/precheckrunner/checkrunner_test.go similarity index 98% rename from artifactory/commands/utils/checkrunner_test.go rename to artifactory/commands/utils/precheckrunner/checkrunner_test.go index 22533f1cf..476f3eea6 100644 --- a/artifactory/commands/utils/checkrunner_test.go +++ b/artifactory/commands/utils/precheckrunner/checkrunner_test.go @@ -1,4 +1,4 @@ -package utils +package precheckrunner import ( "context" diff --git a/artifactory/commands/utils/remoteurlchecker.go b/artifactory/commands/utils/precheckrunner/remoteurlchecker.go similarity index 94% rename from artifactory/commands/utils/remoteurlchecker.go rename to artifactory/commands/utils/precheckrunner/remoteurlchecker.go index f4f3da31f..173ad52f5 100644 --- a/artifactory/commands/utils/remoteurlchecker.go +++ b/artifactory/commands/utils/precheckrunner/remoteurlchecker.go @@ -1,4 +1,4 @@ -package utils +package precheckrunner import ( "encoding/json" @@ -6,6 +6,7 @@ import ( "net/http" "time" + "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" "github.com/jfrog/jfrog-cli-core/v2/utils/progressbar" "github.com/jfrog/jfrog-client-go/artifactory" @@ -114,7 +115,7 @@ func (rrc *RemoteRepositoryCheck) doCheckRemoteRepositories(args RunArguments, r } // Create rtDetails - rtDetails, err := CreateArtifactoryClientDetails(*rrc.targetServicesManager) + rtDetails, err := utils.CreateArtifactoryClientDetails(*rrc.targetServicesManager) if err != nil { return nil, err } @@ -145,7 +146,7 @@ func (rrc *RemoteRepositoryCheck) startCheckRemoteRepositories(rtDetails *httput LogMsgPrefix: "[Config import]", ExecutionHandler: func() (shouldRetry bool, err error) { // Start the remote repositories check process - resp, responseBody, err := (*rrc.targetServicesManager).Client().SendPost(artifactoryUrl+PluginsExecuteRestApi+"remoteRepositoriesCheck", requestBody, rtDetails) + resp, responseBody, err := (*rrc.targetServicesManager).Client().SendPost(artifactoryUrl+utils.PluginsExecuteRestApi+"remoteRepositoriesCheck", requestBody, rtDetails) if err != nil { return false, err } @@ -190,7 +191,7 @@ func (rrc *RemoteRepositoryCheck) waitForRemoteReposCheckCompletion(rtDetails *h func (rrc *RemoteRepositoryCheck) createImportPollingAction(rtDetails *httputils.HttpClientDetails, artifactoryUrl string, progressBar *progressbar.TasksProgressBar) httputils.PollingAction { return func() (shouldStop bool, responseBody []byte, err error) { // Get config import status - resp, body, _, err := (*rrc.targetServicesManager).Client().SendGet(artifactoryUrl+PluginsExecuteRestApi+"remoteRepositoriesCheckStatus", true, rtDetails) + resp, body, _, err := (*rrc.targetServicesManager).Client().SendGet(artifactoryUrl+utils.PluginsExecuteRestApi+"remoteRepositoriesCheckStatus", true, rtDetails) if err != nil { return true, nil, err } @@ -227,7 +228,7 @@ func unmarshalRemoteUrlResponse(body []byte) (*remoteUrlResponse, error) { // Create csv summary of all the files with inaccessible remote repositories and log the result func handleFailureRun(inaccessibleRepositories []inaccessibleRepository) (err error) { // Create summary - csvPath, err := CreateCSVFile("inaccessible-repositories", inaccessibleRepositories, time.Now()) + csvPath, err := utils.CreateCSVFile("inaccessible-repositories", inaccessibleRepositories, time.Now()) if err != nil { log.Error("Couldn't create the inaccessible remote repository URLs CSV file", err) return diff --git a/artifactory/commands/utils/remoteurlchecker_test.go b/artifactory/commands/utils/precheckrunner/remoteurlchecker_test.go similarity index 98% rename from artifactory/commands/utils/remoteurlchecker_test.go rename to artifactory/commands/utils/precheckrunner/remoteurlchecker_test.go index b90a0d202..a2edde628 100644 --- a/artifactory/commands/utils/remoteurlchecker_test.go +++ b/artifactory/commands/utils/precheckrunner/remoteurlchecker_test.go @@ -1,4 +1,4 @@ -package utils +package precheckrunner import ( "encoding/json" diff --git a/artifactory/commands/utils/precheckrunner/repositorynamingchecker.go b/artifactory/commands/utils/precheckrunner/repositorynamingchecker.go new file mode 100644 index 000000000..42c9bb927 --- /dev/null +++ b/artifactory/commands/utils/precheckrunner/repositorynamingchecker.go @@ -0,0 +1,74 @@ +package precheckrunner + +import ( + "fmt" + "strings" + "time" + + commandUtils "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils" + + "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" + "github.com/jfrog/jfrog-client-go/artifactory/services" + "github.com/jfrog/jfrog-client-go/utils/log" +) + +const ( + repositoryNamingCheckName = "Repositories naming" + illegalDockerRepositoryKeyReason = "Docker repository keys in JFrog Cloud are not allowed to include '.' or '_' characters." +) + +type illegalRepositoryKeys struct { + RepoKey string `json:"repo_key,omitempty"` + Reason string `json:"reason,omitempty"` +} + +// Run repository naming check before transferring configuration from one Artifactory to another +type RepositoryNamingCheck struct { + selectedRepos map[utils.RepoType][]services.RepositoryDetails +} + +func NewRepositoryNamingCheck(selectedRepos map[utils.RepoType][]services.RepositoryDetails) *RepositoryNamingCheck { + return &RepositoryNamingCheck{selectedRepos} +} + +func (drc *RepositoryNamingCheck) Name() string { + return repositoryNamingCheckName +} + +func (drc *RepositoryNamingCheck) ExecuteCheck(args RunArguments) (passed bool, err error) { + results := drc.getIllegalRepositoryKeys() + if len(results) == 0 { + return true, nil + } + + return false, handleFailuresInRepositoryKeysRun(results) +} + +func (drc *RepositoryNamingCheck) getIllegalRepositoryKeys() []illegalRepositoryKeys { + var results []illegalRepositoryKeys + for _, repositoriesOfType := range drc.selectedRepos { + for _, repository := range repositoriesOfType { + if strings.ToLower(repository.PackageType) == "docker" && strings.ContainsAny(repository.Key, "_.") { + log.Debug("Found Docker repository with illegal characters:", repository.Key) + results = append(results, illegalRepositoryKeys{ + RepoKey: repository.Key, + Reason: illegalDockerRepositoryKeyReason, + }) + } + } + } + return results +} + +// Create CSV summary of all the files with illegal repository keys and log the result +func handleFailuresInRepositoryKeysRun(illegalDockerRepositoryKeys []illegalRepositoryKeys) (err error) { + // Create summary + csvPath, err := commandUtils.CreateCSVFile("illegal-repository-keys", illegalDockerRepositoryKeys, time.Now()) + if err != nil { + log.Error("Couldn't create the illegal repository keys CSV file", err) + return + } + // Log result + log.Info(fmt.Sprintf("Found %d illegal repository keys. Check the summary CSV file in: %s", len(illegalDockerRepositoryKeys), csvPath)) + return +} diff --git a/artifactory/commands/utils/precheckrunner/repositorynamingchecker_test.go b/artifactory/commands/utils/precheckrunner/repositorynamingchecker_test.go new file mode 100644 index 000000000..a45394ecf --- /dev/null +++ b/artifactory/commands/utils/precheckrunner/repositorynamingchecker_test.go @@ -0,0 +1,26 @@ +package precheckrunner + +import ( + "testing" + + "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" + "github.com/jfrog/jfrog-client-go/artifactory/services" + "github.com/stretchr/testify/assert" +) + +func TestGetIllegalDockerRepositoryKeys(t *testing.T) { + repositoryNamingCheck := RepositoryNamingCheck{ + selectedRepos: map[utils.RepoType][]services.RepositoryDetails{utils.Local: { + {Key: "a.b-docker", PackageType: "docker"}, + {Key: "a.b-generic", PackageType: "generic"}, + {Key: "a_b-docker", PackageType: "docker"}, + {Key: "ab-docker", PackageType: "docker"}, + {Key: "ab-generic", PackageType: "generic"}, + }}, + } + actualIllegalRepositories := repositoryNamingCheck.getIllegalRepositoryKeys() + assert.ElementsMatch(t, []illegalRepositoryKeys{ + {RepoKey: "a.b-docker", Reason: illegalDockerRepositoryKeyReason}, + {RepoKey: "a_b-docker", Reason: illegalDockerRepositoryKeyReason}, + }, actualIllegalRepositories) +} diff --git a/artifactory/commands/utils/testdata/remoteurlchecker/nuget_repo.json b/artifactory/commands/utils/precheckrunner/testdata/remoteurlchecker/nuget_repo.json similarity index 100% rename from artifactory/commands/utils/testdata/remoteurlchecker/nuget_repo.json rename to artifactory/commands/utils/precheckrunner/testdata/remoteurlchecker/nuget_repo.json diff --git a/artifactory/commands/utils/transferconfigbase.go b/artifactory/commands/utils/transferconfigbase.go index 6f88adda6..7bef0a76e 100644 --- a/artifactory/commands/utils/transferconfigbase.go +++ b/artifactory/commands/utils/transferconfigbase.go @@ -12,6 +12,7 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" "github.com/jfrog/jfrog-client-go/access" "github.com/jfrog/jfrog-client-go/artifactory" + "github.com/jfrog/jfrog-client-go/artifactory/services" clientUtils "github.com/jfrog/jfrog-client-go/utils" "github.com/jfrog/jfrog-client-go/utils/errorutils" "github.com/jfrog/jfrog-client-go/utils/io/httputils" @@ -105,13 +106,13 @@ func (tcb *TransferConfigBase) ValidateDifferentServers() error { } // Create a map between the repository types to the list of repositories to transfer. -func (tcb *TransferConfigBase) GetSelectedRepositories() (map[utils.RepoType][]string, error) { +func (tcb *TransferConfigBase) GetSelectedRepositories() (map[utils.RepoType][]services.RepositoryDetails, error) { allTargetRepos, err := tcb.getAllTargetRepositories() if err != nil { return nil, err } - result := make(map[utils.RepoType][]string, len(utils.RepoTypes)+1) + result := make(map[utils.RepoType][]services.RepositoryDetails, len(utils.RepoTypes)+1) sourceRepos, err := tcb.SourceArtifactoryManager.GetAllRepositories() if err != nil { return nil, err @@ -127,7 +128,7 @@ func (tcb *TransferConfigBase) GetSelectedRepositories() (map[utils.RepoType][]s continue } repoType := utils.RepoTypeFromString(sourceRepo.Type) - result[repoType] = append(result[repoType], sourceRepo.Key) + result[repoType] = append(result[repoType], sourceRepo) } } return result, nil @@ -148,7 +149,7 @@ func (tcb *TransferConfigBase) DeactivateKeyEncryption() (reactivateKeyEncryptio // Transfer all repositories to the target Artifactory server // reposToTransfer - Map between a repository type to the list of repository names // remoteRepositories - Remote repositories params, we get the remote repository params in an earlier stage after decryption -func (tcb *TransferConfigBase) TransferRepositoriesToTarget(reposToTransfer map[utils.RepoType][]string, remoteRepositories []interface{}) (err error) { +func (tcb *TransferConfigBase) TransferRepositoriesToTarget(reposToTransfer map[utils.RepoType][]services.RepositoryDetails, remoteRepositories []interface{}) (err error) { // Transfer remote repositories for i, remoteRepositoryName := range reposToTransfer[utils.Remote] { if err = tcb.createRepositoryAndAssignToProject(remoteRepositories[i], remoteRepositoryName); err != nil { @@ -187,10 +188,10 @@ func (tcb *TransferConfigBase) getAllTargetRepositories() (*datastructures.Set[s // Transfer local, federated, unknown, or virtual repositories // reposToTransfer - Repositories names to transfer // repoType - Repository type -func (tcb *TransferConfigBase) transferSpecificRepositoriesToTarget(reposToTransfer []string, repoType utils.RepoType) (err error) { - for _, repoKey := range reposToTransfer { +func (tcb *TransferConfigBase) transferSpecificRepositoriesToTarget(reposToTransfer []services.RepositoryDetails, repoType utils.RepoType) (err error) { + for _, repo := range reposToTransfer { var params interface{} - if err = tcb.SourceArtifactoryManager.GetRepository(repoKey, ¶ms); err != nil { + if err = tcb.SourceArtifactoryManager.GetRepository(repo.Key, ¶ms); err != nil { return } if repoType == utils.Federated { @@ -198,7 +199,7 @@ func (tcb *TransferConfigBase) transferSpecificRepositoriesToTarget(reposToTrans return } } - if err = tcb.createRepositoryAndAssignToProject(params, repoKey); err != nil { + if err = tcb.createRepositoryAndAssignToProject(params, repo); err != nil { return } } @@ -207,17 +208,17 @@ func (tcb *TransferConfigBase) transferSpecificRepositoriesToTarget(reposToTrans // Transfer virtual repositories // reposToTransfer - Repositories names to transfer -func (tcb *TransferConfigBase) transferVirtualRepositoriesToTarget(reposToTransfer []string) (err error) { +func (tcb *TransferConfigBase) transferVirtualRepositoriesToTarget(reposToTransfer []services.RepositoryDetails) (err error) { allReposParams := make(map[string]interface{}) var singleRepoParamsMap map[string]interface{} var singleRepoParams interface{} // Step 1 - Get and create all virtual repositories with the included repositories removed - for _, repoKey := range reposToTransfer { + for _, repoToTransfer := range reposToTransfer { // Get repository params - if err = tcb.SourceArtifactoryManager.GetRepository(repoKey, &singleRepoParams); err != nil { + if err = tcb.SourceArtifactoryManager.GetRepository(repoToTransfer.Key, &singleRepoParams); err != nil { return } - allReposParams[repoKey] = singleRepoParams + allReposParams[repoToTransfer.Key] = singleRepoParams singleRepoParamsMap, err = InterfaceToMap(singleRepoParams) if err != nil { return @@ -226,7 +227,7 @@ func (tcb *TransferConfigBase) transferVirtualRepositoriesToTarget(reposToTransf // Create virtual repository without included repositories repositories := singleRepoParamsMap["repositories"] delete(singleRepoParamsMap, "repositories") - if err = tcb.createRepositoryAndAssignToProject(singleRepoParamsMap, repoKey); err != nil { + if err = tcb.createRepositoryAndAssignToProject(singleRepoParamsMap, repoToTransfer); err != nil { return } @@ -326,9 +327,9 @@ func (tcb *TransferConfigBase) removeFederatedMembers(federatedRepoParams interf // Create a repository in the target server and assign the repository to the required project, if any. // repoParams - Repository parameters // repoKey - Repository key -func (tcb *TransferConfigBase) createRepositoryAndAssignToProject(repoParams interface{}, repoKey string) (err error) { +func (tcb *TransferConfigBase) createRepositoryAndAssignToProject(repoParams interface{}, repoDetails services.RepositoryDetails) (err error) { var projectKey string - if repoParams, projectKey, err = removeProjectKeyIfNeeded(repoParams, repoKey); err != nil { + if repoParams, projectKey, err = removeProjectKeyIfNeeded(repoParams, repoDetails.Key); err != nil { return } if projectKey != "" { @@ -336,13 +337,13 @@ func (tcb *TransferConfigBase) createRepositoryAndAssignToProject(repoParams int // This is why we make sure to detach it before actually creating the repository. // If the project isn't linked to the repository, an error might come up, but we ignore it because we can't // be certain whether the repository was actually assigned to the project or not. - _ = tcb.TargetAccessManager.UnassignRepoFromProject(repoKey) + _ = tcb.TargetAccessManager.UnassignRepoFromProject(repoDetails.Key) } - if err = tcb.TargetArtifactoryManager.CreateRepositoryWithParams(repoParams, repoKey); err != nil { + if err = tcb.TargetArtifactoryManager.CreateRepositoryWithParams(repoParams, repoDetails.Key); err != nil { return } if projectKey != "" { - return tcb.TargetAccessManager.AssignRepoToProject(repoKey, projectKey, true) + return tcb.TargetAccessManager.AssignRepoToProject(repoDetails.Key, projectKey, true) } return } diff --git a/artifactory/commands/utils/transferconfigbase_test.go b/artifactory/commands/utils/transferconfigbase_test.go index 1d0cdc7d0..ac091f28c 100644 --- a/artifactory/commands/utils/transferconfigbase_test.go +++ b/artifactory/commands/utils/transferconfigbase_test.go @@ -153,10 +153,10 @@ func TestGetSelectedRepositories(t *testing.T) { selectedRepos, err := transferConfigBase.GetSelectedRepositories() assert.NoError(t, err) assert.Len(t, selectedRepos, 4) - assert.Equal(t, []string{"generic-local"}, selectedRepos[utils.Local]) - assert.Equal(t, []string{"generic-remote"}, selectedRepos[utils.Remote]) - assert.Equal(t, []string{"generic-virtual"}, selectedRepos[utils.Virtual]) - assert.Equal(t, []string{"generic-federated"}, selectedRepos[utils.Federated]) + assert.Equal(t, []services.RepositoryDetails{{Key: "generic-local", Type: "local"}}, selectedRepos[utils.Local]) + assert.Equal(t, []services.RepositoryDetails{{Key: "generic-remote", Type: "remote"}}, selectedRepos[utils.Remote]) + assert.Equal(t, []services.RepositoryDetails{{Key: "generic-virtual", Type: "virtual"}}, selectedRepos[utils.Virtual]) + assert.Equal(t, []services.RepositoryDetails{{Key: "generic-federated", Type: "federated"}}, selectedRepos[utils.Federated]) } func TestTransferRepositoryToTarget(t *testing.T) { @@ -189,7 +189,8 @@ func TestTransferRepositoryToTarget(t *testing.T) { transferConfigBase := createTransferConfigBase(t, serverDetails, serverDetails) assert.False(t, transferConfigBase.FederatedMembersRemoved) - err := transferConfigBase.transferSpecificRepositoriesToTarget([]string{"federated-local", "federated-local-no-members"}, utils.Federated) + err := transferConfigBase.transferSpecificRepositoriesToTarget([]services.RepositoryDetails{ + {Key: "federated-local"}, {Key: "federated-local-no-members"}}, utils.Federated) assert.NoError(t, err) assert.True(t, transferConfigBase.FederatedMembersRemoved) } @@ -237,7 +238,7 @@ func TestTransferVirtualRepositoriesToTarget(t *testing.T) { defer testServer.Close() transferConfigBase := createTransferConfigBase(t, serverDetails, serverDetails) - assert.NoError(t, transferConfigBase.transferVirtualRepositoriesToTarget([]string{"a-virtual", "b-virtual"})) + assert.NoError(t, transferConfigBase.transferVirtualRepositoriesToTarget([]services.RepositoryDetails{{Key: "a-virtual"}, {Key: "b-virtual"}})) } func TestDeactivateKeyEncryption(t *testing.T) { @@ -343,7 +344,7 @@ func TestCreateRepositoryAndAssignToProject(t *testing.T) { repoParams := services.NewLocalRepositoryBaseParams() repoParams.Key = "local-repo" repoParams.ProjectKey = projectKey - err := transferConfigBase.createRepositoryAndAssignToProject(repoParams, repoParams.Key) + err := transferConfigBase.createRepositoryAndAssignToProject(repoParams, services.RepositoryDetails{Key: repoParams.Key}) assert.NoError(t, err) assert.True(t, projectUnassigned) assert.True(t, repositoryCreated)