github.com/jfrog/jfrog-cli-go@v1.22.1-0.20200318093948-4826ef344ffd/artifactory_test.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "crypto/tls" 6 "encoding/json" 7 "errors" 8 "fmt" 9 "io/ioutil" 10 "net" 11 "net/http" 12 "net/url" 13 "os" 14 "os/exec" 15 "path" 16 "path/filepath" 17 "regexp" 18 "strconv" 19 "strings" 20 "testing" 21 "time" 22 23 "github.com/buger/jsonparser" 24 "github.com/jfrog/gofrog/io" 25 "github.com/jfrog/jfrog-cli-go/artifactory/commands/generic" 26 "github.com/jfrog/jfrog-cli-go/artifactory/spec" 27 "github.com/jfrog/jfrog-cli-go/artifactory/utils" 28 "github.com/jfrog/jfrog-cli-go/inttestutils" 29 "github.com/jfrog/jfrog-cli-go/utils/cliutils" 30 "github.com/jfrog/jfrog-cli-go/utils/config" 31 logUtils "github.com/jfrog/jfrog-cli-go/utils/log" 32 "github.com/jfrog/jfrog-cli-go/utils/tests" 33 cliproxy "github.com/jfrog/jfrog-cli-go/utils/tests/proxy/server" 34 "github.com/jfrog/jfrog-cli-go/utils/tests/proxy/server/certificate" 35 "github.com/jfrog/jfrog-client-go/artifactory/services" 36 rtutils "github.com/jfrog/jfrog-client-go/artifactory/services/utils" 37 "github.com/jfrog/jfrog-client-go/artifactory/services/utils/tests/xray" 38 "github.com/jfrog/jfrog-client-go/auth" 39 "github.com/jfrog/jfrog-client-go/httpclient" 40 clientutils "github.com/jfrog/jfrog-client-go/utils" 41 "github.com/jfrog/jfrog-client-go/utils/errorutils" 42 "github.com/jfrog/jfrog-client-go/utils/io/fileutils" 43 "github.com/jfrog/jfrog-client-go/utils/io/httputils" 44 "github.com/jfrog/jfrog-client-go/utils/log" 45 "github.com/mholt/archiver" 46 "github.com/stretchr/testify/assert" 47 ) 48 49 // JFrog CLI for Artifactory commands 50 var artifactoryCli *tests.JfrogCli 51 52 // JFrog CLI for config command only (doesn't pass the --ssh-passphrase flag) 53 var configArtifactoryCli *tests.JfrogCli 54 55 var artifactoryDetails *config.ArtifactoryDetails 56 var artAuth auth.CommonDetails 57 var artHttpDetails httputils.HttpClientDetails 58 59 func InitArtifactoryTests() { 60 initArtifactoryCli() 61 createReposIfNeeded() 62 cleanArtifactoryTest() 63 } 64 65 func authenticate() string { 66 artifactoryDetails = &config.ArtifactoryDetails{Url: clientutils.AddTrailingSlashIfNeeded(*tests.RtUrl), SshKeyPath: *tests.RtSshKeyPath, SshPassphrase: *tests.RtSshPassphrase, AccessToken: *tests.RtAccessToken} 67 cred := "--url=" + *tests.RtUrl 68 if *tests.RtDistributionUrl != "" { 69 cred += " --dist-url=" + *tests.RtDistributionUrl 70 } 71 if !fileutils.IsSshUrl(artifactoryDetails.Url) { 72 if *tests.RtApiKey != "" { 73 artifactoryDetails.ApiKey = *tests.RtApiKey 74 } else if *tests.RtAccessToken != "" { 75 artifactoryDetails.AccessToken = *tests.RtAccessToken 76 } else { 77 artifactoryDetails.User = *tests.RtUser 78 artifactoryDetails.Password = *tests.RtPassword 79 } 80 } 81 cred += getArtifactoryTestCredentials() 82 var err error 83 if artAuth, err = artifactoryDetails.CreateArtAuthConfig(); err != nil { 84 cliutils.ExitOnErr(errors.New("Failed while attempting to authenticate with Artifactory: " + err.Error())) 85 } 86 artifactoryDetails.SshAuthHeaders = artAuth.GetSshAuthHeaders() 87 artifactoryDetails.Url = artAuth.GetUrl() 88 artifactoryDetails.SshUrl = artAuth.GetSshUrl() 89 artHttpDetails = artAuth.CreateHttpClientDetails() 90 return cred 91 } 92 93 // A Jfrog CLI to be used to execute a config task. 94 // Removed the ssh-passphrase flag that cannot be passed to with a config command 95 func createConfigJfrogCLI(cred string) *tests.JfrogCli { 96 if strings.Contains(cred, " --ssh-passphrase=") { 97 cred = strings.Replace(cred, " --ssh-passphrase="+*tests.RtSshPassphrase, "", -1) 98 } 99 return tests.NewJfrogCli(execMain, "jfrog rt", cred) 100 } 101 102 func getArtifactoryTestCredentials() string { 103 if fileutils.IsSshUrl(artifactoryDetails.Url) { 104 return getSshCredentials() 105 } 106 if *tests.RtApiKey != "" { 107 return " --apikey=" + *tests.RtApiKey 108 } 109 if *tests.RtAccessToken != "" { 110 return " --access-token=" + *tests.RtAccessToken 111 } 112 return " --user=" + *tests.RtUser + " --password=" + *tests.RtPassword 113 } 114 115 func getSshCredentials() string { 116 cred := "" 117 if *tests.RtSshKeyPath != "" { 118 cred += " --ssh-key-path=" + *tests.RtSshKeyPath 119 } 120 if *tests.RtSshPassphrase != "" { 121 cred += " --ssh-passphrase=" + *tests.RtSshPassphrase 122 } 123 return cred 124 } 125 126 func TestArtifactorySimpleUploadSpec(t *testing.T) { 127 initArtifactoryTest(t) 128 specFile, err := tests.CreateSpec(tests.UploadFlatRecursive) 129 assert.NoError(t, err) 130 artifactoryCli.Exec("upload", "--spec="+specFile) 131 searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix) 132 assert.NoError(t, err) 133 verifyExistInArtifactory(tests.GetSimpleUploadExpectedRepo1(), searchFilePath, t) 134 cleanArtifactoryTest() 135 } 136 137 func TestArtifactorySimpleUploadWithWildcardSpec(t *testing.T) { 138 initArtifactoryTest(t) 139 // Init tmp dir 140 specFile, err := tests.CreateSpec(tests.UploadTempWildcard) 141 assert.NoError(t, err) 142 err = fileutils.CopyDir(tests.GetTestResourcesPath()+"cache", filepath.Dir(specFile), true) 143 assert.NoError(t, err) 144 // Upload 145 artifactoryCli.Exec("upload", "--spec="+specFile) 146 searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix) 147 assert.NoError(t, err) 148 verifyExistInArtifactory(tests.GetSimpleWildcardUploadExpectedRepo1(), searchFilePath, t) 149 cleanArtifactoryTest() 150 } 151 152 // This test is similar to TestArtifactorySimpleUploadSpec but using "--server-id" flag 153 func TestArtifactorySimpleUploadSpecUsingConfig(t *testing.T) { 154 initArtifactoryTest(t) 155 passphrase := createServerConfigAndReturnPassphrase() 156 artifactoryCommandExecutor := tests.NewJfrogCli(execMain, "jfrog rt", "") 157 specFile, err := tests.CreateSpec(tests.UploadFlatRecursive) 158 assert.NoError(t, err) 159 artifactoryCommandExecutor.Exec("upload", "--spec="+specFile, "--server-id="+tests.RtServerId, passphrase) 160 161 searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix) 162 assert.NoError(t, err) 163 verifyExistInArtifactory(tests.GetSimpleUploadExpectedRepo1(), searchFilePath, t) 164 deleteServerConfig() 165 cleanArtifactoryTest() 166 } 167 168 func TestArtifactoryUploadPathWithSpecialCharsAsNoRegex(t *testing.T) { 169 initArtifactoryTest(t) 170 filePath := getSpecialCharFilePath() 171 172 artifactoryCli.Exec("upload", filePath, tests.Repo1) 173 searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix) 174 assert.NoError(t, err) 175 176 verifyExistInArtifactory(tests.GetSimpleUploadSpecialCharNoRegexExpectedRepo1(), searchFilePath, t) 177 cleanArtifactoryTest() 178 } 179 180 func TestArtifactoryDownloadFromVirtual(t *testing.T) { 181 initArtifactoryTest(t) 182 183 artifactoryCli.Exec("upload", "testsdata/a/*", tests.Repo1, "--flat=false") 184 artifactoryCli.Exec("dl", tests.VirtualRepo+"/testsdata/(*)", tests.Out+"/"+"{1}", "--flat=true") 185 186 paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 187 tests.VerifyExistLocally(tests.GetVirtualDownloadExpected(), paths, t) 188 189 cleanArtifactoryTest() 190 } 191 192 func TestArtifactoryDownloadPathWithSpecialChars(t *testing.T) { 193 initArtifactoryTest(t) 194 artifactoryCli.Exec("upload", getSpecialCharFilePath(), tests.Repo1, "--flat=false") 195 artifactoryCli.Exec("upload", "testsdata/c#/a#1.in", tests.Repo1, "--flat=false") 196 197 artifactoryCli.Exec("dl", tests.Repo1+"/testsdata/a$+~&^a#/a*", tests.Out+fileutils.GetFileSeparator(), "--flat=true") 198 artifactoryCli.Exec("dl", tests.Repo1+"/testsdata/c#/a#1.in", tests.Out+fileutils.GetFileSeparator(), "--flat=true") 199 200 paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 201 tests.VerifyExistLocally([]string{tests.Out + fileutils.GetFileSeparator() + "a1.in", tests.Out + fileutils.GetFileSeparator() + "a#1.in"}, paths, t) 202 203 cleanArtifactoryTest() 204 } 205 206 func TestArtifactoryConcurrentDownload(t *testing.T) { 207 testArtifactoryDownload(cliutils.DownloadMinSplitKb*1000, t) 208 } 209 210 func TestArtifactoryBulkDownload(t *testing.T) { 211 testArtifactoryDownload(cliutils.DownloadMinSplitKb*1000-1, t) 212 } 213 214 func testArtifactoryDownload(fileSize int, t *testing.T) { 215 initArtifactoryTest(t) 216 err := fileutils.CreateDirIfNotExist(tests.Out) 217 assert.NoError(t, err) 218 randFile, err := io.CreateRandFile(filepath.Join(tests.Out, "randFile"), fileSize) 219 assert.NoError(t, err) 220 localFileDetails, err := fileutils.GetFileDetails(randFile.Name()) 221 assert.NoError(t, err) 222 223 artifactoryCli.Exec("u", randFile.Name(), tests.Repo1+"/testsdata/", "--flat=true") 224 randFile.File.Close() 225 os.RemoveAll(tests.Out) 226 artifactoryCli.Exec("dl", tests.Repo1+"/testsdata/", tests.Out+fileutils.GetFileSeparator(), "--flat=true") 227 228 paths, err := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 229 assert.NoError(t, err) 230 tests.VerifyExistLocally([]string{tests.Out + fileutils.GetFileSeparator() + "randFile"}, paths, t) 231 tests.ValidateChecksums(tests.Out+fileutils.GetFileSeparator()+"randFile", localFileDetails.Checksum, t) 232 cleanArtifactoryTest() 233 } 234 235 func TestArtifactoryDownloadWildcardInRepo(t *testing.T) { 236 initArtifactoryTest(t) 237 var filePath = getSpecialCharFilePath() 238 239 // Upload a file to repo1 and another one to repo2 240 artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/a1.in") 241 artifactoryCli.Exec("upload", filePath, tests.Repo2+"/path/a2.in") 242 243 specFile, err := tests.CreateSpec(tests.DownloadWildcardRepo) 244 assert.NoError(t, err) 245 246 // Verify the 2 files exist using `*` in the repository name 247 verifyExistInArtifactory(tests.GetDownloadWildcardRepo(), specFile, t) 248 249 // Download the 2 files with `*` in the repository name 250 artifactoryCli.Exec("dl", "--spec="+specFile) 251 paths, err := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 252 assert.NoError(t, err) 253 tests.VerifyExistLocally([]string{filepath.Join(tests.Out, "a1.in"), filepath.Join(tests.Out, "a2.in")}, paths, t) 254 cleanArtifactoryTest() 255 } 256 257 func TestArtifactoryCopySingleFileNonFlat(t *testing.T) { 258 initArtifactoryTest(t) 259 var filePath = getSpecialCharFilePath() 260 261 artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/") 262 artifactoryCli.Exec("cp", tests.Repo1+"/path/a1.in", tests.Repo2) 263 searchPath, err := tests.CreateSpec(tests.SearchRepo2) 264 assert.NoError(t, err) 265 verifyExistInArtifactory(tests.GetSingleFileCopy(), searchPath, t) 266 cleanArtifactoryTest() 267 } 268 269 func TestAqlFindingItemOnRoot(t *testing.T) { 270 initArtifactoryTest(t) 271 var filePath = getSpecialCharFilePath() 272 273 artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/inner/") 274 artifactoryCli.Exec("upload", filePath, tests.Repo1+"/someFile", "--flat=true") 275 artifactoryCli.Exec("cp", tests.Repo1+"/*", tests.Repo2) 276 searchPath, err := tests.CreateSpec(tests.SearchRepo2) 277 assert.NoError(t, err) 278 verifyExistInArtifactory(tests.GetAnyItemCopy(), searchPath, t) 279 artifactoryCli.Exec("del", tests.Repo2+"/*") 280 artifactoryCli.Exec("del", tests.Repo1+"/*") 281 artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/") 282 artifactoryCli.Exec("upload", filePath, tests.Repo1+"/someFile", "--flat=true") 283 artifactoryCli.Exec("cp", tests.Repo1+"/*/", tests.Repo2) 284 verifyExistInArtifactory(tests.GetSingleFileCopy(), searchPath, t) 285 cleanArtifactoryTest() 286 } 287 288 func TestExitCode(t *testing.T) { 289 initArtifactoryTest(t) 290 291 err := artifactoryCli.Exec("upload", "DummyText", tests.Repo1, "--fail-no-op=true") 292 checkExitCode(t, cliutils.ExitCodeError, err) 293 err = artifactoryCli.Exec("upload", path.Join("testsdata", "a", "a1.in"), "tests.Repo1") 294 checkExitCode(t, cliutils.ExitCodeError, err) 295 err = artifactoryCli.Exec("upload", "testsdata/a/(*.dummyExt)", tests.Repo1+"/{1}.in", "--fail-no-op=true") 296 checkExitCode(t, cliutils.ExitCodeFailNoOp, err) 297 298 err = artifactoryCli.Exec("dl", "DummyFolder", "--fail-no-op=true") 299 checkExitCode(t, cliutils.ExitCodeFailNoOp, err) 300 301 //upload dummy file inorder to test move & copy 302 artifactoryCli.Exec("upload", path.Join("testsdata", "a", "a1.in"), tests.Repo1) 303 err = artifactoryCli.Exec("move", tests.Repo1, "DummyTargetPath") 304 checkExitCode(t, cliutils.ExitCodeError, err) 305 err = artifactoryCli.Exec("move", "DummyText", tests.Repo1, "--fail-no-op=true") 306 checkExitCode(t, cliutils.ExitCodeFailNoOp, err) 307 308 err = artifactoryCli.Exec("copy", tests.Repo1, "DummyTargetPath") 309 checkExitCode(t, cliutils.ExitCodeError, err) 310 err = artifactoryCli.Exec("copy", "DummyText", tests.Repo1, "--fail-no-op=true") 311 checkExitCode(t, cliutils.ExitCodeFailNoOp, err) 312 313 err = artifactoryCli.Exec("delete", "DummyText", "--fail-no-op=true") 314 checkExitCode(t, cliutils.ExitCodeFailNoOp, err) 315 316 err = artifactoryCli.Exec("s", "DummyText", "--fail-no-op=true") 317 checkExitCode(t, cliutils.ExitCodeFailNoOp, err) 318 319 err = artifactoryCli.Exec("sp", "DummyText", "prop=val;key=value", "--fail-no-op=true") 320 checkExitCode(t, cliutils.ExitCodeFailNoOp, err) 321 322 err = artifactoryCli.Exec("delp", "DummyText", "prop=val;key=value", "--fail-no-op=true") 323 checkExitCode(t, cliutils.ExitCodeFailNoOp, err) 324 325 cleanArtifactoryTest() 326 } 327 328 func checkExitCode(t *testing.T, expected cliutils.ExitCode, er error) { 329 switch underlyingType := er.(type) { 330 case cliutils.CliError: 331 assert.Equal(t, expected, underlyingType.ExitCode) 332 default: 333 assert.Fail(t, "Exit code expected error code %v, got %v", expected.Code, er) 334 } 335 } 336 func TestArtifactoryDirectoryCopy(t *testing.T) { 337 initArtifactoryTest(t) 338 var filePath = getSpecialCharFilePath() 339 340 artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/") 341 artifactoryCli.Exec("cp", tests.Repo1+"/path/", tests.Repo2) 342 searchPath, err := tests.CreateSpec(tests.SearchRepo2) 343 assert.NoError(t, err) 344 verifyExistInArtifactory(tests.GetSingleFileCopy(), searchPath, t) 345 cleanArtifactoryTest() 346 } 347 348 func TestArtifactoryDirectoryCopyUsingWildcard(t *testing.T) { 349 initArtifactoryTest(t) 350 var filePath = getSpecialCharFilePath() 351 352 artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/") 353 artifactoryCli.Exec("cp", tests.Repo1+"/*/", tests.Repo2) 354 searchPath, err := tests.CreateSpec(tests.SearchRepo2) 355 assert.NoError(t, err) 356 verifyExistInArtifactory(tests.GetSingleFileCopy(), searchPath, t) 357 cleanArtifactoryTest() 358 } 359 360 func TestArtifactoryCopyFilesNameWithParentheses(t *testing.T) { 361 initArtifactoryTest(t) 362 363 artifactoryCli.Exec("upload", "testsdata/b/*", tests.Repo1, "--flat=false") 364 artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/(/(.in", tests.Repo2) 365 artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/(b/(b.in", tests.Repo2) 366 artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/b(/b(.in", tests.Repo2) 367 artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/b)/b).in", tests.Repo2) 368 artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/(b)/(b).in", tests.Repo2) 369 artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/)b/)b.in", tests.Repo2) 370 artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/)b)/)b).in", tests.Repo2) 371 artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/(b/(b.in", tests.Repo2+"/()/", "--flat=true") 372 artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/(b)/(b).in", tests.Repo2+"/()/") 373 artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/b(/b(.in", tests.Repo2+"/(/", "--flat=true") 374 artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/(/(*.in)", tests.Repo2+"/c/{1}.zip", "--flat=true") 375 artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/(/(*.in)", tests.Repo2+"/(/{1}.zip") 376 artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/b(/(b*.in)", tests.Repo2+"/(/{1}-up", "--flat=true") 377 artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/b(/(*).(*)", tests.Repo2+"/(/{2}-{1}", "--flat=true") 378 379 searchPath, err := tests.CreateSpec(tests.SearchRepo2) 380 assert.NoError(t, err) 381 verifyExistInArtifactory(tests.GetCopyFileNameWithParentheses(), searchPath, t) 382 383 cleanArtifactoryTest() 384 } 385 386 func TestArtifactoryUploadFilesNameWithParenthesis(t *testing.T) { 387 initArtifactoryTest(t) 388 389 specFile, err := tests.CreateSpec(tests.UploadFileWithParenthesesSpec) 390 assert.NoError(t, err) 391 artifactoryCli.Exec("upload", "--spec="+specFile) 392 393 searchPath, err := tests.CreateSpec(tests.SearchAllRepo1) 394 assert.NoError(t, err) 395 verifyExistInArtifactory(tests.GetUploadFileNameWithParentheses(), searchPath, t) 396 397 cleanArtifactoryTest() 398 } 399 400 func TestArtifactoryDownloadFilesNameWithParenthesis(t *testing.T) { 401 initArtifactoryTest(t) 402 403 artifactoryCli.Exec("upload", "testsdata/b/*", tests.Repo1, "--flat=false") 404 artifactoryCli.Exec("download", path.Join(tests.Repo1), tests.Out+"/") 405 406 paths, err := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 407 assert.NoError(t, err) 408 tests.VerifyExistLocally(tests.GetFileWithParenthesesDownload(), paths, t) 409 410 cleanArtifactoryTest() 411 } 412 413 func TestArtifactoryDirectoryCopyUsingWildcardFlat(t *testing.T) { 414 initArtifactoryTest(t) 415 var filePath = getSpecialCharFilePath() 416 417 artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/inner/") 418 artifactoryCli.Exec("cp", tests.Repo1+"/path/inner", tests.Repo2, "--flat=true") 419 searchPath, err := tests.CreateSpec(tests.SearchRepo2) 420 assert.NoError(t, err) 421 422 verifyExistInArtifactory(tests.GetSingleDirectoryCopyFlat(), searchPath, t) 423 cleanArtifactoryTest() 424 } 425 426 func TestArtifactoryCopyPathsTwice(t *testing.T) { 427 initArtifactoryTest(t) 428 var filePath = getSpecialCharFilePath() 429 artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/inner/") 430 431 log.Info("Copy Folder to root twice") 432 artifactoryCli.Exec("cp", tests.Repo1+"/path", tests.Repo2) 433 searchPath, err := tests.CreateSpec(tests.SearchRepo2) 434 assert.NoError(t, err) 435 436 verifyExistInArtifactory(tests.GetSingleFileCopyFullPath(), searchPath, t) 437 artifactoryCli.Exec("cp", tests.Repo1+"/path", tests.Repo2) 438 verifyExistInArtifactory(tests.GetSingleFileCopyFullPath(), searchPath, t) 439 artifactoryCli.Exec("del", tests.Repo2) 440 441 log.Info("Copy to from repo1/path to repo2/path twice") 442 artifactoryCli.Exec("cp", tests.Repo1+"/path", tests.Repo2+"/path") 443 verifyExistInArtifactory(tests.GetSingleFileCopyFullPath(), searchPath, t) 444 artifactoryCli.Exec("cp", tests.Repo1+"/path", tests.Repo2+"/path") 445 verifyExistInArtifactory(tests.GetFolderCopyTwice(), searchPath, t) 446 artifactoryCli.Exec("del", tests.Repo2) 447 448 log.Info("Copy to from repo1/path/ to repo2/path/ twice") 449 artifactoryCli.Exec("cp", tests.Repo1+"/path/", tests.Repo2+"/path/") 450 verifyExistInArtifactory(tests.GetSingleInnerFileCopyFullPath(), searchPath, t) 451 artifactoryCli.Exec("cp", tests.Repo1+"/path/", tests.Repo2+"/path/") 452 verifyExistInArtifactory(tests.GetSingleInnerFileCopyFullPath(), searchPath, t) 453 artifactoryCli.Exec("del", tests.Repo2) 454 455 log.Info("Copy to from repo1/path/ to repo2/path/ twice") 456 artifactoryCli.Exec("cp", tests.Repo1+"/path", tests.Repo2+"/path/") 457 verifyExistInArtifactory(tests.GetFolderCopyIntoFolder(), searchPath, t) 458 artifactoryCli.Exec("cp", tests.Repo1+"/path", tests.Repo2+"/path/") 459 verifyExistInArtifactory(tests.GetFolderCopyIntoFolder(), searchPath, t) 460 artifactoryCli.Exec("del", tests.Repo2) 461 462 cleanArtifactoryTest() 463 } 464 465 func TestArtifactoryDirectoryCopyPatternEndsWithSlash(t *testing.T) { 466 initArtifactoryTest(t) 467 var filePath = getSpecialCharFilePath() 468 469 artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/inner/") 470 artifactoryCli.Exec("cp", tests.Repo1+"/path/", tests.Repo2, "--flat=true") 471 searchPath, err := tests.CreateSpec(tests.SearchRepo2) 472 assert.NoError(t, err) 473 verifyExistInArtifactory(tests.GetAnyItemCopyUsingSpec(), searchPath, t) 474 cleanArtifactoryTest() 475 } 476 477 func TestArtifactoryCopyAnyItemUsingWildcardFlat(t *testing.T) { 478 initArtifactoryTest(t) 479 var filePath = getSpecialCharFilePath() 480 481 artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/inner/") 482 artifactoryCli.Exec("upload", filePath, tests.Repo1+"/someFile", "--flat=true") 483 artifactoryCli.Exec("cp", tests.Repo1+"/*", tests.Repo2) 484 searchPath, err := tests.CreateSpec(tests.SearchRepo2) 485 assert.NoError(t, err) 486 487 verifyExistInArtifactory(tests.GetAnyItemCopy(), searchPath, t) 488 cleanArtifactoryTest() 489 } 490 491 func TestArtifactoryCopyAnyItemRecursive(t *testing.T) { 492 initArtifactoryTest(t) 493 var filePath = getSpecialCharFilePath() 494 495 artifactoryCli.Exec("upload", filePath, tests.Repo1+"/a/b/") 496 artifactoryCli.Exec("upload", filePath, tests.Repo1+"/aFile", "--flat=true") 497 artifactoryCli.Exec("cp", tests.Repo1+"/a*", tests.Repo2, "--recursive=true") 498 searchPath, err := tests.CreateSpec(tests.SearchRepo2) 499 assert.NoError(t, err) 500 verifyExistInArtifactory(tests.GetAnyItemCopyRecursive(), searchPath, t) 501 cleanArtifactoryTest() 502 } 503 504 func TestArtifactoryCopyAndRenameFolder(t *testing.T) { 505 initArtifactoryTest(t) 506 var filePath = getSpecialCharFilePath() 507 508 artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/inner/") 509 artifactoryCli.Exec("cp", tests.Repo1+"/*", tests.Repo2+"/newPath") 510 searchPath, err := tests.CreateSpec(tests.SearchRepo2) 511 assert.NoError(t, err) 512 verifyExistInArtifactory(tests.GetCopyFolderRename(), searchPath, t) 513 cleanArtifactoryTest() 514 } 515 516 func TestArtifactoryCopyAnyItemUsingSpec(t *testing.T) { 517 initArtifactoryTest(t) 518 var filePath = getSpecialCharFilePath() 519 520 specFile, err := tests.CreateSpec(tests.CopyItemsSpec) 521 assert.NoError(t, err) 522 searchPath, err := tests.CreateSpec(tests.SearchRepo2) 523 assert.NoError(t, err) 524 artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/inner/") 525 artifactoryCli.Exec("upload", filePath, tests.Repo1+"/someFile", "--flat=true") 526 artifactoryCli.Exec("cp", "--spec="+specFile) 527 verifyExistInArtifactory(tests.GetAnyItemCopyUsingSpec(), searchPath, t) 528 cleanArtifactoryTest() 529 } 530 531 func getSpecialCharFilePath() string { 532 return "testsdata/a$+~&^a#/a*" 533 } 534 535 func TestArtifactoryCopyNoSpec(t *testing.T) { 536 testCopyMoveNoSpec("cp", tests.GetBuildBeforeCopyExpected(), tests.GetBuildCopyExpected(), t) 537 } 538 539 func TestArtifactoryCopyExcludeByCli(t *testing.T) { 540 initArtifactoryTest(t) 541 542 // Upload files 543 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 544 assert.NoError(t, err) 545 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 546 assert.NoError(t, err) 547 artifactoryCli.Exec("upload", "--spec="+specFileA) 548 artifactoryCli.Exec("upload", "--spec="+specFileB) 549 550 // Copy by pattern 551 artifactoryCli.Exec("cp", tests.Repo1+"/data/ "+tests.Repo2+"/", "--exclude-patterns=*b*;*c*") 552 553 // Validate files are moved by build number 554 cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec) 555 assert.NoError(t, err) 556 verifyExistInArtifactory(tests.GetBuildCopyExclude(), cpMvDlByBuildAssertSpec, t) 557 558 // Cleanup 559 cleanArtifactoryTest() 560 } 561 562 func TestArtifactoryCopyExcludeBySpec(t *testing.T) { 563 initArtifactoryTest(t) 564 565 // Upload files 566 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 567 assert.NoError(t, err) 568 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 569 assert.NoError(t, err) 570 artifactoryCli.Exec("upload", "--spec="+specFileA) 571 artifactoryCli.Exec("upload", "--spec="+specFileB) 572 573 // Copy by spec 574 specFile, err := tests.CreateSpec(tests.MoveCopySpecExclude) 575 assert.NoError(t, err) 576 artifactoryCli.Exec("cp", "--spec="+specFile) 577 cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec) 578 assert.NoError(t, err) 579 580 // Validate files are moved by build number 581 verifyExistInArtifactory(tests.GetBuildCopyExclude(), cpMvDlByBuildAssertSpec, t) 582 583 // Cleanup 584 cleanArtifactoryTest() 585 } 586 587 func TestArtifactoryUploadDebian(t *testing.T) { 588 initArtifactoryTest(t) 589 specFile, err := tests.CreateSpec(tests.DebianUploadSpec) 590 assert.NoError(t, err) 591 artifactoryCli.Exec("upload", "--spec="+specFile, "--deb=bionic/main/i386") 592 verifyExistInArtifactoryByProps(tests.GetUploadDebianExpected(), tests.DebianRepo+"/*", "deb.distribution=bionic;deb.component=main;deb.architecture=i386", t) 593 artifactoryCli.Exec("upload", "--spec="+specFile, "--deb=cosmic/main\\/18.10/amd64") 594 verifyExistInArtifactoryByProps(tests.GetUploadDebianExpected(), tests.DebianRepo+"/*", "deb.distribution=cosmic;deb.component=main/18.10;deb.architecture=amd64", t) 595 cleanArtifactoryTest() 596 } 597 598 func TestArtifactoryUploadAndExplode(t *testing.T) { 599 initArtifactoryTest(t) 600 artifactoryCli.Exec("upload", filepath.Join("testsdata", "archives", "a.zip"), tests.Repo1, "--explode=true") 601 searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix) 602 assert.NoError(t, err) 603 verifyExistInArtifactory(tests.GetExplodeUploadExpectedRepo1(), searchFilePath, t) 604 cleanArtifactoryTest() 605 } 606 607 func TestArtifactoryUploadAndSyncDelete(t *testing.T) { 608 initArtifactoryTest(t) 609 // Upload all testdata/a/ 610 artifactoryCli.Exec("upload", path.Join("testsdata", "a", "*"), tests.Repo1+"/syncDir/", "--flat=false") 611 searchFilePath, err := tests.CreateSpec(tests.SearchAllRepo1) 612 assert.NoError(t, err) 613 verifyExistInArtifactory(tests.GetUploadExpectedRepo1SyncDeleteStep1(), searchFilePath, t) 614 // Upload testdata/a/b/*1.in and sync syncDir/testdata/a/b/ 615 artifactoryCli.Exec("upload", path.Join("testsdata", "a", "b", "*1.in"), tests.Repo1+"/syncDir/", "--sync-deletes="+tests.Repo1+"/syncDir/testsdata/a/b/", "--flat=false") 616 searchFilePath, err = tests.CreateSpec(tests.SearchAllRepo1) 617 assert.NoError(t, err) 618 verifyExistInArtifactory(tests.GetUploadExpectedRepo1SyncDeleteStep2(), searchFilePath, t) 619 // Upload testdata/archives/* and sync syncDir/ 620 artifactoryCli.Exec("upload", path.Join("testsdata", "archives", "*"), tests.Repo1+"/syncDir/", "--sync-deletes="+tests.Repo1+"/syncDir/") 621 searchFilePath, err = tests.CreateSpec(tests.SearchAllRepo1) 622 assert.NoError(t, err) 623 verifyExistInArtifactory(tests.GetUploadExpectedRepo1SyncDeleteStep3(), searchFilePath, t) 624 625 cleanArtifactoryTest() 626 } 627 628 func TestArtifactoryDownloadAndExplode(t *testing.T) { 629 initArtifactoryTest(t) 630 err := fileutils.CreateDirIfNotExist(tests.Out) 631 assert.NoError(t, err) 632 randFile, err := io.CreateRandFile(filepath.Join(tests.Out, "randFile"), 100000) 633 assert.NoError(t, err) 634 635 err = archiver.TarGz.Make(filepath.Join(tests.Out, "concurrent.tar.gz"), []string{randFile.Name()}) 636 assert.NoError(t, err) 637 err = archiver.Tar.Make(filepath.Join(tests.Out, "bulk.tar"), []string{randFile.Name()}) 638 assert.NoError(t, err) 639 err = archiver.Zip.Make(filepath.Join(tests.Out, "zipFile.zip"), []string{randFile.Name()}) 640 assert.NoError(t, err) 641 artifactoryCli.Exec("upload", tests.Out+"/*", tests.Repo1, "--flat=true") 642 randFile.File.Close() 643 os.RemoveAll(tests.Out) 644 artifactoryCli.Exec("download", path.Join(tests.Repo1, "randFile"), tests.Out+"/", "--explode=true") 645 artifactoryCli.Exec("download", path.Join(tests.Repo1, "concurrent.tar.gz"), tests.Out+"/", "--explode=false", "--min-split=50") 646 artifactoryCli.Exec("download", path.Join(tests.Repo1, "bulk.tar"), tests.Out+"/", "--explode=true") 647 artifactoryCli.Exec("download", path.Join(tests.Repo1, "zipFile.zip"), tests.Out+"/", "--explode=true", "--min-split=50") 648 artifactoryCli.Exec("download", path.Join(tests.Repo1, "zipFile.zip"), tests.Out+"/", "--explode=true") 649 650 paths, err := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 651 assert.NoError(t, err) 652 tests.VerifyExistLocally(tests.GetExtractedDownload(), paths, t) 653 654 cleanArtifactoryTest() 655 } 656 657 func TestArtifactoryDownloadAndSyncDeletes(t *testing.T) { 658 initArtifactoryTest(t) 659 660 outDirPath := tests.Out + string(os.PathSeparator) 661 // Upload all testdata/a/ to repo1/syncDir/ 662 artifactoryCli.Exec("upload", path.Join("testsdata", "a", "*"), tests.Repo1+"/syncDir/", "--flat=false") 663 searchFilePath, err := tests.CreateSpec(tests.SearchAllRepo1) 664 assert.NoError(t, err) 665 verifyExistInArtifactory(tests.GetUploadExpectedRepo1SyncDeleteStep1(), searchFilePath, t) 666 667 // Download repo1/syncDir/ to out/ 668 artifactoryCli.Exec("download", tests.Repo1+"/syncDir/", tests.Out+"/") 669 paths, err := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 670 assert.NoError(t, err) 671 tests.VerifyExistLocally(tests.GetExpectedSyncDeletesDownloadStep2(), paths, t) 672 673 // Download repo1/syncDir/ to out/ with flat=true and sync out/ 674 artifactoryCli.Exec("download", tests.Repo1+"/syncDir/", outDirPath, "--flat=true", "--sync-deletes="+outDirPath) 675 paths, err = fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 676 assert.NoError(t, err) 677 checkSyncedDirContent(tests.GetExpectedSyncDeletesDownloadStep3(), paths, t) 678 679 // Download all files ended with 2.in from repo1/syncDir/ to out/ and sync out/ 680 artifactoryCli.Exec("download", tests.Repo1+"/syncDir/*2.in", outDirPath, "--flat=true", "--sync-deletes="+outDirPath) 681 paths, err = fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 682 assert.NoError(t, err) 683 checkSyncedDirContent(tests.GetExpectedSyncDeletesDownloadStep4(), paths, t) 684 685 // Download repo1/syncDir/ to out/, exclude the pattern "*c*.in" and sync out/ 686 artifactoryCli.Exec("download", tests.Repo1+"/syncDir/", outDirPath, "--sync-deletes="+outDirPath+"syncDir"+string(os.PathSeparator), "--exclude-patterns=syncDir/testsdata/*c*in") 687 paths, err = fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 688 assert.NoError(t, err) 689 checkSyncedDirContent(tests.GetSyncExpectedDeletesDownloadStep5(), paths, t) 690 691 // Delete all files from repo1/syncDir/ 692 artifactoryCli.Exec("delete", tests.Repo1+"/syncDir/") 693 searchFilePath, err = tests.CreateSpec(tests.SearchAllRepo1) 694 assert.NoError(t, err) 695 verifyDoesntExistInArtifactory(searchFilePath, t) 696 697 // Upload all testdata/archives/ to repo1/syncDir/ 698 artifactoryCli.Exec("upload", path.Join("testsdata", "archives", "*"), tests.Repo1+"/syncDir/", "--flat=false") 699 searchFilePath, err = tests.CreateSpec(tests.SearchAllRepo1) 700 assert.NoError(t, err) 701 verifyExistInArtifactory(tests.GetSyncExpectedDeletesDownloadStep6(), searchFilePath, t) 702 703 // Download repo1/syncDir/ to out/ and sync out/ 704 artifactoryCli.Exec("download", tests.Repo1+"/syncDir/", outDirPath, "--sync-deletes="+outDirPath+"syncDir"+string(os.PathSeparator)) 705 paths, err = fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 706 assert.NoError(t, err) 707 checkSyncedDirContent(tests.GetSyncExpectedDeletesDownloadStep7(), paths, t) 708 709 cleanArtifactoryTest() 710 } 711 712 // After syncDeletes we must make sure that the content of the synced directory contains the last operation result only. 713 // Therefore we verify that there are no other files in the synced directory, other than the list of the expected files. 714 func checkSyncedDirContent(expected, actual []string, t *testing.T) { 715 // Check if all expected files are actually exist 716 tests.VerifyExistLocally(expected, actual, t) 717 // Check if all the existing files were expected 718 err := isExclusivelyExistLocally(expected, actual) 719 assert.NoError(t, err) 720 } 721 722 // Check if only the files we were expect, exist locally, i.e return an error if there is a local file we didn't expect. 723 // Since the "actual" list contains paths of both directories and files, for each element in the "actual" list: 724 // Check if the path equals to an existing file (for a file) OR 725 // if the path is a prefix of some path of an existing file (for a dir). 726 func isExclusivelyExistLocally(expected, actual []string) error { 727 for _, v := range actual { 728 for i, r := range expected { 729 if strings.HasPrefix(r, v) || v == r { 730 break 731 } 732 if i == len(actual)-1 { 733 return errors.New("Should not have : " + v) 734 } 735 } 736 } 737 return nil 738 } 739 740 // Test self-signed certificates with Artifactory. For the test, we set up a reverse proxy server. 741 func TestArtifactorySelfSignedCert(t *testing.T) { 742 initArtifactoryTest(t) 743 tempDirPath, err := ioutil.TempDir("", "jfrog.cli.test.") 744 err = errorutils.CheckError(err) 745 assert.NoError(t, err) 746 defer os.RemoveAll(tempDirPath) 747 os.Setenv(cliutils.HomeDir, tempDirPath) 748 os.Setenv(tests.HttpsProxyEnvVar, "1024") 749 go cliproxy.StartLocalReverseHttpProxy(artifactoryDetails.Url, false) 750 751 // The two certificate files are created by the reverse proxy on startup in the current directory. 752 defer os.Remove(certificate.KEY_FILE) 753 defer os.Remove(certificate.CERT_FILE) 754 // Let's wait for the reverse proxy to start up. 755 err = checkIfServerIsUp(cliproxy.GetProxyHttpsPort(), "https", false) 756 assert.NoError(t, err) 757 758 fileSpec := spec.NewBuilder().Pattern(tests.Repo1 + "/*.zip").Recursive(true).BuildSpec() 759 assert.NoError(t, err) 760 parsedUrl, err := url.Parse(artifactoryDetails.Url) 761 artifactoryDetails.Url = "https://127.0.0.1:" + cliproxy.GetProxyHttpsPort() + parsedUrl.RequestURI() 762 763 // The server is using self-signed certificates 764 // Without loading the certificates (or skipping verification) we expect all actions to fail due to error: "x509: certificate signed by unknown authority" 765 searchCmd := generic.NewSearchCommand() 766 searchCmd.SetRtDetails(artifactoryDetails).SetSpec(fileSpec) 767 err = searchCmd.Search() 768 _, isUrlErr := err.(*url.Error) 769 assert.True(t, isUrlErr, "Expected a connection failure, since reverse proxy didn't load self-signed-certs. Connection however is successful", err) 770 771 // Set insecureTls to true and run again. We expect the command to succeed. 772 artifactoryDetails.InsecureTls = true 773 searchCmd = generic.NewSearchCommand() 774 searchCmd.SetRtDetails(artifactoryDetails).SetSpec(fileSpec) 775 err = searchCmd.Search() 776 assert.NoError(t, err) 777 778 // Set insecureTls back to false. 779 // Copy the server certificates to the CLI security dir and run again. We expect the command to succeed. 780 artifactoryDetails.InsecureTls = false 781 securityDirPath, err := cliutils.GetJfrogSecurityDir() 782 assert.NoError(t, err) 783 err = fileutils.CopyFile(securityDirPath, certificate.KEY_FILE) 784 assert.NoError(t, err) 785 err = fileutils.CopyFile(securityDirPath, certificate.CERT_FILE) 786 assert.NoError(t, err) 787 searchCmd = generic.NewSearchCommand() 788 searchCmd.SetRtDetails(artifactoryDetails).SetSpec(fileSpec) 789 err = searchCmd.Search() 790 assert.NoError(t, err) 791 792 artifactoryDetails.Url = artAuth.GetUrl() 793 cleanArtifactoryTest() 794 } 795 796 // Test client certificates with Artifactory. For the test, we set up a reverse proxy server. 797 func TestArtifactoryClientCert(t *testing.T) { 798 initArtifactoryTest(t) 799 tempDirPath, err := ioutil.TempDir("", "jfrog.cli.test.") 800 err = errorutils.CheckError(err) 801 assert.NoError(t, err) 802 defer os.RemoveAll(tempDirPath) 803 os.Setenv(cliutils.HomeDir, tempDirPath) 804 os.Setenv(tests.HttpsProxyEnvVar, "1025") 805 go cliproxy.StartLocalReverseHttpProxy(artifactoryDetails.Url, true) 806 807 // The two certificate files are created by the reverse proxy on startup in the current directory. 808 defer os.Remove(certificate.KEY_FILE) 809 defer os.Remove(certificate.CERT_FILE) 810 // Let's wait for the reverse proxy to start up. 811 err = checkIfServerIsUp(cliproxy.GetProxyHttpsPort(), "https", true) 812 assert.NoError(t, err) 813 814 fileSpec := spec.NewBuilder().Pattern(tests.Repo1 + "/*.zip").Recursive(true).BuildSpec() 815 assert.NoError(t, err) 816 parsedUrl, err := url.Parse(artifactoryDetails.Url) 817 artifactoryDetails.Url = "https://127.0.0.1:" + cliproxy.GetProxyHttpsPort() + parsedUrl.RequestURI() 818 artifactoryDetails.InsecureTls = true 819 820 // The server is requiring client certificates 821 // Without loading a valid client certificate, we expect all actions to fail due to error: "tls: bad certificate" 822 searchCmd := generic.NewSearchCommand() 823 searchCmd.SetRtDetails(artifactoryDetails).SetSpec(fileSpec) 824 err = searchCmd.Search() 825 _, isUrlErr := err.(*url.Error) 826 assert.True(t, isUrlErr, "Expected a connection failure, since client did not provide a client certificate. Connection however is successful") 827 828 // Inject client certificates, we expect the search to succeed 829 artifactoryDetails.ClientCertPath = certificate.CERT_FILE 830 artifactoryDetails.ClientCertKeyPath = certificate.KEY_FILE 831 832 searchCmd = generic.NewSearchCommand() 833 searchCmd.SetRtDetails(artifactoryDetails).SetSpec(fileSpec) 834 err = searchCmd.Search() 835 assert.NoError(t, err) 836 837 artifactoryDetails.Url = artAuth.GetUrl() 838 artifactoryDetails.InsecureTls = false 839 artifactoryDetails.ClientCertPath = "" 840 artifactoryDetails.ClientCertKeyPath = "" 841 cleanArtifactoryTest() 842 } 843 844 func getExternalIP() (string, error) { 845 ifaces, err := net.Interfaces() 846 if err != nil { 847 return "", err 848 } 849 for _, iface := range ifaces { 850 if iface.Flags&net.FlagUp == 0 { 851 continue // interface down 852 } 853 if iface.Flags&net.FlagLoopback != 0 { 854 continue // loopback interface 855 } 856 addrs, err := iface.Addrs() 857 if err != nil { 858 return "", err 859 } 860 for _, addr := range addrs { 861 var ip net.IP 862 switch v := addr.(type) { 863 case *net.IPNet: 864 ip = v.IP 865 case *net.IPAddr: 866 ip = v.IP 867 } 868 if ip == nil || ip.IsLoopback() { 869 continue 870 } 871 ip = ip.To4() 872 if ip == nil { 873 continue // not an ipv4 address 874 } 875 return ip.String(), nil 876 } 877 } 878 return "", errors.New("check connection to the network") 879 } 880 881 // Due the fact that go read the HTTP_PROXY and the HTTPS_PROXY 882 // argument only once we can't set the env var for specific test. 883 // We need to start a new process with the env var set to the value we want. 884 // We decide which var to set by the rtUrl scheme. 885 func TestArtifactoryProxy(t *testing.T) { 886 initArtifactoryTest(t) 887 rtUrl, err := url.Parse(artifactoryDetails.Url) 888 assert.NoError(t, err) 889 var proxyTestArgs []string 890 var httpProxyEnv string 891 testArgs := []string{"-test.artifactoryProxy=true", "-rt.url=" + *tests.RtUrl, "-rt.user=" + *tests.RtUser, "-rt.password=" + *tests.RtPassword, "-rt.apikey=" + *tests.RtApiKey, "-rt.sshKeyPath=" + *tests.RtSshKeyPath, "-rt.sshPassphrase=" + *tests.RtSshPassphrase} 892 if rtUrl.Scheme == "https" { 893 os.Setenv(tests.HttpsProxyEnvVar, "1026") 894 proxyTestArgs = append([]string{"test", "-run=TestArtifactoryHttpsProxyEnvironmentVariableDelegator"}, testArgs...) 895 httpProxyEnv = "HTTPS_PROXY=localhost:" + cliproxy.GetProxyHttpsPort() 896 } else { 897 proxyTestArgs = append([]string{"test", "-run=TestArtifactoryHttpProxyEnvironmentVariableDelegator"}, testArgs...) 898 httpProxyEnv = "HTTP_PROXY=localhost:" + cliproxy.GetProxyHttpPort() 899 } 900 runProxyTest(t, proxyTestArgs, httpProxyEnv) 901 cleanArtifactoryTest() 902 } 903 904 func runProxyTest(t *testing.T, proxyTestArgs []string, httpProxyEnv string) { 905 cmd := exec.Command("go", proxyTestArgs...) 906 cmd.Env = append(os.Environ(), httpProxyEnv) 907 908 tempDirPath, err := tests.GetTestsLogsDir() 909 assert.NoError(t, err) 910 f, err := os.Create(filepath.Join(tempDirPath, "artifactory_proxy_tests.log")) 911 assert.NoError(t, err) 912 913 cmd.Stdout, cmd.Stderr = f, f 914 assert.NoError(t, cmd.Run(), "Artifactory proxy tests failed, full report available at the following path:", f.Name()) 915 log.Info("Full Artifactory proxy testing report available at the following path:", f.Name()) 916 } 917 918 // Should be run only by @TestArtifactoryProxy test. 919 func TestArtifactoryHttpProxyEnvironmentVariableDelegator(t *testing.T) { 920 testArtifactoryProxy(t, false) 921 } 922 923 // Should be run only by @TestArtifactoryProxy test. 924 func TestArtifactoryHttpsProxyEnvironmentVariableDelegator(t *testing.T) { 925 testArtifactoryProxy(t, true) 926 } 927 928 func testArtifactoryProxy(t *testing.T, isHttps bool) { 929 // Value is set to 'true' via testArgs @TestArtifactoryProxy 930 if !*tests.TestArtifactoryProxy { 931 t.SkipNow() 932 } 933 authenticate() 934 proxyRtUrl := prepareArtifactoryUrlForProxyTest(t) 935 spec := spec.NewBuilder().Pattern(tests.Repo1 + "/*.zip").Recursive(true).BuildSpec() 936 artifactoryDetails.Url = proxyRtUrl 937 checkForErrDueToMissingProxy(spec, t) 938 var port string 939 if isHttps { 940 go cliproxy.StartHttpsProxy() 941 port = cliproxy.GetProxyHttpsPort() 942 } else { 943 go cliproxy.StartHttpProxy() 944 port = cliproxy.GetProxyHttpPort() 945 } 946 // Let's wait for the reverse proxy to start up. 947 err := checkIfServerIsUp(port, "http", false) 948 assert.NoError(t, err) 949 searchCmd := generic.NewSearchCommand() 950 searchCmd.SetRtDetails(artifactoryDetails).SetSpec(spec) 951 err = searchCmd.Search() 952 assert.NoError(t, err) 953 artifactoryDetails.Url = artAuth.GetUrl() 954 } 955 956 func prepareArtifactoryUrlForProxyTest(t *testing.T) string { 957 rtUrl, err := url.Parse(artifactoryDetails.Url) 958 assert.NoError(t, err) 959 rtHost, port, err := net.SplitHostPort(rtUrl.Host) 960 if rtHost == "localhost" || rtHost == "127.0.0.1" { 961 externalIp, err := getExternalIP() 962 assert.NoError(t, err) 963 rtUrl.Host = externalIp + ":" + port 964 } 965 return rtUrl.String() 966 } 967 968 func checkForErrDueToMissingProxy(spec *spec.SpecFiles, t *testing.T) { 969 searchCmd := generic.NewSearchCommand() 970 searchCmd.SetRtDetails(artifactoryDetails).SetSpec(spec) 971 err := searchCmd.Search() 972 _, isUrlErr := err.(*url.Error) 973 assert.True(t, isUrlErr, "Expected the request to fails, since the proxy is down.", err) 974 } 975 976 func checkIfServerIsUp(port, proxyScheme string, useClientCerts bool) error { 977 tr := &http.Transport{ 978 TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 979 } 980 981 if useClientCerts { 982 for attempt := 0; attempt < 10; attempt++ { 983 if _, err := os.Stat(certificate.CERT_FILE); os.IsNotExist(err) { 984 log.Info("Waiting for certificate to appear...") 985 time.Sleep(time.Second) 986 continue 987 } 988 989 if _, err := os.Stat(certificate.KEY_FILE); os.IsNotExist(err) { 990 log.Info("Waiting for key to appear...") 991 time.Sleep(time.Second) 992 continue 993 } 994 995 break 996 } 997 998 cert, err := tls.LoadX509KeyPair(certificate.CERT_FILE, certificate.KEY_FILE) 999 if err != nil { 1000 return fmt.Errorf("failed loading client certificate") 1001 } 1002 tr.TLSClientConfig.Certificates = []tls.Certificate{cert} 1003 } 1004 client := &http.Client{Transport: tr} 1005 1006 for attempt := 0; attempt < 10; attempt++ { 1007 log.Info("Checking if proxy server is up and running.", strconv.Itoa(attempt+1), "attempt.", "URL:", proxyScheme+"://localhost:"+port) 1008 resp, err := client.Get(proxyScheme + "://localhost:" + port) 1009 if err != nil { 1010 attempt++ 1011 time.Sleep(time.Second) 1012 continue 1013 } 1014 resp.Body.Close() 1015 if resp.StatusCode != http.StatusOK { 1016 continue 1017 } 1018 1019 return nil 1020 } 1021 return fmt.Errorf("failed while waiting for the proxy server to be accessible") 1022 } 1023 1024 func TestXrayScanBuild(t *testing.T) { 1025 initArtifactoryTest(t) 1026 xrayServerPort := xray.StartXrayMockServer() 1027 serverUrl := "--url=http://localhost:" + strconv.Itoa(xrayServerPort) 1028 artifactoryCommandExecutor := tests.NewJfrogCli(execMain, "jfrog rt", serverUrl+getArtifactoryTestCredentials()) 1029 artifactoryCommandExecutor.Exec("build-scan", xray.CleanScanBuildName, "3") 1030 1031 cleanArtifactoryTest() 1032 } 1033 1034 func TestArtifactorySetProperties(t *testing.T) { 1035 initArtifactoryTest(t) 1036 // Upload a file. 1037 artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/a.in") 1038 // Set the 'prop=red' property to the file. 1039 artifactoryCli.Exec("sp", tests.Repo1+"/a.*", "prop=red") 1040 // Now let's change the property value, by searching for the 'prop=red'. 1041 specFile, err := tests.CreateSpec(tests.SetDeletePropsSpec) 1042 assert.NoError(t, err) 1043 artifactoryCli.Exec("sp", "prop=green", "--spec="+specFile) 1044 1045 resultItems := searchItemsInArtifactory(t) 1046 assert.NotZero(t, len(resultItems), "No artifacts were found.") 1047 for _, item := range resultItems { 1048 properties := item.Properties 1049 assert.GreaterOrEqual(t, len(properties), 1, "Failed setting properties on item:", item.GetItemRelativePath()) 1050 for i, prop := range properties { 1051 assert.Zero(t, i, "Expected a single property.") 1052 assert.Equal(t, "prop", prop.Key, "Wrong property key") 1053 assert.Equal(t, "green", prop.Value, "Wrong property value") 1054 } 1055 } 1056 cleanArtifactoryTest() 1057 } 1058 1059 func TestArtifactorySetPropertiesExcludeByCli(t *testing.T) { 1060 initArtifactoryTest(t) 1061 artifactoryCli.Exec("upload", "testsdata/a/a*.in", tests.Repo1+"/") 1062 artifactoryCli.Exec("sp", tests.Repo1+"/*", "prop=val", "--exclude-patterns=*a1.in;*a2.in") 1063 resultItems := searchItemsInArtifactory(t) 1064 assert.NotZero(t, len(resultItems), "No artifacts were found.") 1065 for _, item := range resultItems { 1066 if item.Name != "a3.in" { 1067 continue 1068 } 1069 properties := item.Properties 1070 assert.GreaterOrEqual(t, len(properties), 1, "Failed setting properties on item:", item.GetItemRelativePath()) 1071 for i, prop := range properties { 1072 assert.Zero(t, i, "Expected single property.") 1073 assert.Equal(t, "prop", prop.Key, "Wrong property key") 1074 assert.Equal(t, "val", prop.Value, "Wrong property value") 1075 } 1076 } 1077 cleanArtifactoryTest() 1078 } 1079 1080 func TestArtifactorySetPropertiesExclusionsByCli(t *testing.T) { 1081 initArtifactoryTest(t) 1082 artifactoryCli.Exec("upload", "testsdata/a/a*.in", tests.Repo1+"/") 1083 artifactoryCli.Exec("sp", tests.Repo1+"/*", "prop=val", "--exclusions=*/*a1.in;*/*a2.in") 1084 resultItems := searchItemsInArtifactory(t) 1085 assert.NotZero(t, len(resultItems), "No artifacts were found.") 1086 for _, item := range resultItems { 1087 if item.Name != "a3.in" { 1088 continue 1089 } 1090 properties := item.Properties 1091 assert.GreaterOrEqual(t, len(properties), 1, "Failed setting properties on item:", item.GetItemRelativePath()) 1092 for i, prop := range properties { 1093 assert.Zero(t, i, "Expected single property.") 1094 assert.Equal(t, "prop", prop.Key, "Wrong property key") 1095 assert.Equal(t, "val", prop.Value, "Wrong property value") 1096 } 1097 } 1098 cleanArtifactoryTest() 1099 } 1100 1101 func TestArtifactoryDeleteProperties(t *testing.T) { 1102 initArtifactoryTest(t) 1103 artifactoryCli.Exec("upload", "testsdata/a/a*.in", tests.Repo1+"/a/") 1104 artifactoryCli.Exec("sp", tests.Repo1+"/a/*", "color=yellow;prop=red;status=ok") 1105 // Delete the 'color' property. 1106 artifactoryCli.Exec("delp", tests.Repo1+"/a/*", "color") 1107 // Delete the 'status' property, by a spec which filters files by 'prop=red'. 1108 specFile, err := tests.CreateSpec(tests.SetDeletePropsSpec) 1109 assert.NoError(t, err) 1110 artifactoryCli.Exec("delp", "status", "--spec="+specFile) 1111 1112 resultItems := searchItemsInArtifactory(t) 1113 assert.NotZero(t, len(resultItems), "No artifacts were found.") 1114 1115 for _, item := range resultItems { 1116 properties := item.Properties 1117 for _, prop := range properties { 1118 assert.False(t, prop.Key == "color" || prop.Key == "status", "Properties 'color' and/or 'status' were not deleted from artifact", item.Name) 1119 } 1120 } 1121 cleanArtifactoryTest() 1122 } 1123 1124 func TestArtifactoryDeletePropertiesWithExclude(t *testing.T) { 1125 initArtifactoryTest(t) 1126 artifactoryCli.Exec("upload", "testsdata/a/a*.in", tests.Repo1+"/") 1127 artifactoryCli.Exec("sp", tests.Repo1+"/*", "prop=val") 1128 1129 artifactoryCli.Exec("delp", tests.Repo1+"/*", "prop", "--exclude-patterns=*a1.in;*a2.in") 1130 resultItems := searchItemsInArtifactory(t) 1131 assert.NotZero(t, len(resultItems), "No artifacts were found.") 1132 1133 for _, item := range resultItems { 1134 properties := item.Properties 1135 for _, prop := range properties { 1136 if item.Name == "a1.in" || item.Name == "a2.in" { 1137 // Check that properties were not removed. 1138 assert.Equal(t, "prop", prop.Key, "Wrong property key") 1139 assert.Equal(t, "val", prop.Value, "Wrong property value") 1140 } 1141 } 1142 } 1143 cleanArtifactoryTest() 1144 } 1145 1146 func TestArtifactoryDeletePropertiesWithExclusions(t *testing.T) { 1147 initArtifactoryTest(t) 1148 artifactoryCli.Exec("upload", "testsdata/a/a*.in", tests.Repo1+"/") 1149 artifactoryCli.Exec("sp", tests.Repo1+"/*", "prop=val") 1150 1151 artifactoryCli.Exec("delp", tests.Repo1+"/*", "prop", "--exclusions=*/*a1.in;*/*a2.in") 1152 resultItems := searchItemsInArtifactory(t) 1153 assert.NotZero(t, len(resultItems), "No artifacts were found.") 1154 1155 for _, item := range resultItems { 1156 properties := item.Properties 1157 for _, prop := range properties { 1158 if item.Name == "a1.in" || item.Name == "a2.in" { 1159 // Check that properties were not removed. 1160 assert.False(t, prop.Key != "prop" || prop.Value != "val", "Wrong properties") 1161 } 1162 } 1163 } 1164 cleanArtifactoryTest() 1165 } 1166 1167 func TestArtifactoryUploadFromHomeDir(t *testing.T) { 1168 initArtifactoryTest(t) 1169 testFileRel, testFileAbs := createFileInHomeDir(t, "cliTestFile.txt") 1170 artifactoryCli.Exec("upload", testFileRel, tests.Repo1, "--recursive=false") 1171 searchTxtPath, err := tests.CreateSpec(tests.SearchTxt) 1172 assert.NoError(t, err) 1173 verifyExistInArtifactory(tests.GetTxtUploadExpectedRepo1(), searchTxtPath, t) 1174 os.Remove(testFileAbs) 1175 cleanArtifactoryTest() 1176 } 1177 1178 func createFileInHomeDir(t *testing.T, fileName string) (testFileRelPath string, testFileAbsPath string) { 1179 testFileRelPath = filepath.Join("~", fileName) 1180 testFileAbsPath = filepath.Join(fileutils.GetHomeDir(), fileName) 1181 d1 := []byte("test file") 1182 err := ioutil.WriteFile(testFileAbsPath, d1, 0644) 1183 assert.NoError(t, err, "Couldn't create file") 1184 return 1185 } 1186 1187 func TestArtifactoryUploadExcludeByCli1Wildcard(t *testing.T) { 1188 initArtifactoryTest(t) 1189 // Upload files 1190 artifactoryCli.Exec("upload", "testsdata/a/a*", tests.Repo1, "--exclusions=*a2*;*a3.in") 1191 searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix) 1192 assert.NoError(t, err) 1193 1194 verifyExistInArtifactory(tests.GetSimpleUploadSpecialCharNoRegexExpectedRepo1(), searchFilePath, t) 1195 cleanArtifactoryTest() 1196 } 1197 1198 func TestArtifactoryUploadExcludeByCli1Regex(t *testing.T) { 1199 initArtifactoryTest(t) 1200 // Upload files 1201 artifactoryCli.Exec("upload", "testsdata/a/a(.*)", tests.Repo1, "--exclusions=(.*)a2.*;.*a3.in", "--regexp=true") 1202 searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix) 1203 assert.NoError(t, err) 1204 verifyExistInArtifactory(tests.GetSimpleUploadSpecialCharNoRegexExpectedRepo1(), searchFilePath, t) 1205 cleanArtifactoryTest() 1206 } 1207 1208 func TestArtifactoryUploadExcludeByCli2Wildcard(t *testing.T) { 1209 initArtifactoryTest(t) 1210 1211 // Create temp dir 1212 absDirPath, err := ioutil.TempDir("", "cliTestDir") 1213 assert.NoError(t, err, "Couldn't create dir") 1214 defer os.Remove(absDirPath) 1215 1216 // Create temp files 1217 d1 := []byte("test file") 1218 err = ioutil.WriteFile(filepath.Join(absDirPath, "cliTestFile1.in"), d1, 0644) 1219 assert.NoError(t, err, "Couldn't create file") 1220 err = ioutil.WriteFile(filepath.Join(absDirPath, "cliTestFile2.in"), d1, 0644) 1221 assert.NoError(t, err, "Couldn't create file") 1222 1223 // Upload files 1224 artifactoryCli.Exec("upload", filepath.ToSlash(absDirPath)+"/*", tests.Repo1, "--exclusions=*cliTestFile1*") 1225 1226 // Check files exists in artifactory 1227 searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix) 1228 assert.NoError(t, err) 1229 1230 verifyExistInArtifactory([]string{tests.Repo1 + "/cliTestFile2.in"}, searchFilePath, t) 1231 1232 // Cleanup 1233 cleanArtifactoryTest() 1234 } 1235 1236 func TestArtifactoryUploadExcludeByCli2Regex(t *testing.T) { 1237 initArtifactoryTest(t) 1238 1239 // Create temp dir 1240 absDirPath, err := ioutil.TempDir("", "cliTestDir") 1241 assert.NoError(t, err, "Couldn't create dir") 1242 defer os.Remove(absDirPath) 1243 1244 // Create temp files 1245 d1 := []byte("test file") 1246 err = ioutil.WriteFile(filepath.Join(absDirPath, "cliTestFile1.in"), d1, 0644) 1247 assert.NoError(t, err, "Couldn't create file") 1248 err = ioutil.WriteFile(filepath.Join(absDirPath, "cliTestFile2.in"), d1, 0644) 1249 assert.NoError(t, err, "Couldn't create file") 1250 1251 // Upload files 1252 artifactoryCli.Exec("upload", filepath.ToSlash(absDirPath)+"(.*)", tests.Repo1, "--exclusions=(.*c)liTestFile1.*", "--regexp=true") 1253 1254 // Check files exists in artifactory 1255 searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix) 1256 assert.NoError(t, err) 1257 1258 verifyExistInArtifactory([]string{tests.Repo1 + "/cliTestFile2.in"}, searchFilePath, t) 1259 1260 // Cleanup 1261 cleanArtifactoryTest() 1262 } 1263 1264 func TestArtifactoryUploadExcludeBySpecWildcard(t *testing.T) { 1265 initArtifactoryTest(t) 1266 1267 // Upload files 1268 specFile, err := tests.CreateSpec(tests.UploadSpecExclude) 1269 assert.NoError(t, err) 1270 artifactoryCli.Exec("upload", "--spec="+specFile) 1271 1272 // Validate files are moved by build number 1273 searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix) 1274 assert.NoError(t, err) 1275 1276 verifyExistInArtifactory(tests.GetUploadSpecExcludeRepo1(), searchFilePath, t) 1277 1278 // Cleanup 1279 cleanArtifactoryTest() 1280 } 1281 1282 func TestArtifactoryUploadExcludeBySpecRegex(t *testing.T) { 1283 initArtifactoryTest(t) 1284 1285 // Upload files 1286 specFile, err := tests.CreateSpec(tests.UploadSpecExcludeRegex) 1287 assert.NoError(t, err) 1288 artifactoryCli.Exec("upload", "--spec="+specFile) 1289 1290 // Validate files are moved by build number 1291 searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix) 1292 assert.NoError(t, err) 1293 1294 verifyExistInArtifactory(tests.GetUploadSpecExcludeRepo1(), searchFilePath, t) 1295 1296 // Cleanup 1297 cleanArtifactoryTest() 1298 } 1299 1300 func TestArtifactoryUploadWithRegexEscaping(t *testing.T) { 1301 initArtifactoryTest(t) 1302 // Upload files 1303 artifactoryCli.Exec("upload", "testsdata/regexp"+"(.*)"+"\\."+".*", tests.Repo1, "--regexp=true") 1304 searchFilePath, err := tests.CreateSpec(tests.SearchAllRepo1) 1305 assert.NoError(t, err) 1306 1307 verifyExistInArtifactory([]string{tests.Repo1 + "/has.dot"}, searchFilePath, t) 1308 cleanArtifactoryTest() 1309 } 1310 1311 func TestArtifactoryCopySpec(t *testing.T) { 1312 testMoveCopySpec("copy", t) 1313 } 1314 1315 func TestArtifactoryMoveSpec(t *testing.T) { 1316 testMoveCopySpec("move", t) 1317 } 1318 1319 func testMoveCopySpec(command string, t *testing.T) { 1320 initArtifactoryTest(t) 1321 preUploadBasicTestResources() 1322 specFile, err := tests.CreateSpec(tests.CopyMoveSimpleSpec) 1323 assert.NoError(t, err) 1324 artifactoryCli.Exec(command, "--spec="+specFile) 1325 1326 // Verify files exist in target location successfully 1327 searchMovedCopiedSpec, err := tests.CreateSpec(tests.SearchTargetInRepo2) 1328 assert.NoError(t, err) 1329 verifyExistInArtifactory(tests.GetMoveCopySpecExpected(), searchMovedCopiedSpec, t) 1330 1331 searchOriginalSpec, err := tests.CreateSpec(tests.SearchRepo1TestResources) 1332 assert.NoError(t, err) 1333 1334 if command == "copy" { 1335 // Verify original files still exist 1336 verifyExistInArtifactory(tests.GetRepo1TestResourcesExpected(), searchOriginalSpec, t) 1337 } else { 1338 // Verify original files were moved 1339 verifyDoesntExistInArtifactory(searchOriginalSpec, t) 1340 } 1341 1342 cleanArtifactoryTest() 1343 } 1344 1345 // Upload symlink by full path to Artifactory and the link content checksum 1346 // Download the symlink which was uploaded. 1347 // validate the symlink content checksum 1348 func TestValidateValidSymlink(t *testing.T) { 1349 if cliutils.IsWindows() { 1350 t.Skip("Running on windows, skipping...") 1351 } 1352 initArtifactoryTest(t) 1353 // Path to local file 1354 localFile := filepath.Join(tests.GetTestResourcesPath()+"a", "a1.in") 1355 // Path to valid symLink 1356 validLink := filepath.Join(tests.GetTestResourcesPath()+"a", "link") 1357 1358 // Link valid symLink to local file 1359 err := os.Symlink(localFile, validLink) 1360 assert.NoError(t, err) 1361 1362 // Upload symlink to artifactory 1363 artifactoryCli.Exec("u", validLink+" "+tests.Repo1+" --symlinks=true") 1364 1365 // Delete the local symlink 1366 err = os.Remove(validLink) 1367 assert.NoError(t, err) 1368 1369 // Download symlink from artifactory 1370 artifactoryCli.Exec("dl", tests.Repo1+"/link "+tests.GetTestResourcesPath()+"a/ --validate-symlinks=true") 1371 1372 // Should be valid if successful 1373 validateSymLink(validLink, localFile, t) 1374 1375 // Delete symlink and clean 1376 os.Remove(validLink) 1377 cleanArtifactoryTest() 1378 } 1379 1380 // Upload symlink by full path to Artifactory and the link content checksum 1381 // Download the symlink which was uploaded. 1382 // validate the symlink content checksum. 1383 func TestValidateBrokenSymlink(t *testing.T) { 1384 if cliutils.IsWindows() { 1385 t.Skip("Running on windows, skipping...") 1386 } 1387 initArtifactoryTest(t) 1388 1389 // Path to broken symLink 1390 brokenLink := filepath.Join(tests.GetTestResourcesPath()+"a/", "brokenLink") 1391 1392 // Link broken symLink to non_existing_path 1393 err := os.Symlink("non-non_existing_path-path", brokenLink) 1394 assert.NoError(t, err) 1395 1396 // Upload symlink to artifactory 1397 artifactoryCli.Exec("u", brokenLink+" "+tests.Repo1+" --symlinks=true") 1398 1399 // Delete the local symlink 1400 err = os.Remove(brokenLink) 1401 assert.NoError(t, err) 1402 1403 // Try downloading symlink from artifactory. Since the link is broken, it shouldn't be downloaded 1404 artifactoryCli.Exec("dl", tests.Repo1+"/link "+tests.GetTestResourcesPath()+"a/ --validate-symlinks=true") 1405 if fileutils.IsPathExists(brokenLink, true) { 1406 os.Remove(brokenLink) 1407 assert.Fail(t, "A broken symLink was downloaded although validate-symlinks flag was set to true") 1408 } 1409 1410 // Clean 1411 cleanArtifactoryTest() 1412 } 1413 1414 // Testing exclude pattern with symlinks. 1415 // This test should not upload any files. 1416 func TestExcludeBrokenSymlink(t *testing.T) { 1417 if cliutils.IsWindows() { 1418 t.Skip("Running on windows, skipping...") 1419 } 1420 initArtifactoryTest(t) 1421 1422 // Creating broken symlink 1423 os.Mkdir(tests.Out, 0777) 1424 linkToNonExistingPath := filepath.Join(tests.Out, "link_to_non_existing_path") 1425 err := os.Symlink("non_existing_path", linkToNonExistingPath) 1426 assert.NoError(t, err) 1427 1428 // This command should succeed because all artifacts are excluded. 1429 artifactoryCli.Exec("u", filepath.Join(tests.Out, "*"), tests.Repo1, "--symlinks=true", "--exclusions=*") 1430 cleanArtifactoryTest() 1431 } 1432 1433 // Upload symlink to Artifactory using wildcard pattern and the link content checksum 1434 // Download the symlink which was uploaded. 1435 // validate the symlink content checksum. 1436 func TestSymlinkWildcardPathHandling(t *testing.T) { 1437 if cliutils.IsWindows() { 1438 t.Skip("Running on windows, skipping...") 1439 } 1440 initArtifactoryTest(t) 1441 localFile := filepath.Join(tests.GetTestResourcesPath()+"a/", "a1.in") 1442 link := filepath.Join(tests.GetTestResourcesPath()+"a/", "link") 1443 err := os.Symlink(localFile, link) 1444 assert.NoError(t, err) 1445 link1 := filepath.Join(tests.GetTestResourcesPath()+"a/", "link*") 1446 artifactoryCli.Exec("u", link1+" "+tests.Repo1+" --symlinks=true") 1447 err = os.Remove(link) 1448 assert.NoError(t, err) 1449 artifactoryCli.Exec("dl", tests.Repo1+"/link "+tests.GetTestResourcesPath()+"a/ --validate-symlinks=true") 1450 validateSymLink(link, localFile, t) 1451 os.Remove(link) 1452 cleanArtifactoryTest() 1453 } 1454 1455 // Upload symlink pointing to directory to Artifactory. 1456 // Download the symlink which was uploaded. 1457 func TestSymlinkToDirHandling(t *testing.T) { 1458 if cliutils.IsWindows() { 1459 t.Skip("Running on windows, skipping...") 1460 } 1461 initArtifactoryTest(t) 1462 localFile := filepath.Join(tests.GetTestResourcesPath(), "a") 1463 link := filepath.Join(tests.GetTestResourcesPath()+"a/", "link") 1464 err := os.Symlink(localFile, link) 1465 assert.NoError(t, err) 1466 artifactoryCli.Exec("u", link+" "+tests.Repo1+" --symlinks=true --recursive=true") 1467 err = os.Remove(link) 1468 assert.NoError(t, err) 1469 artifactoryCli.Exec("dl", tests.Repo1+"/link "+tests.GetTestResourcesPath()+"a/") 1470 validateSymLink(link, localFile, t) 1471 os.Remove(link) 1472 cleanArtifactoryTest() 1473 } 1474 1475 // Upload symlink pointing to directory using wildcard path to Artifactory. 1476 // Download the symlink which was uploaded. 1477 func TestSymlinkToDirWildcardHandling(t *testing.T) { 1478 if cliutils.IsWindows() { 1479 t.Skip("Running on windows, skipping...") 1480 } 1481 initArtifactoryTest(t) 1482 localFile := filepath.Join(tests.GetTestResourcesPath(), "a") 1483 link := filepath.Join(tests.GetTestResourcesPath()+"a/", "link") 1484 err := os.Symlink(localFile, link) 1485 assert.NoError(t, err) 1486 link1 := filepath.Join(tests.GetTestResourcesPath()+"a/", "lin*") 1487 artifactoryCli.Exec("u", link1+" "+tests.Repo1+" --symlinks=true --recursive=true") 1488 err = os.Remove(link) 1489 assert.NoError(t, err) 1490 artifactoryCli.Exec("dl", tests.Repo1+"/link "+tests.GetTestResourcesPath()+"a/") 1491 validateSymLink(link, localFile, t) 1492 os.Remove(link) 1493 cleanArtifactoryTest() 1494 } 1495 1496 // Upload symlink pointing to directory using wildcard path to Artifactory. 1497 // Download the symlink which was uploaded. 1498 // The test create circular links and the test suppose to prune the circular searching. 1499 func TestSymlinkInsideSymlinkDirWithRecursionIssueUpload(t *testing.T) { 1500 if cliutils.IsWindows() { 1501 t.Skip("Running on windows, skipping...") 1502 } 1503 initArtifactoryTest(t) 1504 localDirPath := filepath.Join(tests.GetTestResourcesPath(), "a") 1505 link1 := filepath.Join(tests.GetTestResourcesPath()+"a/", "link1") 1506 err := os.Symlink(localDirPath, link1) 1507 assert.NoError(t, err) 1508 localFilePath := filepath.Join(tests.GetTestResourcesPath()+"a/", "a1.in") 1509 link2 := filepath.Join(tests.GetTestResourcesPath()+"a/", "link2") 1510 err = os.Symlink(localFilePath, link2) 1511 assert.NoError(t, err) 1512 1513 artifactoryCli.Exec("u", localDirPath+"/link* "+tests.Repo1+" --symlinks=true --recursive=true") 1514 err = os.Remove(link1) 1515 assert.NoError(t, err) 1516 1517 err = os.Remove(link2) 1518 assert.NoError(t, err) 1519 1520 artifactoryCli.Exec("dl", tests.Repo1+"/link* "+tests.GetTestResourcesPath()+"a/") 1521 validateSymLink(link1, localDirPath, t) 1522 os.Remove(link1) 1523 validateSymLink(link2, localFilePath, t) 1524 os.Remove(link2) 1525 cleanArtifactoryTest() 1526 } 1527 1528 func validateSymLink(localLinkPath, localFilePath string, t *testing.T) { 1529 exists := fileutils.IsPathSymlink(localLinkPath) 1530 assert.True(t, exists, "failed to download symlinks from artifactory") 1531 symlinks, err := filepath.EvalSymlinks(localLinkPath) 1532 assert.NoError(t, err, "can't eval symlinks") 1533 assert.Equal(t, localFilePath, symlinks, "Symlinks wasn't created as expected") 1534 } 1535 1536 func TestArtifactoryDeleteNoSpec(t *testing.T) { 1537 initArtifactoryTest(t) 1538 testArtifactorySimpleDelete(t, "") 1539 } 1540 1541 func TestArtifactoryDeleteBySpec(t *testing.T) { 1542 initArtifactoryTest(t) 1543 deleteSpecPath, err := tests.CreateSpec(tests.DeleteSimpleSpec) 1544 assert.NoError(t, err) 1545 testArtifactorySimpleDelete(t, deleteSpecPath) 1546 } 1547 1548 func testArtifactorySimpleDelete(t *testing.T, deleteSpecPath string) { 1549 preUploadBasicTestResources() 1550 1551 // Verify exists before deleting 1552 searchSpec, err := tests.CreateSpec(tests.SearchRepo1TestResources) 1553 assert.NoError(t, err) 1554 verifyExistInArtifactory(tests.GetRepo1TestResourcesExpected(), searchSpec, t) 1555 1556 if deleteSpecPath != "" { 1557 artifactoryCli.Exec("delete", "--spec="+deleteSpecPath) 1558 } else { 1559 artifactoryCli.Exec("delete", tests.Repo1+"/test_resources/b/*") 1560 } 1561 1562 verifyExistInArtifactory(tests.GetSimpleDelete(), searchSpec, t) 1563 cleanArtifactoryTest() 1564 } 1565 1566 func TestArtifactoryDeleteFolderWithWildcard(t *testing.T) { 1567 initArtifactoryTest(t) 1568 preUploadBasicTestResources() 1569 1570 // Verify exists before deleting 1571 searchSpec, err := tests.CreateSpec(tests.SearchRepo1TestResources) 1572 assert.NoError(t, err) 1573 verifyExistInArtifactory(tests.GetRepo1TestResourcesExpected(), searchSpec, t) 1574 1575 artifactoryCli.Exec("delete", tests.Repo1+"/test_resources/*/c") 1576 1577 verifyExistInArtifactory(tests.GetDeleteFolderWithWildcard(), searchSpec, t) 1578 cleanArtifactoryTest() 1579 } 1580 1581 func TestArtifactoryDeleteFolderCompletelyNoSpec(t *testing.T) { 1582 testArtifactoryDeleteFoldersNoSpec(t, false) 1583 } 1584 1585 func TestArtifactoryDeleteFolderContentNoSpec(t *testing.T) { 1586 testArtifactoryDeleteFoldersNoSpec(t, true) 1587 } 1588 1589 func testArtifactoryDeleteFoldersNoSpec(t *testing.T, contentOnly bool) { 1590 initArtifactoryTest(t) 1591 preUploadBasicTestResources() 1592 1593 // Verify exists before deleting 1594 searchSpec, err := tests.CreateSpec(tests.SearchRepo1TestResources) 1595 assert.NoError(t, err) 1596 verifyExistInArtifactory(tests.GetRepo1TestResourcesExpected(), searchSpec, t) 1597 1598 // Delete folder 1599 deletePath := tests.Repo1 + "/test_resources" 1600 // End with separator if content only 1601 if contentOnly { 1602 deletePath += "/" 1603 } 1604 artifactoryCli.Exec("delete", deletePath) 1605 1606 client, err := httpclient.ClientBuilder().Build() 1607 assert.NoError(t, err) 1608 1609 // Verify folder exists only if content only 1610 var expectedStatusCode int 1611 if contentOnly { 1612 expectedStatusCode = http.StatusOK 1613 } else { 1614 expectedStatusCode = http.StatusNotFound 1615 } 1616 resp, body, _, err := client.SendGet(artifactoryDetails.Url+"api/storage/"+tests.Repo1+"/test_resources", true, artHttpDetails) 1617 assert.NoError(t, err) 1618 assert.Equal(t, expectedStatusCode, resp.StatusCode, "test_resources shouldn't be deleted: "+tests.Repo1+"/test_resources/ "+string(body)) 1619 1620 // Verify no content exists 1621 verifyDoesntExistInArtifactory(searchSpec, t) 1622 cleanArtifactoryTest() 1623 } 1624 1625 func TestArtifactoryDeleteFoldersBySpecAllRepo(t *testing.T) { 1626 testArtifactoryDeleteFoldersBySpec(t, tests.DeleteSpec) 1627 } 1628 1629 func TestArtifactoryDeleteFoldersBySpecWildcardInRepo(t *testing.T) { 1630 testArtifactoryDeleteFoldersBySpec(t, tests.DeleteSpecWildcardInRepo) 1631 } 1632 1633 func testArtifactoryDeleteFoldersBySpec(t *testing.T, specPath string) { 1634 initArtifactoryTest(t) 1635 preUploadBasicTestResources() 1636 1637 // Verify exists before deleting 1638 searchSpec, err := tests.CreateSpec(tests.SearchRepo1TestResources) 1639 assert.NoError(t, err) 1640 verifyExistInArtifactory(tests.GetRepo1TestResourcesExpected(), searchSpec, t) 1641 1642 deleteSpecPath, err := tests.CreateSpec(specPath) 1643 assert.NoError(t, err) 1644 artifactoryCli.Exec("delete", "--spec="+deleteSpecPath) 1645 1646 completeSearchSpec, err := tests.CreateSpec(tests.SearchAllRepo1) 1647 assert.NoError(t, err) 1648 verifyDoesntExistInArtifactory(completeSearchSpec, t) 1649 cleanArtifactoryTest() 1650 } 1651 1652 func TestArtifactoryDeleteExcludeByCli(t *testing.T) { 1653 initArtifactoryTest(t) 1654 1655 // Upload files 1656 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 1657 assert.NoError(t, err) 1658 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 1659 assert.NoError(t, err) 1660 1661 artifactoryCli.Exec("upload", "--spec="+specFileA) 1662 artifactoryCli.Exec("upload", "--spec="+specFileB) 1663 1664 // Delete by pattern 1665 artifactoryCli.Exec("del", tests.Repo1+"/data/", "--exclude-patterns=*b1.in;*b2.in;*b3.in;*c1.in") 1666 1667 // Validate files are deleted 1668 cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec) 1669 assert.NoError(t, err) 1670 1671 verifyExistInArtifactory(tests.GetBuildDeleteExpected(), cpMvDlByBuildAssertSpec, t) 1672 1673 // Cleanup 1674 cleanArtifactoryTest() 1675 } 1676 1677 func TestArtifactoryDeleteExclusionsByCli(t *testing.T) { 1678 initArtifactoryTest(t) 1679 1680 // Upload files 1681 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 1682 assert.NoError(t, err) 1683 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 1684 assert.NoError(t, err) 1685 1686 artifactoryCli.Exec("upload", "--spec="+specFileA) 1687 artifactoryCli.Exec("upload", "--spec="+specFileB) 1688 1689 // Delete by pattern 1690 artifactoryCli.Exec("del", tests.Repo1+"/data/", "--exclusions=*/*b1.in;*/*b2.in;*/*b3.in;*/*c1.in") 1691 1692 // Validate files are deleted 1693 cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec) 1694 assert.NoError(t, err) 1695 1696 verifyExistInArtifactory(tests.GetBuildDeleteExpected(), cpMvDlByBuildAssertSpec, t) 1697 1698 // Cleanup 1699 cleanArtifactoryTest() 1700 } 1701 1702 func TestArtifactoryDeleteExcludeBySpec(t *testing.T) { 1703 initArtifactoryTest(t) 1704 // Upload files 1705 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 1706 assert.NoError(t, err) 1707 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 1708 assert.NoError(t, err) 1709 artifactoryCli.Exec("upload", "--spec="+specFileA) 1710 artifactoryCli.Exec("upload", "--spec="+specFileB) 1711 1712 specFile, err := tests.CreateSpec(tests.DelSpecExclude) 1713 assert.NoError(t, err) 1714 1715 // Delete by pattern 1716 artifactoryCli.Exec("del", "--spec="+specFile) 1717 1718 // Validate files are deleted 1719 cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec) 1720 assert.NoError(t, err) 1721 1722 verifyExistInArtifactory(tests.GetBuildDeleteExpected(), cpMvDlByBuildAssertSpec, t) 1723 1724 // Cleanup 1725 cleanArtifactoryTest() 1726 } 1727 1728 func TestArtifactoryDeleteExclusionsBySpec(t *testing.T) { 1729 initArtifactoryTest(t) 1730 // Upload files 1731 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 1732 assert.NoError(t, err) 1733 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 1734 assert.NoError(t, err) 1735 artifactoryCli.Exec("upload", "--spec="+specFileA) 1736 artifactoryCli.Exec("upload", "--spec="+specFileB) 1737 1738 specFile, err := tests.CreateSpec(tests.DelSpecExclusions) 1739 assert.NoError(t, err) 1740 1741 // Delete by pattern 1742 artifactoryCli.Exec("del", "--spec="+specFile) 1743 1744 // Validate files are deleted 1745 cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec) 1746 assert.NoError(t, err) 1747 1748 verifyExistInArtifactory(tests.GetBuildDeleteExpected(), cpMvDlByBuildAssertSpec, t) 1749 1750 // Cleanup 1751 cleanArtifactoryTest() 1752 } 1753 1754 func TestArtifactoryDeleteByProps(t *testing.T) { 1755 initArtifactoryTest(t) 1756 1757 // Upload files 1758 specFile, err := tests.CreateSpec(tests.UploadWithPropsSpec) 1759 assert.NoError(t, err) 1760 artifactoryCli.Exec("upload", "--spec="+specFile) 1761 // Set properties to the directories as well (and their content) 1762 artifactoryCli.Exec("sp", tests.Repo1+"/a/b", "D=5", "--include-dirs") 1763 artifactoryCli.Exec("sp", tests.Repo1+"/a/b/c", "D=2", "--include-dirs") 1764 // Set the property D=5 to c1.in, which is a different value then its directory c/ 1765 artifactoryCli.Exec("sp", tests.Repo1+"/a/b/c/c1.in", "D=5") 1766 1767 // Prepare search command 1768 searchSpecBuilder := spec.NewBuilder().Pattern(tests.Repo1).Recursive(true) 1769 searchCmd := generic.NewSearchCommand() 1770 searchCmd.SetRtDetails(artifactoryDetails) 1771 searchCmd.SetSpec(searchSpecBuilder.BuildSpec()) 1772 1773 // Delete all artifacts with D=5 but without c=3 1774 artifactoryCli.Exec("delete", tests.Repo1+"/*", "--props=D=5", "--exclude-props=c=3") 1775 // Search all artifacts in repo1 1776 assert.NoError(t, searchCmd.Search()) 1777 assert.NoError(t, assertDateInSearchResult(searchCmd.SearchResult())) 1778 assert.ElementsMatch(t, searchCmd.SearchResultNoDate(), tests.GetSearchResultAfterDeleteByPropsStep1()) 1779 1780 // Delete all artifacts with c=3 but without a=1 1781 artifactoryCli.Exec("delete", tests.Repo1+"/*", "--props=c=3", "--exclude-props=a=1") 1782 // Search all artifacts in repo1 1783 assert.NoError(t, searchCmd.Search()) 1784 assert.NoError(t, assertDateInSearchResult(searchCmd.SearchResult())) 1785 assert.ElementsMatch(t, searchCmd.SearchResultNoDate(), tests.GetSearchResultAfterDeleteByPropsStep2()) 1786 1787 // Delete all artifacts with a=1 but without b=3&c=3 1788 artifactoryCli.Exec("delete", tests.Repo1+"/*", "--props=a=1", "--exclude-props=b=3;c=3") 1789 // Search all artifacts in repo1 1790 assert.NoError(t, searchCmd.Search()) 1791 assert.NoError(t, assertDateInSearchResult(searchCmd.SearchResult())) 1792 assert.ElementsMatch(t, searchCmd.SearchResultNoDate(), tests.GetSearchResultAfterDeleteByPropsStep3()) 1793 1794 // Cleanup 1795 cleanArtifactoryTest() 1796 } 1797 1798 func TestArtifactoryMultipleFileSpecsUpload(t *testing.T) { 1799 initArtifactoryTest(t) 1800 specFile, err := tests.CreateSpec(tests.UploadMultipleFileSpecs) 1801 assert.NoError(t, err) 1802 resultSpecFile, err := tests.CreateSpec(tests.SearchAllRepo1) 1803 assert.NoError(t, err) 1804 artifactoryCli.Exec("upload", "--spec="+specFile) 1805 1806 verifyExistInArtifactory(tests.GetMultipleFileSpecs(), resultSpecFile, t) 1807 verifyExistInArtifactoryByProps([]string{tests.Repo1 + "/multiple/properties/testsdata/a/b/b2.in"}, tests.Repo1+"/*/properties/*.in", "searchMe=true", t) 1808 cleanArtifactoryTest() 1809 } 1810 1811 func TestArtifactorySimplePlaceHolders(t *testing.T) { 1812 initArtifactoryTest(t) 1813 specFile, err := tests.CreateSpec(tests.UploadSimplePlaceholders) 1814 assert.NoError(t, err) 1815 1816 resultSpecFile, err := tests.CreateSpec(tests.SearchSimplePlaceholders) 1817 assert.NoError(t, err) 1818 1819 artifactoryCli.Exec("upload", "--spec="+specFile) 1820 1821 verifyExistInArtifactory(tests.GetSimplePlaceholders(), resultSpecFile, t) 1822 cleanArtifactoryTest() 1823 } 1824 1825 func TestArtifactoryFolderUploadRecursiveNonFlat(t *testing.T) { 1826 initArtifactoryTest(t) 1827 dirInnerPath := fileutils.GetFileSeparator() + "inner" + fileutils.GetFileSeparator() + "folder" 1828 canonicalPath := tests.Out + dirInnerPath 1829 1830 err := os.MkdirAll(canonicalPath, 0777) 1831 assert.NoError(t, err) 1832 artifactoryCli.Exec("upload", tests.Out+"/(*)", tests.Repo1+"/{1}/", "--include-dirs=true", "--recursive=true", "--flat=false") 1833 err = os.RemoveAll(tests.Out) 1834 assert.NoError(t, err) 1835 artifactoryCli.Exec("download", tests.Repo1, tests.Out+"/", "--include-dirs=true", "--recursive=true") 1836 expectedPath := []string{tests.Out, "inner", "folder", "out", "inner", "folder"} 1837 assert.True(t, fileutils.IsPathExists(strings.Join(expectedPath, fileutils.GetFileSeparator()), false), "Failed to download folders from Artifactory") 1838 // Cleanup 1839 cleanArtifactoryTest() 1840 } 1841 1842 func TestArtifactoryFlatFolderUpload(t *testing.T) { 1843 initArtifactoryTest(t) 1844 dirInnerPath := fileutils.GetFileSeparator() + "inner" + fileutils.GetFileSeparator() + "folder" 1845 canonicalPath := tests.Out + dirInnerPath 1846 err := os.MkdirAll(canonicalPath, 0777) 1847 assert.NoError(t, err) 1848 artifactoryCli.Exec("upload", tests.Out+"/(*)", tests.Repo1+"/{1}/", "--include-dirs=true", "--flat=true") 1849 err = os.RemoveAll(tests.Out) 1850 assert.NoError(t, err) 1851 // Non flat download 1852 artifactoryCli.Exec("download", tests.Repo1, tests.Out+"/", "--include-dirs=true", "--recursive=true") 1853 assert.True(t, fileutils.IsPathExists(canonicalPath+fileutils.GetFileSeparator()+"folder", false), "Failed to download folders from Artifactory") 1854 // Cleanup 1855 cleanArtifactoryTest() 1856 } 1857 1858 // Test the definition of bottom chain directories - Directories which do not include other directories that match the pattern 1859 func TestArtifactoryIncludeDirFlatNonEmptyFolderUpload(t *testing.T) { 1860 initArtifactoryTest(t) 1861 // 'c' folder is defined as bottom chain directory therefore should be uploaded when using flat=true even though 'c' is not empty 1862 artifactoryCli.Exec("upload", tests.GetTestResourcesPath()+"a/b/*", tests.Repo1, "--include-dirs=true", "--flat=true") 1863 artifactoryCli.Exec("download", tests.Repo1, tests.Out+"/", "--include-dirs=true", "--recursive=true") 1864 assert.True(t, fileutils.IsPathExists(tests.Out+"/c", false), "Failed to download folders from Artifactory") 1865 // Cleanup 1866 cleanArtifactoryTest() 1867 } 1868 1869 // Test the definition of bottom chain directories - Directories which do not include other directories that match the pattern 1870 func TestArtifactoryDownloadNotIncludeDirs(t *testing.T) { 1871 initArtifactoryTest(t) 1872 // 'c' folder is defined as bottom chain directory therefore should be uploaded when using flat=true even though 'c' is not empty 1873 artifactoryCli.Exec("upload", tests.GetTestResourcesPath()+"*/c", tests.Repo1, "--include-dirs=true", "--flat=true") 1874 artifactoryCli.Exec("download", tests.Repo1, tests.Out+"/", "--recursive=true") 1875 assert.False(t, fileutils.IsPathExists(tests.Out+"/c", false), "Failed to download folders from Artifactory") 1876 // Cleanup 1877 cleanArtifactoryTest() 1878 } 1879 1880 // Test the definition of bottom chain directories - Directories which do not include other directories that match the pattern 1881 func TestArtifactoryDownloadFlatTrue(t *testing.T) { 1882 initArtifactoryTest(t) 1883 canonicalPath := tests.GetTestResourcesPath() + path.Join("an", "empty", "folder") 1884 err := os.MkdirAll(canonicalPath, 0777) 1885 assert.NoError(t, err) 1886 1887 // 'c' folder is defined as bottom chain directory therefore should be uploaded when using flat=true even though 'c' is not empty 1888 artifactoryCli.Exec("upload", tests.GetTestResourcesPath()+"(a*)/*", tests.Repo1+"/{1}/", "--include-dirs=true", "--flat=true") 1889 // Download without include-dirs 1890 artifactoryCli.Exec("download", tests.Repo1, tests.Out+"/", "--recursive=true", "--flat=true") 1891 assert.False(t, fileutils.IsPathExists(tests.Out+"/c", false), "'c' folder shouldn't exist.") 1892 1893 artifactoryCli.Exec("download", tests.Repo1, tests.Out+"/", "--include-dirs=true", "--recursive=true", "--flat=true") 1894 // Inner folder with files in it 1895 assert.True(t, fileutils.IsPathExists(tests.Out+"/c", false), "'c' folder should exist.") 1896 // Empty inner folder 1897 assert.True(t, fileutils.IsPathExists(tests.Out+"/folder", false), "'folder' folder should exist.") 1898 // Folder on root with files 1899 assert.True(t, fileutils.IsPathExists(tests.Out+"/a$+~&^a#", false), "'a$+~&^a#' folder should exist.") 1900 // None bottom directory - shouldn't exist. 1901 assert.False(t, fileutils.IsPathExists(tests.Out+"/a", false), "'a' folder shouldn't exist.") 1902 // None bottom directory - shouldn't exist. 1903 assert.False(t, fileutils.IsPathExists(tests.Out+"/b", false), "'b' folder shouldn't exist.") 1904 // Cleanup 1905 cleanArtifactoryTest() 1906 } 1907 1908 func TestArtifactoryIncludeDirFlatNonEmptyFolderUploadMatchingPattern(t *testing.T) { 1909 initArtifactoryTest(t) 1910 // 'c' folder is defined as bottom chain directory therefore should be uploaded when using flat=true even though 'c' is not empty 1911 artifactoryCli.Exec("upload", tests.GetTestResourcesPath()+"*/c", tests.Repo1, "--include-dirs=true", "--flat=true") 1912 artifactoryCli.Exec("download", tests.Repo1, tests.Out+"/", "--include-dirs=true", "--recursive=true") 1913 assert.True(t, fileutils.IsPathExists(tests.Out+"/c", false), "Failed to download folders from Artifactory") 1914 // Cleanup 1915 cleanArtifactoryTest() 1916 } 1917 1918 // Test the definition of bottom chain directories - Directories which do not include other directories that match the pattern 1919 func TestArtifactoryUploadFlatFolderWithFileAndInnerEmptyMatchingPattern(t *testing.T) { 1920 initArtifactoryTest(t) 1921 newFolderPath := tests.GetTestResourcesPath() + "a/b/c/d" 1922 err := os.MkdirAll(newFolderPath, 0777) 1923 assert.NoError(t, err) 1924 // We created an empty child folder to 'c' therefore 'c' is not longer a bottom chain and new 'd' inner directory is indeed bottom chain directory. 1925 // 'd' should uploaded and 'c' shouldn't 1926 artifactoryCli.Exec("upload", tests.GetTestResourcesPath()+"a/b/*", tests.Repo1, "--include-dirs=true", "--flat=true") 1927 err = os.RemoveAll(newFolderPath) 1928 assert.NoError(t, err) 1929 artifactoryCli.Exec("download", tests.Repo1, tests.Out+"/", "--include-dirs=true", "--recursive=true") 1930 assert.False(t, fileutils.IsPathExists(tests.Out+"/c", false), "'c' folder shouldn't exist") 1931 assert.True(t, fileutils.IsPathExists(tests.Out+"/d", false), "bottom chain directory, 'd', is missing") 1932 // Cleanup 1933 cleanArtifactoryTest() 1934 } 1935 1936 // Test the definition of bottom chain directories - Directories which do not include other directories that match the pattern 1937 func TestArtifactoryUploadFlatFolderWithFileAndInnerEmptyMatchingPatternWithPlaceHolders(t *testing.T) { 1938 initArtifactoryTest(t) 1939 relativePath := "/b/c/d" 1940 fullPath := tests.GetTestResourcesPath() + "a/" + relativePath 1941 err := os.MkdirAll(fullPath, 0777) 1942 assert.NoError(t, err) 1943 // We created a empty child folder to 'c' therefore 'c' is not longer a bottom chain and new 'd' inner directory is indeed bottom chain directory. 1944 // 'd' should uploaded and 'c' shouldn't 1945 artifactoryCli.Exec("upload", tests.GetTestResourcesPath()+"a/(*)/*", tests.Repo1+"/{1}/", "--include-dirs=true", "--flat=true") 1946 err = os.RemoveAll(fullPath) 1947 assert.NoError(t, err) 1948 artifactoryCli.Exec("download", tests.Repo1, tests.Out+"/", "--include-dirs=true", "--recursive=true") 1949 assert.True(t, fileutils.IsPathExists(tests.Out+relativePath, false), "bottom chain directory, 'd', is missing") 1950 1951 // Cleanup 1952 cleanArtifactoryTest() 1953 } 1954 1955 func TestArtifactoryFlatFolderDownload1(t *testing.T) { 1956 initArtifactoryTest(t) 1957 dirInnerPath := fileutils.GetFileSeparator() + "inner" + fileutils.GetFileSeparator() + "folder" 1958 canonicalPath := tests.Out + dirInnerPath 1959 err := os.MkdirAll(canonicalPath, 0777) 1960 assert.NoError(t, err) 1961 // Flat true by default for upload, by using placeholder we indeed create folders hierarchy in Artifactory inner/folder/folder 1962 artifactoryCli.Exec("upload", tests.Out+"/(*)", tests.Repo1+"/{1}/", "--include-dirs=true") 1963 err = os.RemoveAll(tests.Out) 1964 assert.NoError(t, err) 1965 // Only the inner folder should be downland e.g 'folder' 1966 artifactoryCli.Exec("download", tests.Repo1, tests.Out+"/", "--include-dirs=true", "--flat=true") 1967 assert.False(t, !fileutils.IsPathExists(tests.Out+fileutils.GetFileSeparator()+"folder", false) && 1968 fileutils.IsPathExists(tests.Out+fileutils.GetFileSeparator()+"inner", false), 1969 "Failed to download folders from Artifactory") 1970 // Cleanup 1971 cleanArtifactoryTest() 1972 } 1973 1974 func TestArtifactoryFolderUploadRecursiveUsingSpec(t *testing.T) { 1975 initArtifactoryTest(t) 1976 dirInnerPath := "empty" + fileutils.GetFileSeparator() + "folder" 1977 canonicalPath := tests.GetTestResourcesPath() + dirInnerPath 1978 err := os.MkdirAll(canonicalPath, 0777) 1979 assert.NoError(t, err) 1980 specFile, err := tests.CreateSpec(tests.UploadEmptyDirs) 1981 assert.NoError(t, err) 1982 artifactoryCli.Exec("upload", "--spec="+specFile) 1983 1984 specFile, err = tests.CreateSpec(tests.DownloadEmptyDirs) 1985 assert.NoError(t, err) 1986 artifactoryCli.Exec("download", "--spec="+specFile) 1987 assert.True(t, fileutils.IsPathExists(tests.Out+"/folder", false), "Failed to download folders from Artifactory") 1988 // Cleanup 1989 cleanArtifactoryTest() 1990 } 1991 1992 func TestArtifactoryFolderUploadNonRecursive(t *testing.T) { 1993 initArtifactoryTest(t) 1994 canonicalPath := tests.Out + fileutils.GetFileSeparator() + "inner" + fileutils.GetFileSeparator() + "folder" 1995 err := os.MkdirAll(canonicalPath, 0777) 1996 assert.NoError(t, err) 1997 artifactoryCli.Exec("upload", tests.Out+"/", tests.Repo1, "--recursive=true", "--include-dirs=true") 1998 err = os.RemoveAll(tests.Out) 1999 assert.NoError(t, err) 2000 artifactoryCli.Exec("download", tests.Repo1, tests.Out+"/", "--include-dirs=true") 2001 assert.True(t, fileutils.IsPathExists(tests.Out+"/folder", false), "Failed to download folder from Artifactory") 2002 assert.False(t, fileutils.IsPathExists(canonicalPath, false), "Path should be flat ") 2003 // Cleanup 2004 cleanArtifactoryTest() 2005 } 2006 2007 func TestArtifactoryFolderDownloadNonRecursive(t *testing.T) { 2008 initArtifactoryTest(t) 2009 canonicalPath := tests.Out + fileutils.GetFileSeparator() + "inner" + fileutils.GetFileSeparator() + "folder" 2010 err := os.MkdirAll(canonicalPath, 0777) 2011 assert.NoError(t, err) 2012 artifactoryCli.Exec("upload", tests.Out+"/", tests.Repo1, "--recursive=true", "--include-dirs=true", "--flat=false") 2013 err = os.RemoveAll(tests.Out) 2014 assert.NoError(t, err) 2015 artifactoryCli.Exec("download", tests.Repo1+"/*", "--recursive=false", "--include-dirs=true") 2016 assert.True(t, fileutils.IsPathExists(tests.Out, false), "Failed to download folder from Artifactory") 2017 assert.False(t, fileutils.IsPathExists(canonicalPath, false), "Path should be flat. ") 2018 // Cleanup 2019 cleanArtifactoryTest() 2020 } 2021 2022 func TestArtifactoryChecksumDownload(t *testing.T) { 2023 initArtifactoryTest(t) 2024 2025 var filePath = "testsdata/a/a1.in" 2026 artifactoryCli.Exec("upload", filePath, tests.Repo1) 2027 testChecksumDownload(t, "/a1.in") 2028 // Cleanup 2029 cleanArtifactoryTest() 2030 } 2031 2032 func TestArtifactoryChecksumDownloadRenameFileName(t *testing.T) { 2033 initArtifactoryTest(t) 2034 2035 var filePath = "testsdata/a/a1.in" 2036 artifactoryCli.Exec("upload", filePath, tests.Repo1) 2037 testChecksumDownload(t, "/a1.out") 2038 // Cleanup 2039 cleanArtifactoryTest() 2040 } 2041 2042 func testChecksumDownload(t *testing.T, outFileName string) { 2043 artifactoryCli.Exec("download "+tests.Repo1+"/a1.in", tests.Out+outFileName) 2044 2045 exists, err := fileutils.IsFileExists(tests.Out+outFileName, false) 2046 assert.NoError(t, err) 2047 assert.True(t, exists, "Failed to download file from Artifactory") 2048 2049 firstFileInfo, _ := os.Stat(tests.Out + outFileName) 2050 firstDownloadTime := firstFileInfo.ModTime() 2051 2052 artifactoryCli.Exec("download "+tests.Repo1+"/a1.in", tests.Out+outFileName) 2053 secondFileInfo, _ := os.Stat(tests.Out + outFileName) 2054 secondDownloadTime := secondFileInfo.ModTime() 2055 2056 assert.Equal(t, firstDownloadTime, secondDownloadTime, "Checksum download failed, the file was downloaded twice") 2057 } 2058 2059 func TestArtifactoryDownloadByPatternAndBuildUsingSpec(t *testing.T) { 2060 initArtifactoryTest(t) 2061 buildName, buildNumberA, buildNumberB := "cli-test-build", "10", "11" 2062 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 2063 specFile, err := tests.CreateSpec(tests.BuildDownloadSpec) 2064 assert.NoError(t, err) 2065 // Upload files with buildName and buildNumber 2066 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 2067 assert.NoError(t, err) 2068 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 2069 assert.NoError(t, err) 2070 artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+buildName, "--build-number="+buildNumberA) 2071 artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+buildName, "--build-number="+buildNumberB) 2072 2073 // Publish buildInfo 2074 artifactoryCli.Exec("build-publish", buildName, buildNumberA) 2075 artifactoryCli.Exec("build-publish", buildName, buildNumberB) 2076 2077 // Download by build number 2078 artifactoryCli.Exec("download", "--spec="+specFile) 2079 2080 // Validate files are downloaded by build number 2081 paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 2082 err = tests.ValidateListsIdentical(tests.GetBuildDownload(), paths) 2083 assert.NoError(t, err) 2084 2085 // Cleanup 2086 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 2087 cleanArtifactoryTest() 2088 } 2089 2090 func TestArtifactoryGenericBuildnameAndNumberFromEnv(t *testing.T) { 2091 initArtifactoryTest(t) 2092 buildName, buildNumberA, buildNumberB := "cli-test-build", "10", "11" 2093 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 2094 specFile, err := tests.CreateSpec(tests.BuildDownloadSpec) 2095 assert.NoError(t, err) 2096 // Upload files with buildName and buildNumber 2097 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 2098 assert.NoError(t, err) 2099 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 2100 assert.NoError(t, err) 2101 os.Setenv(cliutils.BuildName, buildName) 2102 os.Setenv(cliutils.BuildNumber, buildNumberA) 2103 defer os.Unsetenv(cliutils.BuildName) 2104 defer os.Unsetenv(cliutils.BuildNumber) 2105 artifactoryCli.Exec("upload", "--spec="+specFileA) 2106 os.Setenv(cliutils.BuildNumber, "11") 2107 artifactoryCli.Exec("upload", "--spec="+specFileB) 2108 2109 // Publish buildInfo 2110 os.Setenv(cliutils.BuildNumber, buildNumberA) 2111 artifactoryCli.Exec("build-publish") 2112 os.Setenv(cliutils.BuildNumber, buildNumberB) 2113 artifactoryCli.Exec("build-publish") 2114 2115 // Download by build number 2116 artifactoryCli.Exec("download", "--spec="+specFile) 2117 2118 // Validate files are downloaded by build number 2119 paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 2120 err = tests.ValidateListsIdentical(tests.GetBuildDownload(), paths) 2121 assert.NoError(t, err) 2122 2123 // Cleanup 2124 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 2125 cleanArtifactoryTest() 2126 } 2127 2128 func TestArtifactoryDownloadByBuildNoPatternUsingSpec(t *testing.T) { 2129 initArtifactoryTest(t) 2130 buildName, buildNumberA, buildNumberB := "cli-test-build", "10", "11" 2131 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 2132 specFile, err := tests.CreateSpec(tests.BuildDownloadSpecNoPattern) 2133 assert.NoError(t, err) 2134 // Upload files with buildName and buildNumber 2135 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 2136 assert.NoError(t, err) 2137 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 2138 assert.NoError(t, err) 2139 artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+buildName, "--build-number="+buildNumberA) 2140 artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+buildName, "--build-number="+buildNumberB) 2141 2142 // Publish buildInfo 2143 artifactoryCli.Exec("build-publish", buildName, buildNumberA) 2144 artifactoryCli.Exec("build-publish", buildName, buildNumberB) 2145 2146 // Download by build number 2147 artifactoryCli.Exec("download", "--spec="+specFile) 2148 2149 // Validate files are downloaded by build number 2150 paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 2151 err = tests.ValidateListsIdentical(tests.GetBuildDownload(), paths) 2152 assert.NoError(t, err) 2153 2154 // Cleanup 2155 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 2156 cleanArtifactoryTest() 2157 } 2158 2159 // Upload a file to build A. 2160 // Verify that it doesn't exist in B. 2161 func TestArtifactoryDownloadArtifactDoesntExistInBuild(t *testing.T) { 2162 initArtifactoryTest(t) 2163 buildName, buildNumber := "cli-test-build1", "10" 2164 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 2165 specFile, err := tests.CreateSpec(tests.BuildDownloadSpecNoBuildNumber) 2166 assert.NoError(t, err) 2167 // Upload a file 2168 artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/data/a10.in", "--build-name="+buildName, "--build-number="+buildNumber) 2169 2170 // Publish buildInfo 2171 artifactoryCli.Exec("build-publish", buildName, buildNumber) 2172 2173 // Download from different build number 2174 artifactoryCli.Exec("download", "--spec="+specFile) 2175 2176 paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 2177 err = tests.ValidateListsIdentical(tests.GetBuildDownloadDoesntExist(), paths) 2178 assert.NoError(t, err) 2179 2180 // Cleanup 2181 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 2182 cleanArtifactoryTest() 2183 } 2184 2185 // Upload a file to 2 different builds. 2186 // Verify that we don't download files with same sha and different build name and build number. 2187 func TestArtifactoryDownloadByShaAndBuild(t *testing.T) { 2188 initArtifactoryTest(t) 2189 buildNameA, buildNameB, buildNumberA, buildNumberB, buildNumberC := "cli-test-build1", "cli-test-build2", "10", "11", "12" 2190 inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameA, artHttpDetails) 2191 inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameB, artHttpDetails) 2192 specFile, err := tests.CreateSpec(tests.BuildDownloadSpecNoBuildNumber) 2193 assert.NoError(t, err) 2194 2195 // Upload 3 similar files to 3 different builds 2196 artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/data/a10.in", "--build-name="+buildNameB, "--build-number="+buildNumberA) 2197 artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/data/a11.in", "--build-name="+buildNameA, "--build-number="+buildNumberB) 2198 artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/data/a12.in", "--build-name="+buildNameA, "--build-number="+buildNumberC) 2199 2200 // Publish buildInfo 2201 artifactoryCli.Exec("build-publish", buildNameB, buildNumberA) 2202 artifactoryCli.Exec("build-publish", buildNameA, buildNumberB) 2203 artifactoryCli.Exec("build-publish", buildNameA, buildNumberC) 2204 2205 // Download by build number 2206 artifactoryCli.Exec("download", "--spec="+specFile) 2207 2208 paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 2209 err = tests.ValidateListsIdentical(tests.GetBuildDownloadByShaAndBuild(), paths) 2210 assert.NoError(t, err) 2211 2212 // Cleanup 2213 inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameA, artHttpDetails) 2214 inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameB, artHttpDetails) 2215 cleanArtifactoryTest() 2216 } 2217 2218 // Upload a file to 2 different builds. 2219 // Verify that we don't download files with same sha and build name and different build number. 2220 func TestArtifactoryDownloadByShaAndBuildName(t *testing.T) { 2221 initArtifactoryTest(t) 2222 buildNameA, buildNameB, buildNumberA, buildNumberB, buildNumberC := "cli-test-build1", "cli-test-build2", "10", "11", "12" 2223 inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameA, artHttpDetails) 2224 inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameB, artHttpDetails) 2225 specFile, err := tests.CreateSpec(tests.BuildDownloadSpecNoBuildNumber) 2226 assert.NoError(t, err) 2227 2228 // Upload 3 similar files to 2 different builds 2229 artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/data/a10.in", "--build-name="+buildNameB, "--build-number="+buildNumberA) 2230 artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/data/a11.in", "--build-name="+buildNameB, "--build-number="+buildNumberB) 2231 artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/data/a12.in", "--build-name="+buildNameA, "--build-number="+buildNumberC) 2232 2233 // Publish buildInfo 2234 artifactoryCli.Exec("build-publish", buildNameA, buildNumberC) 2235 artifactoryCli.Exec("build-publish", buildNameB, buildNumberA) 2236 artifactoryCli.Exec("build-publish", buildNameB, buildNumberB) 2237 2238 // Download by build number 2239 artifactoryCli.Exec("download", "--spec="+specFile) 2240 2241 paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 2242 err = tests.ValidateListsIdentical(tests.GetBuildDownloadByShaAndBuildName(), paths) 2243 assert.NoError(t, err) 2244 2245 // Cleanup 2246 inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameA, artHttpDetails) 2247 inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameB, artHttpDetails) 2248 cleanArtifactoryTest() 2249 } 2250 2251 func TestArtifactoryDownloadByBuildUsingSimpleDownload(t *testing.T) { 2252 initArtifactoryTest(t) 2253 buildName, buildNumberA, buildNumberB := "cli-test-build", "10", "11" 2254 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 2255 2256 // Upload files with buildName and buildNumber 2257 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 2258 assert.NoError(t, err) 2259 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 2260 assert.NoError(t, err) 2261 artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+buildName, "--build-number="+buildNumberA) 2262 artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+buildName, "--build-number="+buildNumberB) 2263 2264 // Publish buildInfo 2265 artifactoryCli.Exec("build-publish", buildName, buildNumberA) 2266 artifactoryCli.Exec("build-publish", buildName, buildNumberB) 2267 2268 // Download by build number, a1 should not be downloaded, b1 should 2269 artifactoryCli.Exec("download "+tests.Repo1+"/data/a1.in "+tests.Out+fileutils.GetFileSeparator()+"download"+fileutils.GetFileSeparator()+"simple_by_build"+fileutils.GetFileSeparator(), "--build="+buildName) 2270 artifactoryCli.Exec("download "+tests.Repo1+"/data/b1.in "+tests.Out+fileutils.GetFileSeparator()+"download"+fileutils.GetFileSeparator()+"simple_by_build"+fileutils.GetFileSeparator(), "--build="+buildName) 2271 2272 // Validate files are downloaded by build number 2273 paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 2274 err = tests.ValidateListsIdentical(tests.GetBuildSimpleDownload(), paths) 2275 assert.NoError(t, err) 2276 2277 // Cleanup 2278 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 2279 cleanArtifactoryTest() 2280 } 2281 2282 func TestArtifactoryDownloadByBuildNoPatternUsingSimpleDownload(t *testing.T) { 2283 initArtifactoryTest(t) 2284 buildName, buildNumberA, buildNumberB := "cli-test-build", "10", "11" 2285 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 2286 2287 // Upload files with buildName and buildNumber 2288 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 2289 assert.NoError(t, err) 2290 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 2291 assert.NoError(t, err) 2292 2293 artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+buildName, "--build-number="+buildNumberA) 2294 artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+buildName, "--build-number="+buildNumberB) 2295 2296 // Publish buildInfo 2297 artifactoryCli.Exec("build-publish", buildName, buildNumberA) 2298 artifactoryCli.Exec("build-publish", buildName, buildNumberB) 2299 2300 // Download by build number, a1 should not be downloaded, b1 should 2301 artifactoryCli.Exec("download * "+tests.Out+fileutils.GetFileSeparator()+"download"+fileutils.GetFileSeparator()+"simple_by_build"+fileutils.GetFileSeparator(), "--build="+buildName+"/"+buildNumberA) 2302 2303 // Validate files are downloaded by build number 2304 paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 2305 err = tests.ValidateListsIdentical(tests.GetBuildSimpleDownloadNoPattern(), paths) 2306 assert.NoError(t, err) 2307 2308 // Cleanup 2309 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 2310 cleanArtifactoryTest() 2311 } 2312 2313 func TestArtifactoryDownloadByArchiveEntriesCli(t *testing.T) { 2314 initArtifactoryTest(t) 2315 uploadSpecFile, err := tests.CreateSpec(tests.ArchiveEntriesUpload) 2316 assert.NoError(t, err) 2317 2318 // Upload archives 2319 artifactoryCli.Exec("upload", "--spec="+uploadSpecFile) 2320 2321 // Create executor for running with retries 2322 retryExecutor := createRetryExecutorForArchiveEntries(tests.GetBuildArchiveEntriesDownloadCli(), 2323 []string{"dl", tests.Repo1, "out/", "--archive-entries=(*)c1.in", "--flat=true"}) 2324 2325 // Perform download by archive-entries only the archives containing c1.in, and validate results 2326 assert.NoError(t, retryExecutor.Execute()) 2327 2328 // Cleanup 2329 cleanArtifactoryTest() 2330 } 2331 2332 func TestArtifactoryDownloadByArchiveEntriesSpecificPathCli(t *testing.T) { 2333 initArtifactoryTest(t) 2334 uploadSpecFile, err := tests.CreateSpec(tests.ArchiveEntriesUpload) 2335 assert.NoError(t, err) 2336 2337 // Upload archives 2338 artifactoryCli.Exec("upload", "--spec="+uploadSpecFile) 2339 2340 // Create executor for running with retries 2341 retryExecutor := createRetryExecutorForArchiveEntries(tests.GetBuildArchiveEntriesSpecificPathDownload(), 2342 []string{"dl", tests.Repo1, "out/", "--archive-entries=b/c/c1.in", "--flat=true"}) 2343 2344 // Perform download by archive-entries only the archives containing c1.in, and validate results 2345 assert.NoError(t, retryExecutor.Execute()) 2346 2347 // Cleanup 2348 cleanArtifactoryTest() 2349 } 2350 2351 func TestArtifactoryDownloadByArchiveEntriesSpec(t *testing.T) { 2352 initArtifactoryTest(t) 2353 uploadSpecFile, err := tests.CreateSpec(tests.ArchiveEntriesUpload) 2354 assert.NoError(t, err) 2355 downloadSpecFile, err := tests.CreateSpec(tests.ArchiveEntriesDownload) 2356 assert.NoError(t, err) 2357 2358 // Upload archives 2359 artifactoryCli.Exec("upload", "--spec="+uploadSpecFile) 2360 2361 // Create executor for running with retries 2362 retryExecutor := createRetryExecutorForArchiveEntries(tests.GetBuildArchiveEntriesDownloadSpec(), 2363 []string{"dl", "--spec=" + downloadSpecFile}) 2364 2365 // Perform download by archive-entries only the archives containing d1.in, and validate results 2366 assert.NoError(t, retryExecutor.Execute()) 2367 2368 // Cleanup 2369 cleanArtifactoryTest() 2370 } 2371 2372 func createRetryExecutorForArchiveEntries(expected []string, args []string) *clientutils.RetryExecutor { 2373 return &clientutils.RetryExecutor{ 2374 MaxRetries: 120, 2375 RetriesInterval: 1, 2376 ErrorMessage: "Waiting for Artifactory to index archives...", 2377 ExecutionHandler: func() (bool, error) { 2378 err := validateDownloadByArchiveEntries(expected, args) 2379 if err != nil { 2380 return true, err 2381 } 2382 2383 return false, nil 2384 }, 2385 } 2386 } 2387 2388 func validateDownloadByArchiveEntries(expected []string, args []string) error { 2389 // Execute the requested cli command 2390 artifactoryCli.Exec(args...) 2391 2392 // Validate files are downloaded as expected 2393 paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 2394 return tests.ValidateListsIdentical(expected, paths) 2395 } 2396 2397 func TestArtifactoryDownloadExcludeByCli(t *testing.T) { 2398 initArtifactoryTest(t) 2399 2400 // Upload files 2401 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 2402 assert.NoError(t, err) 2403 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 2404 assert.NoError(t, err) 2405 artifactoryCli.Exec("upload", "--spec="+specFileA, "--recursive=true") 2406 artifactoryCli.Exec("upload", "--spec="+specFileB, "--recursive=true") 2407 2408 // Download by pattern 2409 artifactoryCli.Exec("download", tests.Repo1+" out/download/aql_by_artifacts/", "--exclude-patterns=*/a1.in;*a2.*;data/c2.in") 2410 2411 // Validate files are excluded 2412 paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 2413 err = tests.ValidateListsIdentical(tests.GetBuildExcludeDownload(), paths) 2414 assert.NoError(t, err) 2415 2416 // Cleanup 2417 cleanArtifactoryTest() 2418 } 2419 2420 func TestArtifactoryDownloadExclusionsByCli(t *testing.T) { 2421 initArtifactoryTest(t) 2422 2423 // Upload files 2424 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 2425 assert.NoError(t, err) 2426 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 2427 assert.NoError(t, err) 2428 artifactoryCli.Exec("upload", "--spec="+specFileA, "--recursive=true") 2429 artifactoryCli.Exec("upload", "--spec="+specFileB, "--recursive=true") 2430 2431 // Download by pattern 2432 artifactoryCli.Exec("download", tests.Repo1+" out/download/aql_by_artifacts/", "--exclusions=*/*/a1.in;*/*a2.*;*/data/c2.in") 2433 2434 // Validate files are excluded 2435 paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 2436 err = tests.ValidateListsIdentical(tests.GetBuildExcludeDownload(), paths) 2437 assert.NoError(t, err) 2438 2439 // Cleanup 2440 cleanArtifactoryTest() 2441 } 2442 2443 func TestArtifactoryDownloadExcludeBySpec(t *testing.T) { 2444 initArtifactoryTest(t) 2445 specFile, err := tests.CreateSpec(tests.DownloadSpecExclude) 2446 assert.NoError(t, err) 2447 2448 // Upload files 2449 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 2450 assert.NoError(t, err) 2451 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 2452 assert.NoError(t, err) 2453 artifactoryCli.Exec("upload", "--spec="+specFileA, "--recursive=true", "--flat=false") 2454 artifactoryCli.Exec("upload", "--spec="+specFileB, "--recursive=true", "--flat=false") 2455 2456 // Download by spec 2457 artifactoryCli.Exec("download", "--spec="+specFile) 2458 2459 // Validate files are excluded 2460 paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 2461 err = tests.ValidateListsIdentical(tests.GetBuildExcludeDownloadBySpec(), paths) 2462 assert.NoError(t, err) 2463 2464 // Cleanup 2465 cleanArtifactoryTest() 2466 } 2467 2468 func TestArtifactoryDownloadExclusionsBySpec(t *testing.T) { 2469 initArtifactoryTest(t) 2470 specFile, err := tests.CreateSpec(tests.DownloadSpecExclusions) 2471 assert.NoError(t, err) 2472 2473 // Upload files 2474 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 2475 assert.NoError(t, err) 2476 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 2477 assert.NoError(t, err) 2478 artifactoryCli.Exec("upload", "--spec="+specFileA, "--recursive=true", "--flat=false") 2479 artifactoryCli.Exec("upload", "--spec="+specFileB, "--recursive=true", "--flat=false") 2480 2481 // Download by spec 2482 artifactoryCli.Exec("download", "--spec="+specFile) 2483 2484 // Validate files are excluded 2485 paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 2486 err = tests.ValidateListsIdentical(tests.GetBuildExcludeDownloadBySpec(), paths) 2487 assert.NoError(t, err) 2488 2489 // Cleanup 2490 cleanArtifactoryTest() 2491 } 2492 2493 func TestArtifactoryDownloadExcludeBySpecOverride(t *testing.T) { 2494 initArtifactoryTest(t) 2495 2496 // Upload files with buildName and buildNumber 2497 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 2498 assert.NoError(t, err) 2499 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 2500 assert.NoError(t, err) 2501 artifactoryCli.Exec("upload", "--spec="+specFileA, "--recursive=true", "--flat=false") 2502 artifactoryCli.Exec("upload", "--spec="+specFileB, "--recursive=true", "--flat=false") 2503 2504 // Download by spec 2505 specFile, err := tests.CreateSpec(tests.DownloadSpecExclude) 2506 assert.NoError(t, err) 2507 artifactoryCli.Exec("download", "--spec="+specFile, "--exclude-patterns=*a1.in;*a2.in;*c2.in") 2508 2509 // Validate files are downloaded by build number 2510 paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 2511 err = tests.ValidateListsIdentical(tests.GetBuildExcludeDownload(), paths) 2512 assert.NoError(t, err) 2513 2514 // Cleanup 2515 cleanArtifactoryTest() 2516 } 2517 2518 func TestArtifactoryDownloadExclusionsBySpecOverride(t *testing.T) { 2519 initArtifactoryTest(t) 2520 2521 // Upload files with buildName and buildNumber 2522 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 2523 assert.NoError(t, err) 2524 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 2525 assert.NoError(t, err) 2526 artifactoryCli.Exec("upload", "--spec="+specFileA, "--recursive=true", "--flat=false") 2527 artifactoryCli.Exec("upload", "--spec="+specFileB, "--recursive=true", "--flat=false") 2528 2529 // Download by spec 2530 specFile, err := tests.CreateSpec(tests.DownloadSpecExclusions) 2531 assert.NoError(t, err) 2532 artifactoryCli.Exec("download", "--spec="+specFile, "--exclusions=*a1.in;*a2.in;*c2.in") 2533 2534 // Validate files are downloaded by build number 2535 paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 2536 err = tests.ValidateListsIdentical(tests.GetBuildExcludeDownload(), paths) 2537 assert.NoError(t, err) 2538 2539 // Cleanup 2540 cleanArtifactoryTest() 2541 } 2542 2543 // Sort and limit changes the way properties are used so this should be tested with symlinks and search by build 2544 2545 // Upload symlink by full path to Artifactory and the link content checksum 2546 // Download the symlink which was uploaded with limit param. 2547 // validate the symlink content checksum. 2548 func TestArtifactoryLimitWithSymlink(t *testing.T) { 2549 if cliutils.IsWindows() { 2550 t.Skip("Running on windows, skipping...") 2551 } 2552 initArtifactoryTest(t) 2553 localFile := filepath.Join(tests.GetTestResourcesPath()+"a", "a1.in") 2554 link := filepath.Join(tests.GetTestResourcesPath()+"a", "link") 2555 err := os.Symlink(localFile, link) 2556 assert.NoError(t, err) 2557 artifactoryCli.Exec("u", link+" "+tests.Repo1+" --symlinks=true") 2558 err = os.Remove(link) 2559 assert.NoError(t, err) 2560 artifactoryCli.Exec("dl", tests.Repo1+"/link "+tests.GetTestResourcesPath()+"a/ --validate-symlinks=true --limit=1") 2561 validateSortLimitWithSymLink(link, localFile, t) 2562 os.Remove(link) 2563 cleanArtifactoryTest() 2564 } 2565 2566 // Upload symlink by full path to Artifactory and the link content checksum 2567 // Download the symlink which was uploaded with limit param. 2568 // validate the symlink content checksum. 2569 func TestArtifactorySortWithSymlink(t *testing.T) { 2570 if cliutils.IsWindows() { 2571 t.Skip("Running on windows, skipping...") 2572 } 2573 initArtifactoryTest(t) 2574 localFile := filepath.Join(tests.GetTestResourcesPath()+"a", "a1.in") 2575 link := filepath.Join(tests.GetTestResourcesPath()+"a", "link") 2576 err := os.Symlink(localFile, link) 2577 assert.NoError(t, err) 2578 artifactoryCli.Exec("u", link+" "+tests.Repo1+" --symlinks=true") 2579 err = os.Remove(link) 2580 assert.NoError(t, err) 2581 artifactoryCli.Exec("dl", tests.Repo1+"/link "+tests.GetTestResourcesPath()+"a/ --validate-symlinks=true --sort-by=created") 2582 validateSortLimitWithSymLink(link, localFile, t) 2583 os.Remove(link) 2584 cleanArtifactoryTest() 2585 } 2586 2587 func validateSortLimitWithSymLink(localLinkPath, localFilePath string, t *testing.T) { 2588 exists := fileutils.IsPathSymlink(localLinkPath) 2589 assert.True(t, exists, "failed to download symlinks from artifactory with Sort/Limit flag") 2590 symlinks, err := filepath.EvalSymlinks(localLinkPath) 2591 assert.NoError(t, err, "can't eval symlinks with Sort/Limit flag") 2592 assert.Equal(t, localFilePath, symlinks, "Symlinks wasn't created as expected with Sort/Limit flag") 2593 } 2594 2595 // Upload a file to 2 different builds. 2596 // Verify that we don't download files with same sha and build name and different build number when sort is configured. 2597 func TestArtifactoryDownloadByShaAndBuildNameWithSort(t *testing.T) { 2598 initArtifactoryTest(t) 2599 buildNameA, buildNameB, buildNumberA, buildNumberB, buildNumberC := "cli-test-build1", "cli-test-build2", "10", "11", "12" 2600 inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameA, artHttpDetails) 2601 inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameB, artHttpDetails) 2602 specFile, err := tests.CreateSpec(tests.BuildDownloadSpecNoBuildNumberWithSort) 2603 assert.NoError(t, err) 2604 // Upload 3 similar files to 2 different builds 2605 artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/data/a10.in", "--build-name="+buildNameB, "--build-number="+buildNumberA) 2606 artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/data/a11.in", "--build-name="+buildNameB, "--build-number="+buildNumberB) 2607 artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/data/a12.in", "--build-name="+buildNameA, "--build-number="+buildNumberC) 2608 2609 // Publish buildInfo 2610 artifactoryCli.Exec("build-publish", buildNameA, buildNumberC) 2611 artifactoryCli.Exec("build-publish", buildNameB, buildNumberA) 2612 artifactoryCli.Exec("build-publish", buildNameB, buildNumberB) 2613 2614 // Download by build number 2615 artifactoryCli.Exec("download", "--sort-by=created --spec="+specFile) 2616 2617 paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(filepath.Join(tests.Out, "download", "sort_limit_by_build"), false) 2618 err = tests.ValidateListsIdentical(tests.GetBuildDownloadByShaAndBuildNameWithSort(), paths) 2619 assert.NoError(t, err) 2620 2621 // Cleanup 2622 inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameA, artHttpDetails) 2623 inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameB, artHttpDetails) 2624 cleanArtifactoryTest() 2625 } 2626 2627 func TestArtifactoryCopyByBuildUsingSpec(t *testing.T) { 2628 initArtifactoryTest(t) 2629 buildName, buildNumberA, buildNumberB := "cli-test-build", "10", "11" 2630 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 2631 specFile, err := tests.CreateSpec(tests.CopyByBuildSpec) 2632 assert.NoError(t, err) 2633 // Upload files with buildName and buildNumber: a* uploaded with build number "10", b* uploaded with build number "11" 2634 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 2635 assert.NoError(t, err) 2636 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 2637 assert.NoError(t, err) 2638 artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+buildName, "--build-number="+buildNumberA) 2639 artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+buildName, "--build-number="+buildNumberB) 2640 2641 // Publish buildInfo 2642 artifactoryCli.Exec("build-publish", buildName, buildNumberA) 2643 artifactoryCli.Exec("build-publish", buildName, buildNumberB) 2644 2645 // Copy by build name "cli-test-build" and build number "10" from spec, a* should be copied 2646 artifactoryCli.Exec("copy", "--spec="+specFile) 2647 2648 // Validate files are Copied by build number 2649 cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec) 2650 assert.NoError(t, err) 2651 verifyExistInArtifactory(tests.GetBuildCopyExpected(), cpMvDlByBuildAssertSpec, t) 2652 2653 // Cleanup 2654 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 2655 cleanArtifactoryTest() 2656 } 2657 2658 func TestArtifactoryCopyByBuildPatternAllUsingSpec(t *testing.T) { 2659 initArtifactoryTest(t) 2660 buildName, buildNumberA, buildNumberB := "cli-test-build", "10", "11" 2661 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 2662 specFile, err := tests.CreateSpec(tests.CopyByBuildPatternAllSpec) 2663 assert.NoError(t, err) 2664 // Upload files with buildName and buildNumber: a* uploaded with build number "10", b* uploaded with build number "11" 2665 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 2666 assert.NoError(t, err) 2667 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 2668 assert.NoError(t, err) 2669 artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+buildName, "--build-number="+buildNumberA) 2670 artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+buildName, "--build-number="+buildNumberB) 2671 2672 // Publish buildInfo 2673 artifactoryCli.Exec("build-publish", buildName, buildNumberA) 2674 artifactoryCli.Exec("build-publish", buildName, buildNumberB) 2675 2676 // Copy by build name "cli-test-build" and build number "10" from spec, a* should be copied 2677 artifactoryCli.Exec("copy", "--spec="+specFile) 2678 2679 // Validate files are Copied by build number 2680 cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec) 2681 assert.NoError(t, err) 2682 verifyExistInArtifactory(tests.GetBuildCopyExpected(), cpMvDlByBuildAssertSpec, t) 2683 2684 // Cleanup 2685 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 2686 cleanArtifactoryTest() 2687 } 2688 2689 func TestArtifactorySortAndLimit(t *testing.T) { 2690 initArtifactoryTest(t) 2691 2692 // Upload all testdata/a/ files 2693 artifactoryCli.Exec("upload", "testsdata/a/(*)", tests.Repo1+"/data/{1}") 2694 2695 // Download 1 sorted by name asc 2696 artifactoryCli.Exec("download", tests.Repo1+"/data/ out/download/sort_limit/", "--sort-by=name", "--limit=1") 2697 2698 // Download 3 sorted by depth desc 2699 artifactoryCli.Exec("download", tests.Repo1+"/data/ out/download/sort_limit/", "--sort-by=depth", "--limit=3", "--sort-order=desc") 2700 2701 paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 2702 err := tests.ValidateListsIdentical(tests.GetSortAndLimit(), paths) 2703 assert.NoError(t, err) 2704 2705 // Cleanup 2706 cleanArtifactoryTest() 2707 } 2708 2709 func TestArtifactoryOffset(t *testing.T) { 2710 initArtifactoryTest(t) 2711 2712 // Upload all testdata/a/ files 2713 artifactoryCli.Exec("upload", "testsdata/a/*", path.Join(tests.Repo1, "offset_test")+"/", "--flat=true") 2714 2715 // Downloading files one by one, to check that the offset is working as expected. 2716 // Download only the first file, expecting to download a1.in 2717 artifactoryCli.Exec("download", tests.Repo1+"/offset_test/", tests.Out+"/", "--flat=true", "--sort-by=name", "--limit=1", "--offset=0") 2718 paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 2719 tests.VerifyExistLocally([]string{tests.Out + fileutils.GetFileSeparator() + "a1.in"}, paths, t) 2720 2721 // Download the second file, expecting to download a2.in 2722 artifactoryCli.Exec("download", tests.Repo1+"/offset_test/", tests.Out+"/", "--flat=true", "--sort-by=name", "--limit=1", "--offset=1") 2723 paths, _ = fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 2724 tests.VerifyExistLocally([]string{tests.Out + fileutils.GetFileSeparator() + "a2.in"}, paths, t) 2725 2726 // Download the third file, expecting to download a3.in 2727 artifactoryCli.Exec("download", tests.Repo1+"/offset_test/", tests.Out+"/", "--flat=true", "--sort-by=name", "--limit=1", "--offset=2") 2728 paths, _ = fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 2729 tests.VerifyExistLocally([]string{tests.Out + fileutils.GetFileSeparator() + "a3.in"}, paths, t) 2730 2731 // Cleanup 2732 cleanArtifactoryTest() 2733 } 2734 2735 func TestArtifactoryCopyByBuildOverridingByInlineFlag(t *testing.T) { 2736 initArtifactoryTest(t) 2737 buildName, buildNumberA, buildNumberB := "cli-test-build", "10", "11" 2738 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 2739 specFile, err := tests.CreateSpec(tests.CopyByBuildSpec) 2740 assert.NoError(t, err) 2741 2742 // Upload files with buildName and buildNumber: b* uploaded with build number "10", a* uploaded with build number "11" 2743 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 2744 assert.NoError(t, err) 2745 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 2746 assert.NoError(t, err) 2747 artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+buildName, "--build-number="+buildNumberA) 2748 artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+buildName, "--build-number="+buildNumberB) 2749 2750 // Publish buildInfo 2751 artifactoryCli.Exec("build-publish", buildName, buildNumberA) 2752 artifactoryCli.Exec("build-publish", buildName, buildNumberB) 2753 2754 // Copy by build number: using override of build by flag from inline (no number set so LATEST build should be copied), a* should be copied 2755 artifactoryCli.Exec("copy", "--build="+buildName+" --spec="+specFile) 2756 2757 // Validate files are Copied by build number 2758 cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec) 2759 assert.NoError(t, err) 2760 2761 verifyExistInArtifactory(tests.GetBuildCopyExpected(), cpMvDlByBuildAssertSpec, t) 2762 2763 // Cleanup 2764 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 2765 cleanArtifactoryTest() 2766 } 2767 2768 func TestArtifactoryMoveByBuildUsingFlags(t *testing.T) { 2769 initArtifactoryTest(t) 2770 buildName, buildNumberA, buildNumberB := "cli-test-build", "10", "11" 2771 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 2772 specFile, err := tests.CreateSpec(tests.CopyByBuildSpec) 2773 assert.NoError(t, err) 2774 2775 // Upload files with buildName and buildNumber 2776 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 2777 assert.NoError(t, err) 2778 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 2779 assert.NoError(t, err) 2780 artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+buildName, "--build-number="+buildNumberA) 2781 artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+buildName, "--build-number="+buildNumberB) 2782 2783 // Publish buildInfo 2784 artifactoryCli.Exec("build-publish", buildName, buildNumberA) 2785 artifactoryCli.Exec("build-publish", buildName, buildNumberB) 2786 2787 // Move by build name and number 2788 artifactoryCli.Exec("move", "--build="+buildName+"/11 --spec="+specFile) 2789 2790 // Validate files are moved by build number 2791 cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec) 2792 assert.NoError(t, err) 2793 2794 verifyExistInArtifactory(tests.GetBuildMoveExpected(), cpMvDlByBuildAssertSpec, t) 2795 2796 // Cleanup 2797 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 2798 cleanArtifactoryTest() 2799 } 2800 2801 func TestArtifactoryMoveNoSpec(t *testing.T) { 2802 testCopyMoveNoSpec("mv", tests.GetBuildBeforeMoveExpected(), tests.GetBuildMoveExpected(), t) 2803 } 2804 2805 func TestArtifactoryMoveExcludeByCli(t *testing.T) { 2806 initArtifactoryTest(t) 2807 2808 // Upload files 2809 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 2810 assert.NoError(t, err) 2811 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 2812 assert.NoError(t, err) 2813 artifactoryCli.Exec("upload", "--spec="+specFileA) 2814 artifactoryCli.Exec("upload", "--spec="+specFileB) 2815 2816 // Move by pattern 2817 artifactoryCli.Exec("move", tests.Repo1+"/data/ "+tests.Repo2+"/", "--exclude-patterns=*b*;*c*") 2818 2819 // Validate excluded files didn't move 2820 cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec) 2821 assert.NoError(t, err) 2822 2823 verifyExistInArtifactory(tests.GetBuildMoveExpected(), cpMvDlByBuildAssertSpec, t) 2824 2825 // Cleanup 2826 cleanArtifactoryTest() 2827 } 2828 2829 func TestArtifactoryMoveExclusionsByCli(t *testing.T) { 2830 initArtifactoryTest(t) 2831 2832 // Upload files 2833 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 2834 assert.NoError(t, err) 2835 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 2836 assert.NoError(t, err) 2837 artifactoryCli.Exec("upload", "--spec="+specFileA) 2838 artifactoryCli.Exec("upload", "--spec="+specFileB) 2839 2840 // Move by pattern 2841 artifactoryCli.Exec("move", tests.Repo1+"/data/ "+tests.Repo2+"/", "--exclusions=*/*b*;*/*c*") 2842 2843 // Validate excluded files didn't move 2844 cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec) 2845 assert.NoError(t, err) 2846 2847 verifyExistInArtifactory(tests.GetBuildMoveExpected(), cpMvDlByBuildAssertSpec, t) 2848 2849 // Cleanup 2850 cleanArtifactoryTest() 2851 } 2852 2853 func TestArtifactoryMoveExcludeBySpec(t *testing.T) { 2854 initArtifactoryTest(t) 2855 specFile, err := tests.CreateSpec(tests.MoveCopySpecExclude) 2856 assert.NoError(t, err) 2857 2858 // Upload files 2859 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 2860 assert.NoError(t, err) 2861 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 2862 assert.NoError(t, err) 2863 artifactoryCli.Exec("upload", "--spec="+specFileA) 2864 artifactoryCli.Exec("upload", "--spec="+specFileB) 2865 2866 // Move by spec 2867 artifactoryCli.Exec("move", "--spec="+specFile) 2868 2869 // Validate excluded files didn't move 2870 cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec) 2871 assert.NoError(t, err) 2872 2873 verifyExistInArtifactory(tests.GetBuildMoveExpected(), cpMvDlByBuildAssertSpec, t) 2874 2875 // Cleanup 2876 cleanArtifactoryTest() 2877 } 2878 2879 func TestArtifactoryMoveExclusionsBySpec(t *testing.T) { 2880 initArtifactoryTest(t) 2881 specFile, err := tests.CreateSpec(tests.MoveCopySpecExclusions) 2882 assert.NoError(t, err) 2883 2884 // Upload files 2885 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 2886 assert.NoError(t, err) 2887 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 2888 assert.NoError(t, err) 2889 artifactoryCli.Exec("upload", "--spec="+specFileA) 2890 artifactoryCli.Exec("upload", "--spec="+specFileB) 2891 2892 // Move by spec 2893 artifactoryCli.Exec("move", "--spec="+specFile) 2894 2895 // Validate excluded files didn't move 2896 cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec) 2897 assert.NoError(t, err) 2898 2899 verifyExistInArtifactory(tests.GetBuildMoveExpected(), cpMvDlByBuildAssertSpec, t) 2900 2901 // Cleanup 2902 cleanArtifactoryTest() 2903 } 2904 2905 func TestArtifactoryDeleteByLatestBuild(t *testing.T) { 2906 initArtifactoryTest(t) 2907 buildName, buildNumberA, buildNumberB := "cli-test-build", "10", "11" 2908 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 2909 specFile, err := tests.CreateSpec(tests.CopyByBuildSpec) 2910 assert.NoError(t, err) 2911 2912 // Upload files with buildName and buildNumber 2913 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 2914 assert.NoError(t, err) 2915 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 2916 assert.NoError(t, err) 2917 artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+buildName, "--build-number="+buildNumberA) 2918 artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+buildName, "--build-number="+buildNumberB) 2919 2920 // Publish buildInfo 2921 artifactoryCli.Exec("build-publish", buildName, buildNumberA) 2922 artifactoryCli.Exec("build-publish", buildName, buildNumberB) 2923 2924 // Delete by build name and LATEST 2925 artifactoryCli.Exec("delete", "--build="+buildName+"/LATEST --spec="+specFile) 2926 2927 // Validate files are deleted by build number 2928 cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec) 2929 assert.NoError(t, err) 2930 2931 verifyExistInArtifactory(tests.GetBuildDeleteExpected(), cpMvDlByBuildAssertSpec, t) 2932 2933 // Cleanup 2934 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 2935 cleanArtifactoryTest() 2936 } 2937 2938 func TestGitLfsCleanup(t *testing.T) { 2939 initArtifactoryTest(t) 2940 var filePath = "testsdata/gitlfs/(4b)(*)" 2941 artifactoryCli.Exec("upload", filePath, tests.LfsRepo+"/objects/4b/f4/{2}{1}") 2942 artifactoryCli.Exec("upload", filePath, tests.LfsRepo+"/objects/4b/f4/") 2943 refs := strings.Join([]string{"refs", "heads", "*"}, fileutils.GetFileSeparator()) 2944 dotGitPath := getCliDotGitPath(t) 2945 artifactoryCli.Exec("glc", dotGitPath, "--repo="+tests.LfsRepo, "--refs=HEAD,"+refs) 2946 gitlfsSpecFile, err := tests.CreateSpec(tests.GitLfsAssertSpec) 2947 assert.NoError(t, err) 2948 verifyExistInArtifactory(tests.GetGitLfsExpected(), gitlfsSpecFile, t) 2949 cleanArtifactoryTest() 2950 } 2951 2952 func TestPing(t *testing.T) { 2953 initArtifactoryTest(t) 2954 artifactoryCli.Exec("ping") 2955 cleanArtifactoryTest() 2956 } 2957 2958 func TestSummaryReport(t *testing.T) { 2959 initArtifactoryTest(t) 2960 2961 previousLog := log.Logger 2962 newLog := log.NewLogger(logUtils.GetCliLogLevel(), nil) 2963 2964 // Set new logger with output redirection to buffer 2965 buffer := &bytes.Buffer{} 2966 newLog.SetOutputWriter(buffer) 2967 log.SetLogger(newLog) 2968 2969 specFile, err := tests.CreateSpec(tests.UploadFlatNonRecursive) 2970 assert.NoError(t, err) 2971 artifactoryCli.Exec("upload", "--spec="+specFile) 2972 verifySummary(t, buffer, 3, 0, previousLog) 2973 2974 artifactoryCli.Exec("move", path.Join(tests.Repo1, "*.in"), tests.Repo2+"/") 2975 verifySummary(t, buffer, 3, 0, previousLog) 2976 2977 artifactoryCli.Exec("copy", path.Join(tests.Repo2, "*.in"), tests.Repo1+"/") 2978 verifySummary(t, buffer, 3, 0, previousLog) 2979 2980 artifactoryCli.Exec("delete", path.Join(tests.Repo2, "*.in")) 2981 verifySummary(t, buffer, 3, 0, previousLog) 2982 2983 artifactoryCli.Exec("set-props", path.Join(tests.Repo1, "*.in"), "prop=val") 2984 verifySummary(t, buffer, 3, 0, previousLog) 2985 2986 specFile, err = tests.CreateSpec(tests.DownloadAllRepo1TestResources) 2987 assert.NoError(t, err) 2988 artifactoryCli.Exec("download", "--spec="+specFile) 2989 verifySummary(t, buffer, 3, 0, previousLog) 2990 2991 // Restore previous logger 2992 log.SetLogger(previousLog) 2993 cleanArtifactoryTest() 2994 } 2995 2996 func TestArtifactoryBuildDiscard(t *testing.T) { 2997 // Initialize 2998 initArtifactoryTest(t) 2999 client, err := httpclient.ClientBuilder().Build() 3000 assert.NoError(t, err) 3001 3002 // Upload files with buildName and buildNumber 3003 buildName := "jfrog-cli-discard-builds-test" 3004 for i := 1; i <= 5; i++ { 3005 artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/data/", "--build-name="+buildName, "--build-number="+strconv.Itoa(i)) 3006 artifactoryCli.Exec("build-publish", buildName, strconv.Itoa(i)) 3007 } 3008 3009 // Test discard by max-builds 3010 artifactoryCli.Exec("build-discard", buildName, "--max-builds=3") 3011 jsonResponse := getAllBuildsByBuildName(client, buildName, t, http.StatusOK) 3012 assert.Len(t, jsonResponse.Builds, 3, "Incorrect operation of build-discard by max-builds.") 3013 3014 // Test discard with exclusion 3015 artifactoryCli.Exec("build-discard", buildName, "--max-days=-1", "--exclude-builds=3,5") 3016 jsonResponse = getAllBuildsByBuildName(client, buildName, t, http.StatusOK) 3017 assert.Len(t, jsonResponse.Builds, 2, "Incorrect operation of build-discard with exclusion.") 3018 3019 // Test discard by max-days 3020 artifactoryCli.Exec("build-discard", buildName, "--max-days=-1") 3021 jsonResponse = getAllBuildsByBuildName(client, buildName, t, http.StatusNotFound) 3022 assert.Zero(t, jsonResponse, "Incorrect operation of build-discard by max-days.") 3023 3024 //Cleanup 3025 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 3026 cleanArtifactoryTest() 3027 } 3028 3029 // Tests compatibility to file paths with windows separators. 3030 // Verifies the upload and download commands work as expected for inputs of both arguments and spec files. 3031 func TestArtifactoryWinBackwardsCompatibility(t *testing.T) { 3032 initArtifactoryTest(t) 3033 if !cliutils.IsWindows() { 3034 t.Skip("Not running on Windows, skipping...") 3035 } 3036 uploadSpecFile, err := tests.CreateSpec(tests.WinSimpleUploadSpec) 3037 assert.NoError(t, err) 3038 artifactoryCli.Exec("upload", "--spec="+uploadSpecFile) 3039 artifactoryCli.Exec("upload", "testsdata\\\\a\\\\b\\\\*", tests.Repo1+"/compatibility_arguments/", "--exclusions=*b2.in;*c*") 3040 3041 downloadSpecFile, err := tests.CreateSpec(tests.WinSimpleDownloadSpec) 3042 assert.NoError(t, err) 3043 artifactoryCli.Exec("download", "--spec="+downloadSpecFile) 3044 artifactoryCli.Exec("download", tests.Repo1+"/*arguments*", "out\\\\win\\\\", "--flat=true") 3045 3046 // Validate files are downloaded by build number 3047 paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) 3048 err = tests.ValidateListsIdentical(tests.GetWinCompatibility(), paths) 3049 assert.NoError(t, err) 3050 cleanArtifactoryTest() 3051 } 3052 3053 func TestArtifactorySearchIncludeDir(t *testing.T) { 3054 initArtifactoryTest(t) 3055 3056 // Upload files 3057 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 3058 assert.NoError(t, err) 3059 artifactoryCli.Exec("upload", "--spec="+specFileA, "--recursive", "--flat=false") 3060 3061 // Prepare search command 3062 searchSpecBuilder := spec.NewBuilder().Pattern(tests.Repo1).Recursive(true) 3063 searchCmd := generic.NewSearchCommand() 3064 searchCmd.SetRtDetails(artifactoryDetails) 3065 3066 // Search without IncludeDirs 3067 searchCmd.SetSpec(searchSpecBuilder.IncludeDirs(false).BuildSpec()) 3068 assert.NoError(t, searchCmd.Search()) 3069 assert.NoError(t, assertDateInSearchResult(searchCmd.SearchResult())) 3070 assert.ElementsMatch(t, searchCmd.SearchResultNoDate(), tests.GetSearchNotIncludeDirsFiles()) 3071 3072 // Search with IncludeDirs 3073 searchCmd.SetSpec(searchSpecBuilder.IncludeDirs(true).BuildSpec()) 3074 assert.NoError(t, searchCmd.Search()) 3075 assert.NoError(t, assertDateInSearchResult(searchCmd.SearchResult())) 3076 assert.ElementsMatch(t, searchCmd.SearchResultNoDate(), tests.GetSearchIncludeDirsFiles()) 3077 3078 // Cleanup 3079 cleanArtifactoryTest() 3080 } 3081 3082 func TestArtifactorySearchProps(t *testing.T) { 3083 initArtifactoryTest(t) 3084 3085 // Upload files 3086 specFile, err := tests.CreateSpec(tests.UploadWithPropsSpec) 3087 assert.NoError(t, err) 3088 artifactoryCli.Exec("upload", "--spec="+specFile, "--recursive") 3089 3090 // Prepare search command 3091 searchSpecBuilder := spec.NewBuilder().Pattern(tests.Repo1).Recursive(true) 3092 searchCmd := generic.NewSearchCommand() 3093 searchCmd.SetRtDetails(artifactoryDetails) 3094 3095 // Search artifacts with c=3 3096 searchCmd.SetSpec(searchSpecBuilder.Props("c=3").BuildSpec()) 3097 assert.NoError(t, searchCmd.Search()) 3098 assert.NoError(t, assertDateInSearchResult(searchCmd.SearchResult())) 3099 assert.ElementsMatch(t, searchCmd.SearchResultNoDate(), tests.GetSearchPropsStep1()) 3100 3101 // Search artifacts without c=3 3102 searchCmd.SetSpec(searchSpecBuilder.Props("").ExcludeProps("c=3").BuildSpec()) 3103 assert.NoError(t, searchCmd.Search()) 3104 assert.NoError(t, assertDateInSearchResult(searchCmd.SearchResult())) 3105 assert.ElementsMatch(t, searchCmd.SearchResultNoDate(), tests.GetSearchPropsStep2()) 3106 3107 // Search artifacts without a=1&b=2 3108 searchCmd.SetSpec(searchSpecBuilder.Props("").ExcludeProps("a=1;b=2").BuildSpec()) 3109 assert.NoError(t, searchCmd.Search()) 3110 assert.NoError(t, assertDateInSearchResult(searchCmd.SearchResult())) 3111 assert.ElementsMatch(t, searchCmd.SearchResultNoDate(), tests.GetSearchPropsStep3()) 3112 3113 // Search artifacts without a=1&b=2 and with c=3 3114 searchCmd.SetSpec(searchSpecBuilder.Props("c=3").ExcludeProps("a=1;b=2").BuildSpec()) 3115 assert.NoError(t, searchCmd.Search()) 3116 assert.NoError(t, assertDateInSearchResult(searchCmd.SearchResult())) 3117 assert.ElementsMatch(t, searchCmd.SearchResultNoDate(), tests.GetSearchPropsStep4()) 3118 3119 // Search artifacts without a=1 and with c=5 3120 searchCmd.SetSpec(searchSpecBuilder.Props("c=5").ExcludeProps("a=1").BuildSpec()) 3121 assert.NoError(t, searchCmd.Search()) 3122 assert.NoError(t, assertDateInSearchResult(searchCmd.SearchResult())) 3123 assert.ElementsMatch(t, searchCmd.SearchResultNoDate(), tests.GetSearchPropsStep5()) 3124 3125 // Search artifacts by pattern "*b*", exclude pattern "*3*", with "b=1" and without "c=3" 3126 pattern := tests.Repo1 + "/*b*" 3127 exclusions := []string{tests.Repo1 + "/*3*"} 3128 searchSpecBuilder = spec.NewBuilder().Pattern(pattern).Recursive(true).Exclusions(exclusions).Props("b=1").ExcludeProps("c=3") 3129 searchCmd.SetSpec(searchSpecBuilder.BuildSpec()) 3130 assert.NoError(t, searchCmd.Search()) 3131 assert.NoError(t, assertDateInSearchResult(searchCmd.SearchResult())) 3132 assert.ElementsMatch(t, searchCmd.SearchResultNoDate(), tests.GetSearchPropsStep6()) 3133 3134 // Cleanup 3135 cleanArtifactoryTest() 3136 } 3137 3138 func getAllBuildsByBuildName(client *httpclient.HttpClient, buildName string, t *testing.T, expectedHttpStatusCode int) buildsApiResponseStruct { 3139 resp, body, _, _ := client.SendGet(artifactoryDetails.Url+"api/build/"+buildName, true, artHttpDetails) 3140 assert.Equal(t, expectedHttpStatusCode, resp.StatusCode, "Failed retrieving build information from artifactory.") 3141 3142 buildsApiResponse := &buildsApiResponseStruct{} 3143 err := json.Unmarshal(body, buildsApiResponse) 3144 assert.NoError(t, err, "Unmarshaling failed with an error") 3145 return *buildsApiResponse 3146 } 3147 3148 type buildsApiInnerBuildsStruct struct { 3149 Uri string `json:"uri,omitempty"` 3150 Started string `json:"started,omitempty"` 3151 } 3152 3153 type buildsApiResponseStruct struct { 3154 Uri string `json:"uri,omitempty"` 3155 Builds []buildsApiInnerBuildsStruct `json:"buildsNumbers,omitempty"` 3156 } 3157 3158 func verifySummary(t *testing.T, buffer *bytes.Buffer, success, failure int64, logger log.Log) { 3159 content := buffer.Bytes() 3160 buffer.Reset() 3161 logger.Output(string(content)) 3162 3163 status, err := jsonparser.GetString(content, "status") 3164 assert.NoError(t, err) 3165 assert.Equal(t, "success", status, "Summary validation failed") 3166 3167 resultSuccess, err := jsonparser.GetInt(content, "totals", "success") 3168 assert.NoError(t, err) 3169 3170 resultFailure, err := jsonparser.GetInt(content, "totals", "failure") 3171 assert.NoError(t, err) 3172 3173 assert.Equal(t, success, resultSuccess, "Summary validation failed") 3174 assert.Equal(t, failure, resultFailure, "Summary validation failed") 3175 } 3176 3177 func CleanArtifactoryTests() { 3178 cleanArtifactoryTest() 3179 deleteRepos() 3180 } 3181 3182 func initArtifactoryTest(t *testing.T) { 3183 if !*tests.TestArtifactory { 3184 t.Skip("Artifactory is not being tested, skipping...") 3185 } 3186 } 3187 3188 func cleanArtifactoryTest() { 3189 if !*tests.TestArtifactory && !*tests.TestDistribution { 3190 return 3191 } 3192 os.Unsetenv(cliutils.HomeDir) 3193 log.Info("Cleaning test data...") 3194 cleanArtifactory() 3195 tests.CleanFileSystem() 3196 } 3197 3198 func preUploadBasicTestResources() { 3199 uploadPath := tests.GetTestResourcesPath() + "a/(.*)" 3200 targetPath := tests.Repo1 + "/test_resources/{1}" 3201 flags := "--threads=10 --regexp=true --props=searchMe=true --flat=false" 3202 artifactoryCli.Exec("upload", uploadPath, targetPath, flags) 3203 } 3204 3205 func execDeleteRepoRest(repoName string) { 3206 client, err := httpclient.ClientBuilder().Build() 3207 if err != nil { 3208 log.Error(err) 3209 os.Exit(1) 3210 } 3211 resp, body, err := client.SendDelete(artifactoryDetails.Url+"api/repositories/"+repoName, nil, artHttpDetails) 3212 if err != nil { 3213 log.Error(err) 3214 return 3215 } 3216 if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated { 3217 log.Error(errors.New("Artifactory response: " + resp.Status + "\n" + clientutils.IndentJson(body))) 3218 return 3219 } 3220 log.Info("Repository", repoName, "deleted.") 3221 } 3222 3223 func execListRepoRest() ([]string, error) { 3224 var repositoryKeys []string 3225 3226 // Build http client 3227 client, err := httpclient.ClientBuilder().Build() 3228 if err != nil { 3229 return nil, err 3230 } 3231 3232 // Send get request 3233 resp, body, _, err := client.SendGet(artifactoryDetails.Url+"api/repositories", true, artHttpDetails) 3234 if err != nil { 3235 return nil, err 3236 } 3237 if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated { 3238 return nil, errors.New("Artifactory response: " + resp.Status + "\n" + clientutils.IndentJson(body)) 3239 } 3240 3241 // Extract repository keys from the json response 3242 var keyError error 3243 _, err = jsonparser.ArrayEach(body, func(value []byte, dataType jsonparser.ValueType, offset int, err error) { 3244 if err != nil || keyError != nil { 3245 return 3246 } 3247 repoKey, err := jsonparser.GetString(value, "key") 3248 if err != nil { 3249 keyError = err 3250 return 3251 } 3252 repositoryKeys = append(repositoryKeys, repoKey) 3253 }) 3254 if keyError != nil { 3255 return nil, err 3256 } 3257 3258 return repositoryKeys, err 3259 } 3260 3261 func execCreateRepoRest(repoConfig, repoName string) { 3262 content, err := ioutil.ReadFile(repoConfig) 3263 if err != nil { 3264 log.Error(err) 3265 os.Exit(1) 3266 } 3267 rtutils.AddHeader("Content-Type", "application/json", &artHttpDetails.Headers) 3268 client, err := httpclient.ClientBuilder().Build() 3269 if err != nil { 3270 log.Error(err) 3271 os.Exit(1) 3272 } 3273 resp, body, err := client.SendPut(artifactoryDetails.Url+"api/repositories/"+repoName, content, artHttpDetails) 3274 if err != nil { 3275 log.Error(err) 3276 os.Exit(1) 3277 } 3278 if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated { 3279 log.Error(errors.New("Artifactory response: " + resp.Status + "\n" + clientutils.IndentJson(body))) 3280 os.Exit(1) 3281 } 3282 log.Info("Repository", repoName, "created.") 3283 } 3284 3285 func createReposIfNeeded() { 3286 cleanUpOldRepositories() 3287 createRandomReposName() 3288 nonVirtualRepos := tests.GetNonVirtualRepositories() 3289 createRepos(nonVirtualRepos) 3290 virtualRepos := tests.GetVirtualRepositories() 3291 createRepos(virtualRepos) 3292 } 3293 3294 func cleanUpOldRepositories() { 3295 repositoryKeys, err := execListRepoRest() 3296 if err != nil { 3297 log.Warn("Couldn't retrieve repository list from Artifactory", err) 3298 return 3299 } 3300 3301 now := time.Now() 3302 repoPattern := regexp.MustCompile(`^jfrog-cli-tests(-\w*)+-(\d*)$`) 3303 for _, repoKey := range repositoryKeys { 3304 regexGroups := repoPattern.FindStringSubmatch(repoKey) 3305 if regexGroups == nil { 3306 // Repository is not "jfrog-cli-tests-..." 3307 continue 3308 } 3309 3310 repoTimestamp, err := strconv.ParseInt(regexGroups[len(regexGroups)-1], 10, 64) 3311 if err != nil { 3312 log.Warn("Error while parsing repository timestamp of repository ", repoKey, err) 3313 continue 3314 } 3315 3316 repoTime := time.Unix(repoTimestamp, 0) 3317 if now.Sub(repoTime).Hours() > 24.0 { 3318 log.Info("Deleting old repository", repoKey) 3319 execDeleteRepoRest(repoKey) 3320 } 3321 } 3322 } 3323 3324 func createRepos(repos map[string]string) { 3325 for repoName, configFile := range repos { 3326 if !isRepoExist(repoName) { 3327 repoConfig := tests.GetTestResourcesPath() + configFile 3328 repoConfig, err := tests.ReplaceTemplateVariables(repoConfig, "") 3329 if err != nil { 3330 log.Error(err) 3331 os.Exit(1) 3332 } 3333 execCreateRepoRest(repoConfig, repoName) 3334 } 3335 } 3336 } 3337 3338 func createRandomReposName() { 3339 timestamp := strconv.FormatInt(time.Now().Unix(), 10) 3340 tests.Repo1 += "-" + timestamp 3341 tests.Repo2 += "-" + timestamp 3342 tests.Repo1And2 += "-" + timestamp 3343 tests.VirtualRepo += "-" + timestamp 3344 tests.LfsRepo += "-" + timestamp 3345 tests.DebianRepo += "-" + timestamp 3346 tests.JcenterRemoteRepo += "-" + timestamp 3347 if *tests.TestNpm { 3348 tests.NpmLocalRepo += "-" + timestamp 3349 tests.NpmRemoteRepo += "-" + timestamp 3350 } 3351 if *tests.TestGo { 3352 tests.GoLocalRepo += "-" + timestamp 3353 } 3354 if *tests.TestPip { 3355 tests.PypiRemoteRepo += "-" + timestamp 3356 tests.PypiVirtualRepo += "-" + timestamp 3357 } 3358 } 3359 3360 // Important - Virtual repositories most be deleted first 3361 func deleteRepos() { 3362 repos := []string{ 3363 tests.VirtualRepo, 3364 tests.Repo1, 3365 tests.Repo2, 3366 tests.LfsRepo, 3367 tests.DebianRepo, 3368 tests.JcenterRemoteRepo, 3369 } 3370 3371 if *tests.TestNpm { 3372 repos = append(repos, tests.NpmLocalRepo, tests.NpmRemoteRepo) 3373 } 3374 if *tests.TestGo { 3375 repos = append(repos, tests.GoLocalRepo) 3376 } 3377 if *tests.TestPip { 3378 repos = append(repos, tests.PypiVirtualRepo, tests.PypiRemoteRepo) 3379 } 3380 3381 for _, repoName := range repos { 3382 if isRepoExist(repoName) { 3383 execDeleteRepoRest(repoName) 3384 } 3385 } 3386 } 3387 3388 func cleanArtifactory() { 3389 deleteSpecFile := tests.GetFilePathForArtifactory(tests.DeleteSpec) 3390 fmt.Println(deleteSpecFile) 3391 deleteSpecFile, err := tests.ReplaceTemplateVariables(deleteSpecFile, "") 3392 fmt.Println(deleteSpecFile) 3393 if err != nil { 3394 log.Error(err) 3395 os.Exit(1) 3396 } 3397 deleteSpec, _ := spec.CreateSpecFromFile(deleteSpecFile, nil) 3398 tests.DeleteFiles(deleteSpec, artifactoryDetails) 3399 } 3400 3401 func searchInArtifactory(specFile string) ([]generic.SearchResult, error) { 3402 searchSpec, _ := spec.CreateSpecFromFile(specFile, nil) 3403 searchCmd := generic.NewSearchCommand() 3404 searchCmd.SetRtDetails(artifactoryDetails).SetSpec(searchSpec) 3405 err := searchCmd.Search() 3406 return searchCmd.SearchResult(), err 3407 } 3408 3409 func getSpecAndCommonFlags(specFile string) (*spec.SpecFiles, rtutils.CommonConf) { 3410 searchFlags := new(rtutils.CommonConfImpl) 3411 searchSpec, _ := spec.CreateSpecFromFile(specFile, nil) 3412 return searchSpec, searchFlags 3413 } 3414 3415 func verifyExistInArtifactory(expected []string, specFile string, t *testing.T) { 3416 results, _ := searchInArtifactory(specFile) 3417 tests.CompareExpectedVsActual(expected, results, t) 3418 } 3419 3420 func verifyDoesntExistInArtifactory(specFile string, t *testing.T) { 3421 verifyExistInArtifactory([]string{}, specFile, t) 3422 } 3423 3424 func verifyExistInArtifactoryByProps(expected []string, pattern, props string, t *testing.T) { 3425 searchSpec := spec.NewBuilder().Pattern(pattern).Props(props).Recursive(true).BuildSpec() 3426 searchCmd := generic.NewSearchCommand() 3427 searchCmd.SetRtDetails(artifactoryDetails).SetSpec(searchSpec) 3428 err := searchCmd.Search() 3429 assert.NoError(t, err) 3430 tests.CompareExpectedVsActual(expected, searchCmd.SearchResult(), t) 3431 } 3432 3433 func isRepoExist(repoName string) bool { 3434 client, err := httpclient.ClientBuilder().Build() 3435 if err != nil { 3436 log.Error(err) 3437 os.Exit(1) 3438 } 3439 resp, _, _, err := client.SendGet(artifactoryDetails.Url+tests.RepoDetailsUrl+repoName, true, artHttpDetails) 3440 if err != nil { 3441 log.Error(err) 3442 os.Exit(1) 3443 } 3444 3445 if resp.StatusCode != http.StatusBadRequest { 3446 return true 3447 } 3448 return false 3449 } 3450 3451 func getCliDotGitPath(t *testing.T) string { 3452 dotGitPath, err := os.Getwd() 3453 assert.NoError(t, err, "Failed to get current dir.") 3454 dotGitExists, err := fileutils.IsDirExists(filepath.Join(dotGitPath, ".git"), false) 3455 assert.NoError(t, err) 3456 assert.True(t, dotGitExists, "Can't find .git") 3457 return dotGitPath 3458 } 3459 3460 func deleteServerConfig() { 3461 configArtifactoryCli.Exec("c", "delete", tests.RtServerId, "--interactive=false") 3462 } 3463 3464 // This function will create server config and return the entire passphrase flag if it needed. 3465 // For example if passphrase is needed it will return "--ssh-passphrase=${theConfiguredPassphrase}" or empty string. 3466 func createServerConfigAndReturnPassphrase() (passphrase string) { 3467 if *tests.RtSshPassphrase != "" { 3468 passphrase = "--ssh-passphrase=" + *tests.RtSshPassphrase 3469 } 3470 configArtifactoryCli.Exec("c", tests.RtServerId, "--interactive=false") 3471 return passphrase 3472 } 3473 3474 func testCopyMoveNoSpec(command string, beforeCommandExpected, afterCommandExpected []string, t *testing.T) { 3475 initArtifactoryTest(t) 3476 3477 // Upload files 3478 specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA) 3479 assert.NoError(t, err) 3480 specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB) 3481 assert.NoError(t, err) 3482 3483 artifactoryCli.Exec("upload", "--spec="+specFileA) 3484 artifactoryCli.Exec("upload", "--spec="+specFileB) 3485 3486 // Run command with dry-run 3487 artifactoryCli.Exec(command, tests.Repo1+"/data/*a* "+tests.Repo2+"/", "--dry-run") 3488 3489 // Validate files weren't affected 3490 cpMvSpecFilePath, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec) 3491 assert.NoError(t, err) 3492 verifyExistInArtifactory(beforeCommandExpected, cpMvSpecFilePath, t) 3493 3494 // Run command 3495 artifactoryCli.Exec(command, tests.Repo1+"/data/*a* "+tests.Repo2+"/") 3496 3497 // Validate files were affected 3498 verifyExistInArtifactory(afterCommandExpected, cpMvSpecFilePath, t) 3499 3500 // Cleanup 3501 cleanArtifactoryTest() 3502 } 3503 3504 func searchItemsInArtifactory(t *testing.T) []rtutils.ResultItem { 3505 fileSpec, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix) 3506 assert.NoError(t, err) 3507 spec, flags := getSpecAndCommonFlags(fileSpec) 3508 flags.SetArtifactoryDetails(artAuth) 3509 var resultItems []rtutils.ResultItem 3510 for i := 0; i < len(spec.Files); i++ { 3511 3512 searchParams, err := generic.GetSearchParams(spec.Get(i)) 3513 assert.NoError(t, err, "Failed Searching files") 3514 3515 currentResultItems, err := services.SearchBySpecFiles(searchParams, flags, rtutils.ALL) 3516 assert.NoError(t, err, "Failed Searching files") 3517 resultItems = append(resultItems, currentResultItems...) 3518 } 3519 return resultItems 3520 } 3521 3522 func assertDateInSearchResult(searchResult []generic.SearchResult) error { 3523 for _, v := range searchResult { 3524 if v.Created == "" || v.Modified == "" { 3525 message, err := json.Marshal(&v) 3526 if err != nil { 3527 return errors.New("failed to process search result to assert it includes date: " + err.Error()) 3528 } 3529 return errors.New("search result does not include date: " + string(message)) 3530 } 3531 } 3532 return nil 3533 } 3534 3535 func TestArtifactoryUploadInflatedPath(t *testing.T) { 3536 initArtifactoryTest(t) 3537 artifactoryCli.Exec("upload", "testsdata/a/../a/a1.*", tests.Repo1) 3538 artifactoryCli.Exec("upload", "testsdata/./a/a1.*", tests.Repo1) 3539 searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix) 3540 assert.NoError(t, err) 3541 verifyExistInArtifactory(tests.GetSimpleUploadSpecialCharNoRegexExpectedRepo1(), searchFilePath, t) 3542 3543 artifactoryCli.Exec("upload", "testsdata/./a/../a/././././a2.*", tests.Repo1) 3544 searchFilePath, err = tests.CreateSpec(tests.SearchRepo1ByInSuffix) 3545 assert.NoError(t, err) 3546 verifyExistInArtifactory(tests.GetSimpleUploadSpecialCharNoRegexExpected2filesRepo1(), searchFilePath, t) 3547 if cliutils.IsWindows() { 3548 artifactoryCli.Exec("upload", `testsdata\\a\\..\\a\\a1.*`, tests.Repo2) 3549 artifactoryCli.Exec("upload", `testsdata\\.\\\a\a1.*`, tests.Repo2) 3550 searchFilePath, err = tests.CreateSpec(tests.SearchRepo2) 3551 assert.NoError(t, err) 3552 verifyExistInArtifactory(tests.GetSimpleUploadSpecialCharNoRegexExpectedRepo2(), searchFilePath, t) 3553 3554 artifactoryCli.Exec("upload", `testsdata\\.\\a\\..\\a\\.\\.\\.\\.\\a2.*`, tests.Repo2) 3555 searchFilePath, err = tests.CreateSpec(tests.SearchRepo2) 3556 assert.NoError(t, err) 3557 verifyExistInArtifactory(tests.GetSimpleUploadSpecialCharNoRegexExpected2filesRepo2(), searchFilePath, t) 3558 } 3559 cleanArtifactoryTest() 3560 } 3561 3562 func TestGetJcenterRemoteDetails(t *testing.T) { 3563 initArtifactoryTest(t) 3564 createServerConfigAndReturnPassphrase() 3565 3566 unsetEnvVars := func() { 3567 err := os.Unsetenv(utils.JCenterRemoteServerEnv) 3568 assert.NoError(t, err) 3569 err = os.Unsetenv(utils.JCenterRemoteRepoEnv) 3570 assert.NoError(t, err) 3571 } 3572 unsetEnvVars() 3573 defer unsetEnvVars() 3574 3575 // The utils.JCenterRemoteServerEnv env var is not set, so extractor1.jar should be downloaded from jcenter. 3576 downloadPath := "org/jfrog/buildinfo/build-info-extractor/extractor1.jar" 3577 expectedRemotePath := path.Join("bintray/jcenter", downloadPath) 3578 validateJcenterRemoteDetails(t, downloadPath, expectedRemotePath) 3579 3580 // Still, the utils.JCenterRemoteServerEnv env var is not set, so the download should be from jcenter. 3581 // Expecting a different download path this time. 3582 downloadPath = "org/jfrog/buildinfo/build-info-extractor/extractor2.jar" 3583 expectedRemotePath = path.Join("bintray/jcenter", downloadPath) 3584 validateJcenterRemoteDetails(t, downloadPath, expectedRemotePath) 3585 3586 // Setting the utils.JCenterRemoteServerEnv env var now, 3587 // Expecting therefore the download to be from the the server ID configured by this env var. 3588 err := os.Setenv(utils.JCenterRemoteServerEnv, tests.RtServerId) 3589 assert.NoError(t, err) 3590 downloadPath = "org/jfrog/buildinfo/build-info-extractor/extractor3.jar" 3591 expectedRemotePath = path.Join("jcenter", downloadPath) 3592 validateJcenterRemoteDetails(t, downloadPath, expectedRemotePath) 3593 3594 // Still expecting the download to be from the same server ID, but this time, not through a remote repo named 3595 // jcenter, but through test-remote-repo. 3596 testRemoteRepo := "test-remote-repo" 3597 err = os.Setenv(utils.JCenterRemoteRepoEnv, testRemoteRepo) 3598 assert.NoError(t, err) 3599 downloadPath = "1org/jfrog/buildinfo/build-info-extractor/extractor4.jar" 3600 expectedRemotePath = path.Join(testRemoteRepo, downloadPath) 3601 validateJcenterRemoteDetails(t, downloadPath, expectedRemotePath) 3602 cleanArtifactoryTest() 3603 } 3604 3605 func validateJcenterRemoteDetails(t *testing.T, downloadPath, expectedRemotePath string) { 3606 artDetails, remotePath, err := utils.GetJcenterRemoteDetails(downloadPath) 3607 assert.NoError(t, err) 3608 assert.Equal(t, expectedRemotePath, remotePath) 3609 assert.False(t, os.Getenv(utils.JCenterRemoteServerEnv) != "" && artDetails == nil, "Expected a server to be returned") 3610 } 3611 3612 func TestVcsProps(t *testing.T) { 3613 initArtifactoryTest(t) 3614 testDir := initVcsTestDir(t) 3615 artifactoryCli.Exec("upload", filepath.Join(testDir, "*"), tests.Repo1, "--flat=false", "--build-name=jfrog-cli-test-vcs-props", "--build-number=2020") 3616 resultItems := searchItemsInArtifactory(t) 3617 assert.NotZero(t, len(resultItems), "No artifacts were found.") 3618 for _, item := range resultItems { 3619 properties := item.Properties 3620 foundUrl, foundRevision := false, false 3621 for _, prop := range properties { 3622 if item.Name == "a1.in" || item.Name == "a2.in" { 3623 // Check that properties were not removed. 3624 if prop.Key == "vcs.url" && prop.Value == "https://github.com/jfrog/jfrog-cli.git" { 3625 assert.False(t, foundUrl, "Found duplicate VCS property(url) in artifact") 3626 foundUrl = true 3627 } 3628 if prop.Key == "vcs.revision" && prop.Value == "d63c5957ad6819f4c02a817abe757f210d35ff92" { 3629 assert.False(t, foundRevision, "Found duplicate VCS property(revision) in artifact") 3630 foundRevision = true 3631 } 3632 } 3633 if item.Name == "b1.in" || item.Name == "b2.in" { 3634 if prop.Key == "vcs.url" && prop.Value == "https://github.com/jfrog/jfrog-client-go.git" { 3635 assert.False(t, foundUrl, "Found duplicate VCS property(url) in artifact") 3636 foundUrl = true 3637 } 3638 if prop.Key == "vcs.revision" && prop.Value == "ad99b6c068283878fde4d49423728f0bdc00544a" { 3639 assert.False(t, foundRevision, "Found duplicate VCS property(revision) in artifact") 3640 foundRevision = true 3641 } 3642 } 3643 } 3644 assert.True(t, foundUrl && foundRevision, "VCS property was not found on artifact: "+item.Name) 3645 } 3646 cleanArtifactoryTest() 3647 } 3648 3649 func initVcsTestDir(t *testing.T) string { 3650 testsdataSrc := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "vcs") 3651 testsdataTarget := tests.Temp 3652 err := fileutils.CopyDir(testsdataSrc, testsdataTarget, true) 3653 assert.NoError(t, err) 3654 if found, err := fileutils.IsDirExists(filepath.Join(testsdataTarget, "gitdata"), false); found { 3655 assert.NoError(t, err) 3656 tests.RenamePath(filepath.Join(testsdataTarget, "gitdata"), filepath.Join(testsdataTarget, ".git"), t) 3657 } 3658 if found, err := fileutils.IsDirExists(filepath.Join(testsdataTarget, "OtherGit", "gitdata"), false); found { 3659 assert.NoError(t, err) 3660 tests.RenamePath(filepath.Join(testsdataTarget, "OtherGit", "gitdata"), filepath.Join(testsdataTarget, "OtherGit", ".git"), t) 3661 } 3662 path, err := filepath.Abs(tests.Temp) 3663 assert.NoError(t, err) 3664 return path 3665 } 3666 3667 func TestArtifactoryReplicationCreate(t *testing.T) { 3668 initArtifactoryTest(t) 3669 configArtifactoryCli.Exec("c", tests.RtServerId, "--url="+*tests.RtUrl, "--user="+*tests.RtUser, "--password="+*tests.RtPassword, "--apikey="+*tests.RtApiKey, "--access-token="+*tests.RtAccessToken, "--interactive=false") 3670 defer deleteServerConfig() 3671 3672 // Init tmp dir 3673 specFile, err := tests.CreateSpec(tests.ReplicationTempCreate) 3674 assert.NoError(t, err) 3675 3676 // Create push replication 3677 err = artifactoryCli.Exec("rplc", specFile) 3678 assert.NoError(t, err) 3679 3680 // Validate create replication 3681 servicesManager, err := utils.CreateServiceManager(artifactoryDetails, false) 3682 assert.NoError(t, err) 3683 result, err := servicesManager.GetReplication(tests.Repo1) 3684 assert.NoError(t, err) 3685 result[0].Password = "" 3686 assert.ElementsMatch(t, result, tests.GetReplicationConfig()) 3687 3688 // Delete replication 3689 err = artifactoryCli.Exec("rpldel", tests.Repo1) 3690 assert.NoError(t, err) 3691 3692 // Validate delete replication 3693 result, err = servicesManager.GetReplication(tests.Repo1) 3694 assert.Error(t, err) 3695 // Cleanup 3696 cleanArtifactoryTest() 3697 }