github.com/jfrog/jfrog-cli-core/v2@v2.51.0/artifactory/commands/transferconfig/transferconfig_test.go (about) 1 package transferconfig 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "io" 7 "net/http" 8 "os" 9 "path/filepath" 10 "strings" 11 "testing" 12 13 commandUtils "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils" 14 "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" 15 commonTests "github.com/jfrog/jfrog-cli-core/v2/common/tests" 16 "github.com/jfrog/jfrog-cli-core/v2/utils/config" 17 "github.com/jfrog/jfrog-cli-core/v2/utils/tests" 18 "github.com/jfrog/jfrog-client-go/artifactory/services" 19 "github.com/jfrog/jfrog-client-go/utils/io/fileutils" 20 "github.com/stretchr/testify/assert" 21 ) 22 23 func TestExportSourceArtifactory(t *testing.T) { 24 // Create transfer config command 25 testServer, serverDetails, _ := commonTests.CreateRtRestsMockServer(t, func(w http.ResponseWriter, r *http.Request) { 26 w.WriteHeader(http.StatusOK) 27 28 // Read body 29 content, err := io.ReadAll(r.Body) 30 assert.NoError(t, err) 31 var actual services.ExportBody 32 assert.NoError(t, json.Unmarshal(content, &actual)) 33 34 // Make sure all parameters as expected 35 assert.False(t, *actual.IncludeMetadata) 36 assert.False(t, *actual.Verbose) 37 assert.True(t, *actual.ExcludeContent) 38 assert.Nil(t, actual.CreateArchive) 39 assert.Nil(t, actual.M2) 40 41 // Create the export-dir in the export path 42 assert.NoError(t, os.Mkdir(filepath.Join(actual.ExportPath, "export-dir"), os.ModePerm)) 43 }) 44 defer testServer.Close() 45 46 // Create working dir 47 tmpDir, createTempDirCallback := tests.CreateTempDirWithCallbackAndAssert(t) 48 defer createTempDirCallback() 49 50 // Test export source artifactory 51 transferConfigCmd := createTransferConfigCommand(t, serverDetails, nil).SetSourceWorkingDir(tmpDir) 52 exportDir, cleanUp, err := transferConfigCmd.exportSourceArtifactory() 53 assert.NoError(t, err) 54 assert.DirExists(t, exportDir) 55 assert.NoError(t, cleanUp()) 56 assert.NoDirExists(t, exportDir) 57 assert.True(t, strings.HasPrefix(exportDir, tmpDir)) 58 } 59 60 func TestImportToTargetArtifactory(t *testing.T) { 61 // Create transfer config command 62 testServer, serverDetails, _ := commonTests.CreateRtRestsMockServer(t, func(w http.ResponseWriter, r *http.Request) { 63 w.WriteHeader(http.StatusOK) 64 65 content, err := io.ReadAll(r.Body) 66 assert.NoError(t, err) 67 if r.RequestURI == "/"+commandUtils.PluginsExecuteRestApi+"configImport" { 68 // Read body 69 assert.Equal(t, []byte("zip-content"), content) 70 _, err = w.Write([]byte("123456")) 71 assert.NoError(t, err) 72 return 73 } 74 75 assert.Equal(t, []byte("123456"), content) 76 }) 77 defer testServer.Close() 78 79 // Test export source artifactory 80 transferConfigCmd := createTransferConfigCommand(t, nil, serverDetails) 81 err := transferConfigCmd.importToTargetArtifactory(bytes.NewBuffer([]byte("zip-content"))) 82 assert.NoError(t, err) 83 } 84 85 func TestGetConfigXml(t *testing.T) { 86 // Create transfer config command 87 testServer, serverDetails, _ := commonTests.CreateRtRestsMockServer(t, func(w http.ResponseWriter, r *http.Request) { 88 w.WriteHeader(http.StatusOK) 89 if r.RequestURI == "/api/system/configuration" { 90 _, err := w.Write([]byte("<config></config>")) 91 assert.NoError(t, err) 92 } 93 }) 94 defer testServer.Close() 95 96 // Test get config xml 97 transferConfigCmd := createTransferConfigCommand(t, serverDetails, nil) 98 configXml, _, err := transferConfigCmd.getEncryptedItems(make(map[utils.RepoType][]services.RepositoryDetails)) 99 assert.NoError(t, err) 100 assert.Equal(t, "<config></config>", configXml) 101 } 102 103 func TestValidateTargetServer(t *testing.T) { 104 var users []services.User 105 // Create transfer config command 106 testServer, serverDetails, _ := commonTests.CreateRtRestsMockServer(t, func(w http.ResponseWriter, r *http.Request) { 107 switch r.RequestURI { 108 case "/" + commandUtils.PluginsExecuteRestApi + "checkPermissions": 109 w.WriteHeader(http.StatusOK) 110 case "/" + commandUtils.PluginsExecuteRestApi + "configImportVersion": 111 content, err := json.Marshal(commandUtils.VersionResponse{Version: "1.0.0"}) 112 assert.NoError(t, err) 113 _, err = w.Write(content) 114 assert.NoError(t, err) 115 case "/api/system/version": 116 content, err := json.Marshal(commandUtils.VersionResponse{Version: "7.0.0"}) 117 assert.NoError(t, err) 118 _, err = w.Write(content) 119 assert.NoError(t, err) 120 default: 121 content, err := json.Marshal(users) 122 assert.NoError(t, err) 123 _, err = w.Write(content) 124 assert.NoError(t, err) 125 users = append(users, services.User{}) 126 } 127 }) 128 defer testServer.Close() 129 130 transferConfigCmd := createTransferConfigCommand(t, &config.ServerDetails{Url: "dummy-url"}, serverDetails) 131 // Test no users 132 err := transferConfigCmd.validateTargetServer() 133 assert.NoError(t, err) 134 135 // Test 1 users 136 err = transferConfigCmd.validateTargetServer() 137 assert.NoError(t, err) 138 139 // Test 2 users 140 err = transferConfigCmd.validateTargetServer() 141 assert.NoError(t, err) 142 143 // Test 3 users 144 err = transferConfigCmd.validateTargetServer() 145 assert.ErrorContains(t, err, "cowardly refusing to import the config to the target server, because it contains more than 2 users.") 146 147 // Assert force = true 148 transferConfigCmd.force = true 149 err = transferConfigCmd.validateTargetServer() 150 assert.NoError(t, err) 151 } 152 153 func TestVerifyConfigImportPluginNotInstalled(t *testing.T) { 154 // Create transfer config command 155 testServer, serverDetails, _ := commonTests.CreateRtRestsMockServer(t, func(w http.ResponseWriter, _ *http.Request) { 156 w.WriteHeader(http.StatusNotFound) 157 _, err := w.Write([]byte("Not found")) 158 assert.NoError(t, err) 159 }) 160 defer testServer.Close() 161 162 transferConfigCmd := createTransferConfigCommand(t, &config.ServerDetails{Url: "dummy-url"}, serverDetails) 163 err := transferConfigCmd.verifyConfigImportPlugin() 164 assert.ErrorContains(t, err, "Response from Artifactory: 404 Not Found.") 165 } 166 167 func TestVerifyConfigImportPluginForbidden(t *testing.T) { 168 // Create transfer config command 169 testServer, serverDetails, _ := commonTests.CreateRtRestsMockServer(t, func(w http.ResponseWriter, _ *http.Request) { 170 w.WriteHeader(http.StatusForbidden) 171 _, err := w.Write([]byte("An admin user is required")) 172 assert.NoError(t, err) 173 }) 174 defer testServer.Close() 175 176 transferConfigCmd := createTransferConfigCommand(t, &config.ServerDetails{Url: "dummy-url"}, serverDetails) 177 err := transferConfigCmd.verifyConfigImportPlugin() 178 assert.ErrorContains(t, err, "Response from Artifactory: 403 Forbidden.") 179 } 180 181 func TestCreateExportPath(t *testing.T) { 182 transferConfigBase := NewTransferConfigCommand(nil, nil) 183 184 // Create export path and check results 185 exportPath, unsetTempDir, err := transferConfigBase.createExportPath() 186 unsetTempDir() 187 assert.NoError(t, err) 188 assert.NotEmpty(t, exportPath) 189 assert.DirExists(t, exportPath) 190 191 // Create working dir 192 const testExportDir = "test-export-dir" 193 tmpDir, createTempDirCallback := tests.CreateTempDirWithCallbackAndAssert(t) 194 defer createTempDirCallback() 195 tmpDir = filepath.Join(tmpDir, testExportDir) 196 assert.NoError(t, os.MkdirAll(tmpDir, 0700)) 197 transferConfigBase.sourceWorkingDir = tmpDir 198 199 // Create export path with custom working dir 200 exportPath, unsetTempDir, err = transferConfigBase.createExportPath() 201 unsetTempDir() 202 assert.NoError(t, err) 203 assert.True(t, strings.HasPrefix(exportPath, tmpDir)) 204 assert.DirExists(t, exportPath) 205 206 // Ensure unsetTempDir did work 207 assert.NotContains(t, fileutils.GetTempDirBase(), testExportDir) 208 } 209 210 func createTransferConfigCommand(t *testing.T, sourceServerDetails, targetServerDetails *config.ServerDetails) *TransferConfigCommand { 211 transferConfigBase := NewTransferConfigCommand(sourceServerDetails, targetServerDetails) 212 var err error 213 if sourceServerDetails != nil { 214 transferConfigBase.SourceArtifactoryManager, err = utils.CreateServiceManager(sourceServerDetails, -1, 0, false) 215 assert.NoError(t, err) 216 } 217 if targetServerDetails != nil { 218 transferConfigBase.TargetArtifactoryManager, err = utils.CreateServiceManager(targetServerDetails, -1, 0, false) 219 assert.NoError(t, err) 220 } 221 return transferConfigBase 222 } 223 224 var validateMinVersionAndDifferentServersCases = []struct { 225 testName string 226 sourceVersion string 227 targetVersion string 228 expectedError string 229 }{ 230 {testName: "Same version", sourceVersion: minTransferConfigArtifactoryVersion, targetVersion: minTransferConfigArtifactoryVersion, expectedError: ""}, 231 {testName: "Different versions", sourceVersion: "7.0.0", targetVersion: "7.0.1", expectedError: ""}, 232 {testName: "Low Artifactory version", sourceVersion: "6.0.0", targetVersion: "7.0.0", expectedError: "while this operation requires version"}, 233 {testName: "Source newer than target", sourceVersion: "7.0.1", targetVersion: "7.0.0", expectedError: "can't be higher than the target Artifactory version"}, 234 } 235 236 func TestValidateMinVersion(t *testing.T) { 237 var sourceRtVersion, targetRtVersion string 238 // Create transfer config command 239 sourceTestServer, sourceServerDetails, _ := commonTests.CreateRtRestsMockServer(t, func(w http.ResponseWriter, _ *http.Request) { 240 content, err := json.Marshal(commandUtils.VersionResponse{Version: sourceRtVersion}) 241 assert.NoError(t, err) 242 _, err = w.Write(content) 243 assert.NoError(t, err) 244 }) 245 defer sourceTestServer.Close() 246 targetTestServer, targetServerDetails, _ := commonTests.CreateRtRestsMockServer(t, func(w http.ResponseWriter, _ *http.Request) { 247 content, err := json.Marshal(commandUtils.VersionResponse{Version: targetRtVersion}) 248 assert.NoError(t, err) 249 _, err = w.Write(content) 250 assert.NoError(t, err) 251 }) 252 defer targetTestServer.Close() 253 254 for _, testCase := range validateMinVersionAndDifferentServersCases { 255 t.Run(testCase.testName, func(t *testing.T) { 256 sourceRtVersion = testCase.sourceVersion 257 targetRtVersion = testCase.targetVersion 258 actualSourceRtVersion, err := createTransferConfigCommand(t, sourceServerDetails, targetServerDetails).validateMinVersion() 259 if testCase.expectedError == "" { 260 assert.NoError(t, err) 261 assert.Equal(t, sourceRtVersion, actualSourceRtVersion) 262 } else { 263 assert.ErrorContains(t, err, testCase.expectedError) 264 } 265 }) 266 } 267 } 268 269 func TestValidateAccessServerConnection(t *testing.T) { 270 // Create transfer config command 271 testServer, serverDetails, accessManager := commonTests.CreateAccessRestsMockServer(t, func(w http.ResponseWriter, r *http.Request) { 272 switch r.RequestURI { 273 case "/access/api/v1/system/ping": 274 w.WriteHeader(http.StatusOK) 275 default: 276 assert.Fail(t, "Unexpected request URI: "+r.RequestURI) 277 } 278 }) 279 defer testServer.Close() 280 281 transferConfigCmd := createTransferConfigCommand(t, nil, nil) 282 err := transferConfigCmd.ValidateAccessServerConnection(serverDetails, accessManager) 283 assert.NoError(t, err) 284 } 285 286 func TestValidateAccessServerConnectionForbidden(t *testing.T) { 287 // Create transfer config command 288 testServer, serverDetails, accessManager := commonTests.CreateAccessRestsMockServer(t, func(w http.ResponseWriter, r *http.Request) { 289 switch r.RequestURI { 290 case "/access/api/v1/system/ping": 291 w.WriteHeader(http.StatusForbidden) 292 default: 293 assert.Fail(t, "Unexpected request URI: "+r.RequestURI) 294 } 295 }) 296 defer testServer.Close() 297 298 transferConfigCmd := createTransferConfigCommand(t, nil, nil) 299 // Assert access token invalid error 300 err := transferConfigCmd.ValidateAccessServerConnection(serverDetails, accessManager) 301 assert.ErrorContains(t, err, "the 'test-server' instance Access Token is not valid. Please provide a valid access token by running the 'jf c edit test-server'") 302 }