github.com/wmuizelaar/kpt@v0.0.0-20221018115725-bd564717b2ed/internal/util/get/get_test.go (about) 1 // Copyright 2019 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package get_test 16 17 import ( 18 "bytes" 19 "os" 20 "path/filepath" 21 "testing" 22 23 "github.com/GoogleContainerTools/kpt/internal/printer/fake" 24 "github.com/GoogleContainerTools/kpt/internal/testutil" 25 "github.com/GoogleContainerTools/kpt/internal/testutil/pkgbuilder" 26 . "github.com/GoogleContainerTools/kpt/internal/util/get" 27 kptfilev1 "github.com/GoogleContainerTools/kpt/pkg/api/kptfile/v1" 28 "github.com/stretchr/testify/assert" 29 "sigs.k8s.io/kustomize/kyaml/kio" 30 "sigs.k8s.io/kustomize/kyaml/kio/filters" 31 "sigs.k8s.io/kustomize/kyaml/yaml" 32 ) 33 34 const JavaSubdir = "java" 35 36 func TestMain(m *testing.M) { 37 os.Exit(testutil.ConfigureTestKptCache(m)) 38 } 39 40 // TestCommand_Run_failEmptyRepo verifies that Command fail if not repo is provided. 41 func TestCommand_Run_failEmptyRepo(t *testing.T) { 42 _, w, clean := testutil.SetupRepoAndWorkspace(t, testutil.Content{}) 43 defer clean() 44 45 err := Command{ 46 Destination: w.WorkspaceDirectory, 47 }.Run(fake.CtxWithDefaultPrinter()) 48 if !assert.Error(t, err) { 49 t.FailNow() 50 } 51 assert.Contains(t, err.Error(), "must specify git repo information") 52 } 53 54 // TestCommand_Run_failEmptyRepo verifies that Command fail if not repo is provided. 55 func TestCommand_Run_failNoRevision(t *testing.T) { 56 _, w, clean := testutil.SetupRepoAndWorkspace(t, testutil.Content{}) 57 defer clean() 58 59 err := Command{ 60 Git: &kptfilev1.Git{ 61 Repo: "foo", 62 }, 63 Destination: w.WorkspaceDirectory, 64 }.Run(fake.CtxWithDefaultPrinter()) 65 if !assert.Error(t, err) { 66 t.FailNow() 67 } 68 assert.Contains(t, err.Error(), "must specify ref") 69 } 70 71 // TestCommand_Run verifies that Command will clone the HEAD of the master branch. 72 // 73 // - destination directory should match the base name of the repo 74 // - KptFile should be populated with values pointing to the origin 75 func TestCommand_Run(t *testing.T) { 76 g, w, clean := testutil.SetupRepoAndWorkspace(t, testutil.Content{ 77 Data: testutil.Dataset1, 78 Branch: "master", 79 }) 80 defer clean() 81 82 defer testutil.Chdir(t, w.WorkspaceDirectory)() 83 84 absPath := filepath.Join(w.WorkspaceDirectory, g.RepoName) 85 err := Command{Git: &kptfilev1.Git{ 86 Repo: "file://" + g.RepoDirectory, 87 Ref: "master", 88 Directory: "/", 89 }, 90 Destination: absPath}.Run(fake.CtxWithDefaultPrinter()) 91 assert.NoError(t, err) 92 93 // verify the cloned contents matches the repository 94 g.AssertEqual(t, filepath.Join(g.DatasetDirectory, testutil.Dataset1), absPath, true) 95 96 // verify the KptFile contains the expected values 97 commit, err := g.GetCommit() 98 assert.NoError(t, err) 99 g.AssertKptfile(t, absPath, kptfilev1.KptFile{ 100 ResourceMeta: yaml.ResourceMeta{ 101 ObjectMeta: yaml.ObjectMeta{ 102 NameMeta: yaml.NameMeta{ 103 Name: g.RepoName, 104 }, 105 }, 106 TypeMeta: yaml.TypeMeta{ 107 APIVersion: kptfilev1.TypeMeta.APIVersion, 108 Kind: kptfilev1.TypeMeta.Kind}, 109 }, 110 UpstreamLock: &kptfilev1.UpstreamLock{ 111 Type: kptfilev1.GitOrigin, 112 Git: &kptfilev1.GitLock{ 113 Directory: "/", 114 Repo: "file://" + g.RepoDirectory, 115 Ref: "master", 116 Commit: commit, // verify the commit matches the repo 117 }, 118 }, 119 Upstream: &kptfilev1.Upstream{ 120 Type: kptfilev1.GitOrigin, 121 Git: &kptfilev1.Git{ 122 Directory: "/", 123 Repo: "file://" + g.RepoDirectory, 124 Ref: "master", 125 }, 126 UpdateStrategy: kptfilev1.ResourceMerge, 127 }, 128 }) 129 } 130 131 // TestCommand_Run_subdir verifies that Command will clone a subdirectory of a repo. 132 // 133 // - destination dir should match the name of the subdirectory 134 // - KptFile should have the subdir listed 135 func TestCommand_Run_subdir(t *testing.T) { 136 subdir := JavaSubdir 137 g, w, clean := testutil.SetupRepoAndWorkspace(t, testutil.Content{ 138 Data: testutil.Dataset1, 139 Branch: "master", 140 }) 141 defer clean() 142 143 defer testutil.Chdir(t, w.WorkspaceDirectory)() 144 145 absPath := filepath.Join(w.WorkspaceDirectory, subdir) 146 err := Command{Git: &kptfilev1.Git{ 147 Repo: g.RepoDirectory, Ref: "refs/heads/master", Directory: subdir}, 148 Destination: absPath, 149 }.Run(fake.CtxWithDefaultPrinter()) 150 assert.NoError(t, err) 151 152 // verify the cloned contents matches the repository 153 g.AssertEqual(t, filepath.Join(g.DatasetDirectory, testutil.Dataset1, subdir), absPath, true) 154 155 // verify the KptFile contains the expected values 156 commit, err := g.GetCommit() 157 assert.NoError(t, err) 158 g.AssertKptfile(t, absPath, kptfilev1.KptFile{ 159 ResourceMeta: yaml.ResourceMeta{ 160 ObjectMeta: yaml.ObjectMeta{ 161 NameMeta: yaml.NameMeta{ 162 Name: subdir, 163 }, 164 }, 165 TypeMeta: yaml.TypeMeta{ 166 APIVersion: kptfilev1.TypeMeta.APIVersion, 167 Kind: kptfilev1.TypeMeta.Kind}, 168 }, 169 UpstreamLock: &kptfilev1.UpstreamLock{ 170 Type: "git", 171 Git: &kptfilev1.GitLock{ 172 Commit: commit, 173 Directory: subdir, 174 Ref: "refs/heads/master", 175 Repo: g.RepoDirectory, 176 }, 177 }, 178 Upstream: &kptfilev1.Upstream{ 179 Type: "git", 180 Git: &kptfilev1.Git{ 181 Directory: subdir, 182 Ref: "refs/heads/master", 183 Repo: g.RepoDirectory, 184 }, 185 UpdateStrategy: kptfilev1.ResourceMerge, 186 }, 187 }) 188 } 189 190 // TestCommand_Run_subdir_symlinks verifies Command will 191 // clone a subdirectory of a repo inside the subdirectory. 192 // 193 // - destination dir should match the name of the subdirectory 194 // - KptFile should have the subdir listed 195 // - Content outside the subdirectory should be ignored 196 // - symlinks inside the subdirectory should be ignored 197 func TestCommand_Run_subdir_symlinks(t *testing.T) { 198 subdir := JavaSubdir 199 g, w, clean := testutil.SetupRepoAndWorkspace(t, testutil.Content{ 200 Data: testutil.Dataset6, 201 Branch: "master", 202 }) 203 defer clean() 204 205 defer testutil.Chdir(t, w.WorkspaceDirectory)() 206 207 cliOutput := &bytes.Buffer{} 208 209 absPath := filepath.Join(w.WorkspaceDirectory, subdir) 210 err := Command{Git: &kptfilev1.Git{ 211 Repo: g.RepoDirectory, Ref: "refs/heads/master", Directory: subdir}, 212 Destination: absPath, 213 }.Run(fake.CtxWithPrinter(cliOutput, cliOutput)) 214 assert.NoError(t, err) 215 216 // ensure warning for symlink is printed on the CLI 217 assert.Contains(t, cliOutput.String(), `[Warn] Ignoring symlink "config-symlink"`) 218 219 // verify the cloned contents do not contains symlinks 220 diff, err := testutil.Diff(filepath.Join(g.DatasetDirectory, testutil.Dataset6, subdir), absPath, true) 221 assert.NoError(t, err) 222 diff = diff.Difference(testutil.KptfileSet) 223 // original repo contains symlink and cloned doesn't, so the difference 224 assert.Contains(t, diff.List(), "config-symlink") 225 226 // verify the KptFile contains the expected values 227 commit, err := g.GetCommit() 228 assert.NoError(t, err) 229 g.AssertKptfile(t, absPath, kptfilev1.KptFile{ 230 ResourceMeta: yaml.ResourceMeta{ 231 ObjectMeta: yaml.ObjectMeta{ 232 NameMeta: yaml.NameMeta{ 233 Name: subdir, 234 }, 235 }, 236 TypeMeta: yaml.TypeMeta{ 237 APIVersion: kptfilev1.TypeMeta.APIVersion, 238 Kind: kptfilev1.TypeMeta.Kind}, 239 }, 240 UpstreamLock: &kptfilev1.UpstreamLock{ 241 Type: "git", 242 Git: &kptfilev1.GitLock{ 243 Commit: commit, 244 Directory: subdir, 245 Ref: "refs/heads/master", 246 Repo: g.RepoDirectory, 247 }, 248 }, 249 Upstream: &kptfilev1.Upstream{ 250 Type: "git", 251 Git: &kptfilev1.Git{ 252 Directory: subdir, 253 Ref: "refs/heads/master", 254 Repo: g.RepoDirectory, 255 }, 256 UpdateStrategy: kptfilev1.ResourceMerge, 257 }, 258 }) 259 } 260 261 // TestCommand_Run_destination verifies Command clones the repo to a destination with a specific name rather 262 // than using the name of the source repo. 263 func TestCommand_Run_destination(t *testing.T) { 264 dest := "my-dataset" 265 g, w, clean := testutil.SetupRepoAndWorkspace(t, testutil.Content{ 266 Data: testutil.Dataset1, 267 Branch: "master", 268 }) 269 defer clean() 270 271 defer testutil.Chdir(t, w.WorkspaceDirectory)() 272 273 absPath := filepath.Join(w.WorkspaceDirectory, dest) 274 err := Command{ 275 Git: &kptfilev1.Git{ 276 Repo: g.RepoDirectory, 277 Ref: "master", 278 Directory: "/", 279 }, 280 Destination: absPath, 281 }.Run(fake.CtxWithDefaultPrinter()) 282 assert.NoError(t, err) 283 284 // verify the cloned contents matches the repository 285 g.AssertEqual(t, filepath.Join(g.DatasetDirectory, testutil.Dataset1), absPath, true) 286 287 // verify the KptFile contains the expected values 288 commit, err := g.GetCommit() 289 assert.NoError(t, err) 290 g.AssertKptfile(t, absPath, kptfilev1.KptFile{ 291 ResourceMeta: yaml.ResourceMeta{ 292 ObjectMeta: yaml.ObjectMeta{ 293 NameMeta: yaml.NameMeta{ 294 Name: dest, 295 }, 296 }, 297 TypeMeta: yaml.TypeMeta{ 298 APIVersion: kptfilev1.TypeMeta.APIVersion, 299 Kind: kptfilev1.TypeMeta.Kind}, 300 }, 301 UpstreamLock: &kptfilev1.UpstreamLock{ 302 Type: kptfilev1.GitOrigin, 303 Git: &kptfilev1.GitLock{ 304 Directory: "/", 305 Repo: g.RepoDirectory, 306 Ref: "master", 307 Commit: commit, 308 }, 309 }, 310 Upstream: &kptfilev1.Upstream{ 311 Type: kptfilev1.GitOrigin, 312 Git: &kptfilev1.Git{ 313 Directory: "/", 314 Repo: g.RepoDirectory, 315 Ref: "master", 316 }, 317 UpdateStrategy: kptfilev1.ResourceMerge, 318 }, 319 }) 320 } 321 322 // TestCommand_Run_subdirAndDestination verifies that Command will copy a subdirectory of a repo to a 323 // specific destination. 324 // 325 // - name of the destination is used over the name of the subdir in the KptFile 326 func TestCommand_Run_subdirAndDestination(t *testing.T) { 327 subdir := JavaSubdir 328 dest := "new-java" 329 g, w, clean := testutil.SetupRepoAndWorkspace(t, testutil.Content{ 330 Data: testutil.Dataset1, 331 Branch: "master", 332 }) 333 defer clean() 334 335 defer testutil.Chdir(t, w.WorkspaceDirectory)() 336 337 absPath := filepath.Join(w.WorkspaceDirectory, dest) 338 err := Command{ 339 Git: &kptfilev1.Git{ 340 Repo: g.RepoDirectory, 341 Ref: "master", 342 Directory: subdir, 343 }, 344 Destination: absPath, 345 }.Run(fake.CtxWithDefaultPrinter()) 346 assert.NoError(t, err) 347 348 // verify the cloned contents matches the repository 349 g.AssertEqual(t, filepath.Join(g.DatasetDirectory, testutil.Dataset1, subdir), absPath, true) 350 351 // verify the KptFile contains the expected values 352 commit, err := g.GetCommit() 353 assert.NoError(t, err) 354 g.AssertKptfile(t, absPath, kptfilev1.KptFile{ 355 ResourceMeta: yaml.ResourceMeta{ 356 ObjectMeta: yaml.ObjectMeta{ 357 NameMeta: yaml.NameMeta{ 358 Name: dest, 359 }, 360 }, 361 TypeMeta: yaml.TypeMeta{ 362 APIVersion: kptfilev1.TypeMeta.APIVersion, 363 Kind: kptfilev1.TypeMeta.Kind}, 364 }, 365 UpstreamLock: &kptfilev1.UpstreamLock{ 366 Type: kptfilev1.GitOrigin, 367 Git: &kptfilev1.GitLock{ 368 Commit: commit, 369 Directory: subdir, 370 Ref: "master", 371 Repo: g.RepoDirectory, 372 }, 373 }, 374 Upstream: &kptfilev1.Upstream{ 375 Type: kptfilev1.GitOrigin, 376 Git: &kptfilev1.Git{ 377 Directory: subdir, 378 Ref: "master", 379 Repo: g.RepoDirectory, 380 }, 381 UpdateStrategy: kptfilev1.ResourceMerge, 382 }, 383 }) 384 } 385 386 // TestCommand_Run_branch verifies Command can clone a git branch 387 // 388 // 1. create a new branch 389 // 2. add data to the branch 390 // 3. checkout the master branch again 391 // 4. clone the new branch 392 // 5. verify contents match the new branch 393 func TestCommand_Run_branch(t *testing.T) { 394 g, w, clean := testutil.SetupRepoAndWorkspace(t, testutil.Content{ 395 Data: testutil.Dataset1, 396 Branch: "master", 397 }) 398 defer clean() 399 400 defer testutil.Chdir(t, w.WorkspaceDirectory)() 401 402 // add commits to the exp branch 403 err := g.CheckoutBranch("exp", true) 404 assert.NoError(t, err) 405 err = g.ReplaceData(testutil.Dataset2) 406 assert.NoError(t, err) 407 _, err = g.Commit("new dataset") 408 assert.NoError(t, err) 409 commit, err := g.GetCommit() 410 assert.NoError(t, err) 411 err = g.CheckoutBranch("master", false) 412 assert.NoError(t, err) 413 commit2, err := g.GetCommit() 414 assert.NoError(t, err) 415 assert.NotEqual(t, commit, commit2) 416 417 absPath := filepath.Join(w.WorkspaceDirectory, g.RepoName) 418 err = Command{ 419 Git: &kptfilev1.Git{ 420 Repo: g.RepoDirectory, 421 Ref: "refs/heads/exp", 422 Directory: "/", 423 }, 424 Destination: absPath, 425 }.Run(fake.CtxWithDefaultPrinter()) 426 assert.NoError(t, err) 427 428 // verify the cloned contents matches the repository 429 g.AssertEqual(t, filepath.Join(g.DatasetDirectory, testutil.Dataset2), absPath, true) 430 431 // verify the KptFile contains the expected values 432 g.AssertKptfile(t, absPath, kptfilev1.KptFile{ 433 ResourceMeta: yaml.ResourceMeta{ 434 ObjectMeta: yaml.ObjectMeta{ 435 NameMeta: yaml.NameMeta{ 436 Name: g.RepoName, 437 }, 438 }, 439 TypeMeta: yaml.TypeMeta{ 440 APIVersion: kptfilev1.TypeMeta.APIVersion, 441 Kind: kptfilev1.TypeMeta.Kind}, 442 }, 443 UpstreamLock: &kptfilev1.UpstreamLock{ 444 Type: kptfilev1.GitOrigin, 445 Git: &kptfilev1.GitLock{ 446 Directory: "/", 447 Repo: g.RepoDirectory, 448 Ref: "refs/heads/exp", 449 Commit: commit, 450 }, 451 }, 452 Upstream: &kptfilev1.Upstream{ 453 Type: kptfilev1.GitOrigin, 454 Git: &kptfilev1.Git{ 455 Directory: "/", 456 Repo: g.RepoDirectory, 457 Ref: "refs/heads/exp", 458 }, 459 UpdateStrategy: kptfilev1.ResourceMerge, 460 }, 461 }) 462 } 463 464 // TestCommand_Run_tag verifies Command can clone from a git tag 465 // 466 // 1. add data to the master branch 467 // 2. commit and tag the master branch 468 // 3. add more data to the master branch, commit it 469 // 4. clone at the tag 470 // 5. verify the clone has the data from the tagged version 471 func TestCommand_Run_tag(t *testing.T) { 472 g, w, clean := testutil.SetupRepoAndWorkspace(t, testutil.Content{ 473 Data: testutil.Dataset1, 474 Branch: "master", 475 }) 476 defer clean() 477 478 defer testutil.Chdir(t, w.WorkspaceDirectory)() 479 480 // create a commit with dataset2 and tag it v2, then add another commit on top with dataset3 481 commit0, err := g.GetCommit() 482 assert.NoError(t, err) 483 err = g.ReplaceData(testutil.Dataset2) 484 assert.NoError(t, err) 485 _, err = g.Commit("new-data for v2") 486 assert.NoError(t, err) 487 commit, err := g.GetCommit() 488 assert.NoError(t, err) 489 err = g.Tag("v2") 490 assert.NoError(t, err) 491 err = g.ReplaceData(testutil.Dataset3) 492 assert.NoError(t, err) 493 _, err = g.Commit("new-data post-v2") 494 assert.NoError(t, err) 495 commit2, err := g.GetCommit() 496 assert.NoError(t, err) 497 assert.NotEqual(t, commit, commit0) 498 assert.NotEqual(t, commit, commit2) 499 500 absPath := filepath.Join(w.WorkspaceDirectory, g.RepoName) 501 err = Command{ 502 Git: &kptfilev1.Git{ 503 Repo: g.RepoDirectory, 504 Ref: "refs/tags/v2", 505 Directory: "/", 506 }, 507 Destination: absPath, 508 }.Run(fake.CtxWithDefaultPrinter()) 509 assert.NoError(t, err) 510 511 // verify the cloned contents matches the repository 512 g.AssertEqual(t, filepath.Join(g.DatasetDirectory, testutil.Dataset2), absPath, true) 513 514 // verify the KptFile contains the expected values 515 g.AssertKptfile(t, absPath, kptfilev1.KptFile{ 516 ResourceMeta: yaml.ResourceMeta{ 517 ObjectMeta: yaml.ObjectMeta{ 518 NameMeta: yaml.NameMeta{ 519 Name: g.RepoName, 520 }, 521 }, 522 TypeMeta: yaml.TypeMeta{ 523 APIVersion: kptfilev1.TypeMeta.APIVersion, 524 Kind: kptfilev1.TypeMeta.Kind}, 525 }, 526 UpstreamLock: &kptfilev1.UpstreamLock{ 527 Type: kptfilev1.GitOrigin, 528 Git: &kptfilev1.GitLock{ 529 Directory: "/", 530 Repo: g.RepoDirectory, 531 Ref: "refs/tags/v2", 532 Commit: commit, 533 }, 534 }, 535 Upstream: &kptfilev1.Upstream{ 536 Type: kptfilev1.GitOrigin, 537 Git: &kptfilev1.Git{ 538 Directory: "/", 539 Repo: g.RepoDirectory, 540 Ref: "refs/tags/v2", 541 }, 542 UpdateStrategy: kptfilev1.ResourceMerge, 543 }, 544 }) 545 } 546 547 func TestCommand_Run_ref(t *testing.T) { 548 testCases := map[string]struct { 549 reposContent map[string][]testutil.Content 550 directory string 551 ref func(repos map[string]*testutil.TestGitRepo) string 552 expected *pkgbuilder.RootPkg 553 }{ 554 "package tag": { 555 reposContent: map[string][]testutil.Content{ 556 testutil.Upstream: { 557 { 558 Pkg: pkgbuilder.NewRootPkg(). 559 WithSubPackages( 560 pkgbuilder.NewSubPkg("kafka"). 561 WithResource(pkgbuilder.DeploymentResource). 562 WithResource(pkgbuilder.SecretResource), 563 ), 564 Branch: "master", 565 Tag: "kafka/v2", 566 }, 567 { 568 Pkg: pkgbuilder.NewRootPkg(). 569 WithSubPackages( 570 pkgbuilder.NewSubPkg("kafka"). 571 WithResource(pkgbuilder.DeploymentResource). 572 WithResource(pkgbuilder.ConfigMapResource), 573 ), 574 Tag: "v2", 575 }, 576 }, 577 }, 578 directory: "kafka", 579 ref: func(_ map[string]*testutil.TestGitRepo) string { 580 return "v2" 581 }, 582 expected: pkgbuilder.NewRootPkg(). 583 WithKptfile( 584 pkgbuilder.NewKptfile(). 585 WithUpstreamRef(testutil.Upstream, "kafka", "v2", "resource-merge"). 586 WithUpstreamLockRef(testutil.Upstream, "kafka", "kafka/v2", 0), 587 ). 588 WithResource(pkgbuilder.DeploymentResource). 589 WithResource(pkgbuilder.SecretResource), 590 }, 591 "commit sha": { 592 reposContent: map[string][]testutil.Content{ 593 testutil.Upstream: { 594 { 595 Pkg: pkgbuilder.NewRootPkg(). 596 WithSubPackages( 597 pkgbuilder.NewSubPkg("kafka"). 598 WithResource(pkgbuilder.DeploymentResource). 599 WithResource(pkgbuilder.SecretResource), 600 ), 601 Branch: "master", 602 Tag: "kafka/v2", 603 }, 604 { 605 Pkg: pkgbuilder.NewRootPkg(). 606 WithSubPackages( 607 pkgbuilder.NewSubPkg("kafka"). 608 WithResource(pkgbuilder.DeploymentResource). 609 WithResource(pkgbuilder.ConfigMapResource), 610 ), 611 Tag: "v2", 612 }, 613 }, 614 }, 615 directory: "kafka", 616 ref: func(repos map[string]*testutil.TestGitRepo) string { 617 return repos[testutil.Upstream].Commits[0] 618 }, 619 expected: pkgbuilder.NewRootPkg(). 620 WithKptfile( 621 pkgbuilder.NewKptfile(). 622 WithUpstreamRef(testutil.Upstream, "kafka", "COMMIT-INDEX:0", "resource-merge"). 623 WithUpstreamLockRef(testutil.Upstream, "kafka", "COMMIT-INDEX:0", 0), 624 ). 625 WithResource(pkgbuilder.DeploymentResource). 626 WithResource(pkgbuilder.SecretResource), 627 }, 628 } 629 630 for tn, tc := range testCases { 631 t.Run(tn, func(t *testing.T) { 632 repos, w, clean := testutil.SetupReposAndWorkspace(t, tc.reposContent) 633 defer clean() 634 err := testutil.UpdateRepos(t, repos, tc.reposContent) 635 if !assert.NoError(t, err) { 636 t.FailNow() 637 } 638 639 ref := tc.ref(repos) 640 641 absPath := filepath.Join(w.WorkspaceDirectory, repos[testutil.Upstream].RepoName) 642 err = Command{ 643 Git: &kptfilev1.Git{ 644 Repo: repos[testutil.Upstream].RepoDirectory, 645 Ref: ref, 646 Directory: tc.directory, 647 }, 648 Destination: absPath, 649 }.Run(fake.CtxWithDefaultPrinter()) 650 assert.NoError(t, err) 651 652 expectedPath := tc.expected.ExpandPkgWithName(t, repos[testutil.Upstream].RepoName, testutil.ToReposInfo(repos)) 653 654 testutil.KptfileAwarePkgEqual(t, expectedPath, absPath, true) 655 }) 656 } 657 } 658 659 // TestCommand_Run_failExistingDir verifies that command will fail without changing anything if the 660 // directory already exists 661 func TestCommand_Run_failExistingDir(t *testing.T) { 662 g, w, clean := testutil.SetupRepoAndWorkspace(t, testutil.Content{ 663 Data: testutil.Dataset1, 664 Branch: "master", 665 }) 666 defer clean() 667 668 defer testutil.Chdir(t, w.WorkspaceDirectory)() 669 670 absPath := filepath.Join(w.WorkspaceDirectory, g.RepoName) 671 err := Command{ 672 Git: &kptfilev1.Git{ 673 Repo: g.RepoDirectory, 674 Ref: "master", 675 Directory: "/", 676 }, 677 Destination: absPath, 678 }.Run(fake.CtxWithDefaultPrinter()) 679 assert.NoError(t, err) 680 681 // verify the KptFile contains the expected values 682 commit, err := g.GetCommit() 683 assert.NoError(t, err) 684 685 // verify the cloned contents matches the repository 686 g.AssertEqual(t, filepath.Join(g.DatasetDirectory, testutil.Dataset1), absPath, true) 687 g.AssertKptfile(t, absPath, kptfilev1.KptFile{ 688 ResourceMeta: yaml.ResourceMeta{ 689 ObjectMeta: yaml.ObjectMeta{ 690 NameMeta: yaml.NameMeta{ 691 Name: g.RepoName, 692 }, 693 }, 694 TypeMeta: yaml.TypeMeta{ 695 APIVersion: kptfilev1.TypeMeta.APIVersion, 696 Kind: kptfilev1.TypeMeta.Kind}, 697 }, 698 UpstreamLock: &kptfilev1.UpstreamLock{ 699 Type: kptfilev1.GitOrigin, 700 Git: &kptfilev1.GitLock{ 701 Directory: "/", 702 Repo: g.RepoDirectory, 703 Ref: "master", 704 Commit: commit, // verify the commit matches the repo 705 }, 706 }, 707 Upstream: &kptfilev1.Upstream{ 708 Type: kptfilev1.GitOrigin, 709 Git: &kptfilev1.Git{ 710 Directory: "/", 711 Repo: g.RepoDirectory, 712 Ref: "master", 713 }, 714 UpdateStrategy: kptfilev1.ResourceMerge, 715 }, 716 }) 717 718 // update the data that would be cloned 719 err = g.ReplaceData(testutil.Dataset2) 720 assert.NoError(t, err) 721 _, err = g.Commit("new-data") 722 assert.NoError(t, err) 723 724 // try to clone and expect a failure 725 err = Command{ 726 Git: &kptfilev1.Git{ 727 Repo: g.RepoDirectory, 728 Ref: "master", 729 Directory: "/", 730 }, 731 Destination: absPath, 732 }.Run(fake.CtxWithDefaultPrinter()) 733 if !assert.Error(t, err) { 734 t.FailNow() 735 } 736 assert.Contains(t, err.Error(), "destination directory already exists") 737 738 // verify files are unchanged 739 g.AssertEqual(t, filepath.Join(g.DatasetDirectory, testutil.Dataset1), absPath, true) 740 g.AssertKptfile(t, absPath, kptfilev1.KptFile{ 741 ResourceMeta: yaml.ResourceMeta{ 742 ObjectMeta: yaml.ObjectMeta{ 743 NameMeta: yaml.NameMeta{ 744 Name: g.RepoName, 745 }, 746 }, 747 TypeMeta: yaml.TypeMeta{ 748 APIVersion: kptfilev1.TypeMeta.APIVersion, 749 Kind: kptfilev1.TypeMeta.Kind}, 750 }, 751 UpstreamLock: &kptfilev1.UpstreamLock{ 752 Type: kptfilev1.GitOrigin, 753 Git: &kptfilev1.GitLock{ 754 Directory: "/", 755 Repo: g.RepoDirectory, 756 Ref: "master", 757 Commit: commit, // verify the commit matches the repo 758 }, 759 }, 760 Upstream: &kptfilev1.Upstream{ 761 Type: kptfilev1.GitOrigin, 762 Git: &kptfilev1.Git{ 763 Directory: "/", 764 Repo: g.RepoDirectory, 765 Ref: "master", 766 }, 767 UpdateStrategy: kptfilev1.ResourceMerge, 768 }, 769 }) 770 } 771 772 func TestCommand_Run_nonexistingParentDir(t *testing.T) { 773 g, w, clean := testutil.SetupRepoAndWorkspace(t, testutil.Content{ 774 Data: testutil.Dataset1, 775 Branch: "master", 776 }) 777 defer clean() 778 779 defer testutil.Chdir(t, w.WorkspaceDirectory)() 780 781 absPath := filepath.Join(w.WorkspaceDirectory, "more", "dirs", g.RepoName) 782 err := Command{ 783 Git: &kptfilev1.Git{ 784 Repo: g.RepoDirectory, 785 Ref: "master", 786 Directory: "/", 787 }, 788 Destination: absPath, 789 }.Run(fake.CtxWithDefaultPrinter()) 790 assert.NoError(t, err) 791 g.AssertEqual(t, filepath.Join(g.DatasetDirectory, testutil.Dataset1), absPath, true) 792 } 793 794 func TestCommand_Run_failInvalidRepo(t *testing.T) { 795 _, w, clean := testutil.SetupRepoAndWorkspace(t, testutil.Content{ 796 Data: testutil.Dataset1, 797 Branch: "master", 798 }) 799 defer clean() 800 801 absPath := filepath.Join(w.WorkspaceDirectory, "foo") 802 err := Command{ 803 Git: &kptfilev1.Git{ 804 Repo: "foo", 805 Directory: "/", 806 Ref: "refs/heads/master", 807 }, 808 Destination: absPath, 809 }.Run(fake.CtxWithDefaultPrinter()) 810 if !assert.Error(t, err) { 811 t.FailNow() 812 } 813 if !assert.Contains(t, err.Error(), "'foo' does not appear to be a git repository") { 814 t.FailNow() 815 } 816 817 // Confirm destination directory no longer exists. 818 _, err = os.Stat(absPath) 819 if !assert.Error(t, err) { 820 t.FailNow() 821 } 822 } 823 824 func TestCommand_Run_failInvalidBranch(t *testing.T) { 825 g, w, clean := testutil.SetupRepoAndWorkspace(t, testutil.Content{ 826 Data: testutil.Dataset1, 827 Branch: "master", 828 }) 829 defer clean() 830 831 absPath := filepath.Join(w.WorkspaceDirectory, g.RepoDirectory) 832 err := Command{ 833 Git: &kptfilev1.Git{ 834 Repo: g.RepoDirectory, 835 Directory: "/", 836 Ref: "refs/heads/foo", 837 }, 838 Destination: absPath, 839 }.Run(fake.CtxWithDefaultPrinter()) 840 if !assert.Error(t, err) { 841 t.FailNow() 842 } 843 if !assert.Contains(t, err.Error(), "refs/heads/foo") { 844 t.FailNow() 845 } 846 if !assert.Contains(t, err.Error(), "exit status 128") { 847 t.FailNow() 848 } 849 850 // Confirm destination directory no longer exists. 851 _, err = os.Stat(absPath) 852 if !assert.Error(t, err) { 853 t.FailNow() 854 } 855 } 856 857 func TestCommand_Run_failInvalidTag(t *testing.T) { 858 g, w, clean := testutil.SetupRepoAndWorkspace(t, testutil.Content{ 859 Data: testutil.Dataset1, 860 Branch: "master", 861 }) 862 defer clean() 863 864 absPath := filepath.Join(w.WorkspaceDirectory, g.RepoDirectory) 865 err := Command{ 866 Git: &kptfilev1.Git{ 867 Repo: g.RepoDirectory, 868 Directory: "/", 869 Ref: "refs/tags/foo", 870 }, 871 Destination: absPath, 872 }.Run(fake.CtxWithDefaultPrinter()) 873 if !assert.Error(t, err) { 874 t.FailNow() 875 } 876 if !assert.Contains(t, err.Error(), "refs/tags/foo") { 877 t.FailNow() 878 } 879 if !assert.Contains(t, err.Error(), "exit status 128") { 880 t.FailNow() 881 } 882 883 // Confirm destination directory no longer exists. 884 _, err = os.Stat(absPath) 885 if !assert.Error(t, err) { 886 t.FailNow() 887 } 888 } 889 890 func TestCommand_Run_subpackages(t *testing.T) { 891 testCases := map[string]struct { 892 directory string 893 ref string 894 updateStrategy kptfilev1.UpdateStrategyType 895 reposContent map[string][]testutil.Content 896 expectedResult *pkgbuilder.RootPkg 897 expectedErrMsg string 898 }{ 899 "basic package without pipeline": { 900 directory: "/", 901 ref: "master", 902 reposContent: map[string][]testutil.Content{ 903 testutil.Upstream: { 904 { 905 Branch: "master", 906 Pkg: pkgbuilder.NewRootPkg(). 907 WithKptfile(). 908 WithResource(pkgbuilder.DeploymentResource), 909 }, 910 }, 911 }, 912 expectedResult: pkgbuilder.NewRootPkg(). 913 WithKptfile( 914 pkgbuilder.NewKptfile(). 915 WithUpstreamRef("upstream", "/", "master", "resource-merge"). 916 WithUpstreamLockRef("upstream", "/", "master", 0), 917 ). 918 WithResource(pkgbuilder.DeploymentResource), 919 }, 920 921 "basic package with non-KRM files": { 922 directory: "/", 923 ref: "master", 924 reposContent: map[string][]testutil.Content{ 925 testutil.Upstream: { 926 { 927 Branch: "master", 928 Pkg: pkgbuilder.NewRootPkg(). 929 WithKptfile(). 930 WithFile("foo.txt", `this is a test`), 931 }, 932 }, 933 }, 934 expectedResult: pkgbuilder.NewRootPkg(). 935 WithKptfile( 936 pkgbuilder.NewKptfile(). 937 WithUpstreamRef("upstream", "/", "master", "resource-merge"). 938 WithUpstreamLockRef("upstream", "/", "master", 0), 939 ). 940 WithFile("foo.txt", `this is a test`), 941 }, 942 "basic package with pipeline": { 943 directory: "/", 944 ref: "master", 945 reposContent: map[string][]testutil.Content{ 946 testutil.Upstream: { 947 { 948 Branch: "master", 949 Pkg: pkgbuilder.NewRootPkg(). 950 WithKptfile( 951 pkgbuilder.NewKptfile(). 952 WithPipeline( 953 pkgbuilder.NewFunction("gcr.io/kpt-dev/foo:latest"), 954 ), 955 ). 956 WithResource(pkgbuilder.DeploymentResource), 957 }, 958 }, 959 }, 960 expectedResult: pkgbuilder.NewRootPkg(). 961 WithKptfile( 962 pkgbuilder.NewKptfile(). 963 WithUpstreamRef("upstream", "/", "master", "resource-merge"). 964 WithUpstreamLockRef("upstream", "/", "master", 0). 965 WithPipeline( 966 pkgbuilder.NewFunction("gcr.io/kpt-dev/foo:latest"), 967 ), 968 ). 969 WithResource(pkgbuilder.DeploymentResource), 970 }, 971 "basic package with no Kptfile in upstream": { 972 directory: "/", 973 ref: "master", 974 reposContent: map[string][]testutil.Content{ 975 testutil.Upstream: { 976 { 977 Branch: "master", 978 Pkg: pkgbuilder.NewRootPkg(). 979 WithResource(pkgbuilder.DeploymentResource), 980 }, 981 }, 982 }, 983 expectedResult: pkgbuilder.NewRootPkg(). 984 WithKptfile( 985 pkgbuilder.NewKptfile(). 986 WithUpstreamRef("upstream", "/", "master", "resource-merge"). 987 WithUpstreamLockRef("upstream", "/", "master", 0), 988 ). 989 WithResource(pkgbuilder.DeploymentResource), 990 }, 991 "basic package with explicit update strategy": { 992 directory: "/", 993 ref: "master", 994 updateStrategy: kptfilev1.FastForward, 995 reposContent: map[string][]testutil.Content{ 996 testutil.Upstream: { 997 { 998 Branch: "master", 999 Pkg: pkgbuilder.NewRootPkg(). 1000 WithResource(pkgbuilder.DeploymentResource), 1001 }, 1002 }, 1003 }, 1004 expectedResult: pkgbuilder.NewRootPkg(). 1005 WithKptfile( 1006 pkgbuilder.NewKptfile(). 1007 WithUpstreamRef("upstream", "/", "master", "fast-forward"). 1008 WithUpstreamLockRef("upstream", "/", "master", 0), 1009 ). 1010 WithResource(pkgbuilder.DeploymentResource), 1011 }, 1012 "package with subpackages": { 1013 directory: "/", 1014 ref: "master", 1015 reposContent: map[string][]testutil.Content{ 1016 testutil.Upstream: { 1017 { 1018 Branch: "master", 1019 Pkg: pkgbuilder.NewRootPkg(). 1020 WithKptfile(). 1021 WithResource(pkgbuilder.DeploymentResource). 1022 WithSubPackages( 1023 pkgbuilder.NewSubPkg("subpkg"). 1024 WithKptfile(). 1025 WithResource(pkgbuilder.ConfigMapResource), 1026 ), 1027 }, 1028 }, 1029 }, 1030 expectedResult: pkgbuilder.NewRootPkg(). 1031 WithKptfile( 1032 pkgbuilder.NewKptfile(). 1033 WithUpstreamRef("upstream", "/", "master", "resource-merge"). 1034 WithUpstreamLockRef("upstream", "/", "master", 0), 1035 ). 1036 WithResource(pkgbuilder.DeploymentResource). 1037 WithSubPackages( 1038 pkgbuilder.NewSubPkg("subpkg"). 1039 WithKptfile(). 1040 WithResource(pkgbuilder.ConfigMapResource), 1041 ), 1042 }, 1043 "package with deeply nested subpackages": { 1044 directory: "/", 1045 ref: "master", 1046 reposContent: map[string][]testutil.Content{ 1047 testutil.Upstream: { 1048 { 1049 Branch: "master", 1050 Pkg: pkgbuilder.NewRootPkg(). 1051 WithKptfile(). 1052 WithResource(pkgbuilder.DeploymentResource). 1053 WithSubPackages( 1054 pkgbuilder.NewSubPkg("subpkg"). 1055 WithResource(pkgbuilder.ConfigMapResource). 1056 WithSubPackages( 1057 pkgbuilder.NewSubPkg("deepsubpkg"). 1058 WithKptfile( 1059 pkgbuilder.NewKptfile(). 1060 WithUpstreamRef("foo", "/", "main", "fast-forward"), 1061 ), 1062 ), 1063 ), 1064 }, 1065 }, 1066 "foo": { 1067 { 1068 Branch: "main", 1069 Pkg: pkgbuilder.NewRootPkg(). 1070 WithKptfile(). 1071 WithResource(pkgbuilder.SecretResource), 1072 }, 1073 }, 1074 }, 1075 expectedResult: pkgbuilder.NewRootPkg(). 1076 WithKptfile( 1077 pkgbuilder.NewKptfile(). 1078 WithUpstreamRef("upstream", "/", "master", "resource-merge"). 1079 WithUpstreamLockRef("upstream", "/", "master", 0), 1080 ). 1081 WithResource(pkgbuilder.DeploymentResource). 1082 WithSubPackages( 1083 pkgbuilder.NewSubPkg("subpkg"). 1084 WithResource(pkgbuilder.ConfigMapResource). 1085 WithSubPackages( 1086 pkgbuilder.NewSubPkg("deepsubpkg"). 1087 WithKptfile( 1088 pkgbuilder.NewKptfile(). 1089 WithUpstreamRef("foo", "/", "main", "fast-forward"). 1090 WithUpstreamLockRef("foo", "/", "main", 0), 1091 ). 1092 WithResource(pkgbuilder.SecretResource), 1093 ), 1094 ), 1095 }, 1096 "package with local and remote subpackages": { 1097 directory: "/", 1098 ref: "master", 1099 reposContent: map[string][]testutil.Content{ 1100 testutil.Upstream: { 1101 { 1102 Branch: "master", 1103 Pkg: pkgbuilder.NewRootPkg(). 1104 WithResource(pkgbuilder.DeploymentResource). 1105 WithSubPackages( 1106 pkgbuilder.NewSubPkg("subpkg"). 1107 WithResource(pkgbuilder.ConfigMapResource), 1108 pkgbuilder.NewSubPkg("foo"). 1109 WithKptfile( 1110 pkgbuilder.NewKptfile(). 1111 WithUpstreamRef("foo", "/", "main", "fast-forward"). 1112 WithUpstreamLockRef("foo", "/", "main", 0), 1113 ). 1114 WithResource(pkgbuilder.DeploymentResource). 1115 WithSubPackages( 1116 pkgbuilder.NewSubPkg("subpkg"). 1117 WithKptfile( 1118 pkgbuilder.NewKptfile(), 1119 ). 1120 WithResource(pkgbuilder.ConfigMapResource). 1121 WithSubPackages( 1122 pkgbuilder.NewSubPkg("bar"). 1123 WithKptfile( 1124 pkgbuilder.NewKptfile(). 1125 WithUpstreamRef("bar", "/", "main", "fast-forward"). 1126 WithUpstreamLockRef("bar", "/", "main", 0), 1127 ).WithResource(pkgbuilder.DeploymentResource), 1128 ), 1129 ), 1130 ), 1131 }, 1132 }, 1133 "foo": { 1134 { 1135 Pkg: pkgbuilder.NewRootPkg(). 1136 WithKptfile(). 1137 WithResource(pkgbuilder.DeploymentResource). 1138 WithSubPackages( 1139 pkgbuilder.NewSubPkg("subpkg"). 1140 WithKptfile( 1141 pkgbuilder.NewKptfile(), 1142 ). 1143 WithResource(pkgbuilder.ConfigMapResource). 1144 WithSubPackages( 1145 pkgbuilder.NewSubPkg("bar"). 1146 WithKptfile( 1147 pkgbuilder.NewKptfile(). 1148 WithUpstreamRef("bar", "/", "main", "fast-forward"). 1149 WithUpstreamLockRef("bar", "/", "main", 0), 1150 ). 1151 WithResource(pkgbuilder.DeploymentResource), 1152 ), 1153 ), 1154 }, 1155 }, 1156 "bar": { 1157 { 1158 Pkg: pkgbuilder.NewRootPkg(). 1159 WithKptfile(). 1160 WithResource(pkgbuilder.DeploymentResource), 1161 }, 1162 }, 1163 }, 1164 expectedResult: pkgbuilder.NewRootPkg(). 1165 WithKptfile( 1166 pkgbuilder.NewKptfile(). 1167 WithUpstreamRef("upstream", "/", "master", "resource-merge"). 1168 WithUpstreamLockRef("upstream", "/", "master", 0), 1169 ). 1170 WithResource(pkgbuilder.DeploymentResource). 1171 WithSubPackages( 1172 pkgbuilder.NewSubPkg("foo"). 1173 WithKptfile( 1174 pkgbuilder.NewKptfile(). 1175 WithUpstreamRef("foo", "/", "main", "fast-forward"). 1176 WithUpstreamLockRef("foo", "/", "main", 0), 1177 ). 1178 WithResource(pkgbuilder.DeploymentResource). 1179 WithSubPackages( 1180 pkgbuilder.NewSubPkg("subpkg"). 1181 WithKptfile( 1182 pkgbuilder.NewKptfile(), 1183 ). 1184 WithResource(pkgbuilder.ConfigMapResource). 1185 WithSubPackages( 1186 pkgbuilder.NewSubPkg("bar"). 1187 WithKptfile( 1188 pkgbuilder.NewKptfile(). 1189 WithUpstreamRef("bar", "/", "main", "fast-forward"). 1190 WithUpstreamLockRef("bar", "/", "main", 0), 1191 ). 1192 WithResource(pkgbuilder.DeploymentResource), 1193 ), 1194 ), 1195 pkgbuilder.NewSubPkg("subpkg"). 1196 WithResource(pkgbuilder.ConfigMapResource), 1197 ), 1198 }, 1199 "fetch subpackage on a different branch than master": { 1200 directory: "/bar", 1201 ref: "main", 1202 reposContent: map[string][]testutil.Content{ 1203 testutil.Upstream: { 1204 { 1205 Branch: "main", 1206 Pkg: pkgbuilder.NewRootPkg(). 1207 WithKptfile(). 1208 WithResource(pkgbuilder.DeploymentResource). 1209 WithSubPackages( 1210 pkgbuilder.NewSubPkg("bar"). 1211 WithKptfile(). 1212 WithResource(pkgbuilder.ConfigMapResource), 1213 pkgbuilder.NewSubPkg("foo"). 1214 WithKptfile( 1215 pkgbuilder.NewKptfile(). 1216 WithUpstreamRef("foo", "/subpkg", "v1.2", "fast-forward"), 1217 ), 1218 ), 1219 }, 1220 }, 1221 "foo": { 1222 { 1223 Pkg: pkgbuilder.NewRootPkg(). 1224 WithKptfile(). 1225 WithResource(pkgbuilder.DeploymentResource), 1226 }, 1227 }, 1228 }, 1229 expectedResult: pkgbuilder.NewRootPkg(). 1230 WithKptfile( 1231 pkgbuilder.NewKptfile(). 1232 WithUpstreamRef("upstream", "/bar", "main", "resource-merge"). 1233 WithUpstreamLockRef("upstream", "/bar", "main", 0), 1234 ). 1235 WithResource(pkgbuilder.ConfigMapResource), 1236 }, 1237 "package with unfetched remote subpackage with a tag reference": { 1238 directory: "/", 1239 ref: "main", 1240 reposContent: map[string][]testutil.Content{ 1241 testutil.Upstream: { 1242 { 1243 Branch: "main", 1244 Pkg: pkgbuilder.NewRootPkg(). 1245 WithResource(pkgbuilder.DeploymentResource). 1246 WithSubPackages( 1247 pkgbuilder.NewSubPkg("bar"). 1248 WithKptfile(). 1249 WithResource(pkgbuilder.ConfigMapResource), 1250 pkgbuilder.NewSubPkg("foo"). 1251 WithKptfile( 1252 pkgbuilder.NewKptfile(). 1253 WithUpstreamRef("foo", "/subpkg", "v1.2", "fast-forward"), 1254 ), 1255 ), 1256 }, 1257 }, 1258 "foo": { 1259 { 1260 Branch: "master", 1261 Pkg: pkgbuilder.NewRootPkg(). 1262 WithKptfile(). 1263 WithResource(pkgbuilder.ConfigMapResource), 1264 }, 1265 { 1266 Pkg: pkgbuilder.NewRootPkg(). 1267 WithKptfile(). 1268 WithResource(pkgbuilder.ConfigMapResource). 1269 WithSubPackages( 1270 pkgbuilder.NewSubPkg("subpkg"). 1271 WithKptfile(). 1272 WithResource(pkgbuilder.DeploymentResource), 1273 ), 1274 Tag: "v1.2", 1275 Branch: "master", 1276 }, 1277 }, 1278 }, 1279 expectedResult: pkgbuilder.NewRootPkg(). 1280 WithKptfile( 1281 pkgbuilder.NewKptfile(). 1282 WithUpstreamRef("upstream", "/", "main", "resource-merge"). 1283 WithUpstreamLockRef("upstream", "/", "main", 0), 1284 ). 1285 WithResource(pkgbuilder.DeploymentResource). 1286 WithSubPackages( 1287 pkgbuilder.NewSubPkg("bar"). 1288 WithKptfile(). 1289 WithResource(pkgbuilder.ConfigMapResource), 1290 pkgbuilder.NewSubPkg("foo"). 1291 WithKptfile( 1292 pkgbuilder.NewKptfile(). 1293 WithUpstreamRef("foo", "/subpkg", "v1.2", "fast-forward"). 1294 WithUpstreamLockRef("foo", "/subpkg", "v1.2", 1), 1295 ). 1296 WithResource(pkgbuilder.DeploymentResource), 1297 ), 1298 }, 1299 "same unfetched remote subpackage referenced multiple times": { 1300 directory: "/", 1301 ref: "master", 1302 reposContent: map[string][]testutil.Content{ 1303 testutil.Upstream: { 1304 { 1305 Branch: "master", 1306 Pkg: pkgbuilder.NewRootPkg(). 1307 WithSubPackages( 1308 pkgbuilder.NewSubPkg("foo-sub"). 1309 WithKptfile( 1310 pkgbuilder.NewKptfile(). 1311 WithUpstreamRef("foo", "/subpkg", "subpkg/v1.2", "fast-forward"), 1312 ), 1313 pkgbuilder.NewSubPkg("foo-root"). 1314 WithKptfile( 1315 pkgbuilder.NewKptfile(). 1316 WithUpstreamRef("foo", "/", "master", "fast-forward"), 1317 ), 1318 ), 1319 }, 1320 }, 1321 "foo": { 1322 { 1323 Branch: "master", 1324 Pkg: pkgbuilder.NewRootPkg(). 1325 WithKptfile(). 1326 WithResource(pkgbuilder.ConfigMapResource), 1327 }, 1328 { 1329 Pkg: pkgbuilder.NewRootPkg(). 1330 WithKptfile(). 1331 WithResource(pkgbuilder.ConfigMapResource). 1332 WithSubPackages( 1333 pkgbuilder.NewSubPkg("subpkg"). 1334 WithKptfile(). 1335 WithResource(pkgbuilder.DeploymentResource), 1336 ), 1337 Tag: "subpkg/v1.2", 1338 }, 1339 }, 1340 }, 1341 expectedResult: pkgbuilder.NewRootPkg(). 1342 WithKptfile( 1343 pkgbuilder.NewKptfile(). 1344 WithUpstreamRef("upstream", "/", "master", "resource-merge"). 1345 WithUpstreamLockRef("upstream", "/", "master", 0), 1346 ). 1347 WithSubPackages( 1348 pkgbuilder.NewSubPkg("foo-sub"). 1349 WithKptfile( 1350 pkgbuilder.NewKptfile(). 1351 WithUpstreamRef("foo", "/subpkg", "subpkg/v1.2", "fast-forward"). 1352 WithUpstreamLockRef("foo", "/subpkg", "subpkg/v1.2", 1), 1353 ). 1354 WithResource(pkgbuilder.DeploymentResource), 1355 pkgbuilder.NewSubPkg("foo-root"). 1356 WithKptfile( 1357 pkgbuilder.NewKptfile(). 1358 WithUpstreamRef("foo", "/", "master", "fast-forward"). 1359 WithUpstreamLockRef("foo", "/", "master", 1), 1360 ). 1361 WithResource(pkgbuilder.ConfigMapResource). 1362 WithSubPackages( 1363 pkgbuilder.NewSubPkg("subpkg"). 1364 WithKptfile(). 1365 WithResource(pkgbuilder.DeploymentResource), 1366 ), 1367 ), 1368 }, 1369 } 1370 1371 for tn, tc := range testCases { 1372 t.Run(tn, func(t *testing.T) { 1373 repos, w, clean := testutil.SetupReposAndWorkspace(t, tc.reposContent) 1374 defer clean() 1375 upstreamRepo := repos[testutil.Upstream] 1376 err := testutil.UpdateRepos(t, repos, tc.reposContent) 1377 if !assert.NoError(t, err) { 1378 t.FailNow() 1379 } 1380 1381 var targetDir string 1382 if tc.directory == "/" { 1383 targetDir = filepath.Base(upstreamRepo.RepoName) 1384 } else { 1385 targetDir = filepath.Base(tc.directory) 1386 } 1387 w.PackageDir = targetDir 1388 destinationDir := filepath.Join(w.WorkspaceDirectory, targetDir) 1389 1390 err = Command{ 1391 Git: &kptfilev1.Git{ 1392 Repo: upstreamRepo.RepoDirectory, 1393 Directory: tc.directory, 1394 Ref: tc.ref, 1395 }, 1396 Destination: destinationDir, 1397 UpdateStrategy: tc.updateStrategy, 1398 }.Run(fake.CtxWithDefaultPrinter()) 1399 1400 if tc.expectedErrMsg != "" { 1401 if !assert.Error(t, err) { 1402 t.FailNow() 1403 } 1404 assert.Contains(t, err.Error(), tc.expectedErrMsg) 1405 return 1406 } 1407 1408 if !assert.NoError(t, err) { 1409 t.FailNow() 1410 } 1411 1412 // Format the Kptfiles so we can diff the output without 1413 // formatting issues. 1414 rw := &kio.LocalPackageReadWriter{ 1415 NoDeleteFiles: true, 1416 PackagePath: w.FullPackagePath(), 1417 MatchFilesGlob: []string{kptfilev1.KptFileName}, 1418 PreserveSeqIndent: true, 1419 WrapBareSeqNode: true, 1420 } 1421 err = kio.Pipeline{ 1422 Inputs: []kio.Reader{rw}, 1423 Filters: []kio.Filter{filters.FormatFilter{}}, 1424 Outputs: []kio.Writer{rw}, 1425 }.Execute() 1426 if !assert.NoError(t, err) { 1427 t.FailNow() 1428 } 1429 1430 expectedPath := tc.expectedResult.ExpandPkgWithName(t, targetDir, testutil.ToReposInfo(repos)) 1431 testutil.KptfileAwarePkgEqual(t, expectedPath, w.FullPackagePath(), true) 1432 }) 1433 } 1434 } 1435 1436 func TestCommand_Run_symlinks(t *testing.T) { 1437 repos, w, clean := testutil.SetupReposAndWorkspace(t, map[string][]testutil.Content{ 1438 testutil.Upstream: { 1439 { 1440 Branch: "master", 1441 Pkg: pkgbuilder.NewRootPkg(). 1442 WithKptfile(). 1443 WithResource(pkgbuilder.DeploymentResource). 1444 WithSubPackages( 1445 pkgbuilder.NewSubPkg("subpkg"). 1446 WithKptfile(). 1447 WithResource(pkgbuilder.ConfigMapResource), 1448 ), 1449 UpdateFunc: func(path string) error { 1450 // Create symlink in the upstream repo. 1451 return os.Symlink(filepath.Join(path, "subpkg"), 1452 filepath.Join(path, "subpkg-sym")) 1453 }, 1454 }, 1455 }, 1456 }) 1457 defer clean() 1458 upstreamRepo := repos[testutil.Upstream] 1459 1460 destinationDir := filepath.Join(w.WorkspaceDirectory, upstreamRepo.RepoName) 1461 err := Command{ 1462 Git: &kptfilev1.Git{ 1463 Repo: upstreamRepo.RepoDirectory, 1464 Directory: "/", 1465 Ref: "master", 1466 }, 1467 Destination: destinationDir, 1468 }.Run(fake.CtxWithDefaultPrinter()) 1469 if !assert.NoError(t, err) { 1470 t.FailNow() 1471 } 1472 w.PackageDir = upstreamRepo.RepoName 1473 1474 expectedPkg := pkgbuilder.NewRootPkg(). 1475 WithKptfile( 1476 pkgbuilder.NewKptfile(). 1477 WithUpstreamRef(testutil.Upstream, "/", "master", "resource-merge"). 1478 WithUpstreamLockRef(testutil.Upstream, "/", "master", 0), 1479 ). 1480 WithResource(pkgbuilder.DeploymentResource). 1481 WithSubPackages( 1482 pkgbuilder.NewSubPkg("subpkg"). 1483 WithKptfile(). 1484 WithResource(pkgbuilder.ConfigMapResource), 1485 ) 1486 expectedPath := expectedPkg.ExpandPkgWithName(t, upstreamRepo.RepoName, testutil.ToReposInfo(repos)) 1487 1488 testutil.KptfileAwarePkgEqual(t, expectedPath, w.FullPackagePath(), true) 1489 }