github.com/YousefHaggyHeroku/pack@v1.5.5/internal/builder/builder_test.go (about) 1 package builder_test 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io/ioutil" 8 "os" 9 "path" 10 "path/filepath" 11 "testing" 12 13 "github.com/buildpacks/imgutil" 14 "github.com/buildpacks/imgutil/fakes" 15 "github.com/buildpacks/lifecycle/api" 16 "github.com/golang/mock/gomock" 17 "github.com/heroku/color" 18 "github.com/sclevine/spec" 19 "github.com/sclevine/spec/report" 20 21 pubbldr "github.com/YousefHaggyHeroku/pack/builder" 22 "github.com/YousefHaggyHeroku/pack/internal/archive" 23 "github.com/YousefHaggyHeroku/pack/internal/builder" 24 "github.com/YousefHaggyHeroku/pack/internal/builder/testmocks" 25 "github.com/YousefHaggyHeroku/pack/internal/dist" 26 ifakes "github.com/YousefHaggyHeroku/pack/internal/fakes" 27 ilogging "github.com/YousefHaggyHeroku/pack/internal/logging" 28 "github.com/YousefHaggyHeroku/pack/logging" 29 h "github.com/YousefHaggyHeroku/pack/testhelpers" 30 ) 31 32 func TestBuilder(t *testing.T) { 33 color.Disable(true) 34 defer color.Disable(false) 35 spec.Run(t, "Builder", testBuilder, spec.Parallel(), spec.Report(report.Terminal{})) 36 } 37 38 func testBuilder(t *testing.T, when spec.G, it spec.S) { 39 var ( 40 baseImage *fakes.Image 41 subject *builder.Builder 42 mockController *gomock.Controller 43 mockLifecycle *testmocks.MockLifecycle 44 bp1v1 dist.Buildpack 45 bp1v2 dist.Buildpack 46 bp2v1 dist.Buildpack 47 bpOrder dist.Buildpack 48 outBuf bytes.Buffer 49 logger logging.Logger 50 ) 51 52 it.Before(func() { 53 logger = ilogging.NewLogWithWriters(&outBuf, &outBuf) 54 baseImage = fakes.NewImage("base/image", "", nil) 55 mockController = gomock.NewController(t) 56 57 lifecycleTarReader := archive.ReadDirAsTar( 58 filepath.Join("testdata", "lifecycle", "platform-0.4"), 59 ".", 0, 0, 0755, true, nil, 60 ) 61 62 descriptorContents, err := ioutil.ReadFile(filepath.Join("testdata", "lifecycle", "platform-0.4", "lifecycle.toml")) 63 h.AssertNil(t, err) 64 65 lifecycleDescriptor, err := builder.ParseDescriptor(string(descriptorContents)) 66 h.AssertNil(t, err) 67 68 mockLifecycle = testmocks.NewMockLifecycle(mockController) 69 mockLifecycle.EXPECT().Open().Return(lifecycleTarReader, nil).AnyTimes() 70 mockLifecycle.EXPECT().Descriptor().Return(builder.CompatDescriptor(lifecycleDescriptor)).AnyTimes() 71 72 bp1v1, err = ifakes.NewFakeBuildpack(dist.BuildpackDescriptor{ 73 API: api.MustParse("0.2"), 74 Info: dist.BuildpackInfo{ 75 ID: "buildpack-1-id", 76 Version: "buildpack-1-version-1", 77 }, 78 Stacks: []dist.Stack{{ 79 ID: "some.stack.id", 80 Mixins: []string{"mixinX", "mixinY"}, 81 }}, 82 }, 0644) 83 h.AssertNil(t, err) 84 85 bp1v2, err = ifakes.NewFakeBuildpack(dist.BuildpackDescriptor{ 86 API: api.MustParse("0.2"), 87 Info: dist.BuildpackInfo{ 88 ID: "buildpack-1-id", 89 Version: "buildpack-1-version-2", 90 }, 91 Stacks: []dist.Stack{{ 92 ID: "some.stack.id", 93 Mixins: []string{"mixinX", "mixinY"}, 94 }}, 95 }, 0644) 96 h.AssertNil(t, err) 97 98 bp2v1, err = ifakes.NewFakeBuildpack(dist.BuildpackDescriptor{ 99 API: api.MustParse("0.2"), 100 Info: dist.BuildpackInfo{ 101 ID: "buildpack-2-id", 102 Version: "buildpack-2-version-1", 103 }, 104 Stacks: []dist.Stack{{ 105 ID: "some.stack.id", 106 Mixins: []string{"build:mixinA", "run:mixinB"}, 107 }}, 108 }, 0644) 109 h.AssertNil(t, err) 110 111 bpOrder, err = ifakes.NewFakeBuildpack(dist.BuildpackDescriptor{ 112 API: api.MustParse("0.2"), 113 Info: dist.BuildpackInfo{ 114 ID: "order-buildpack-id", 115 Version: "order-buildpack-version", 116 }, 117 Order: []dist.OrderEntry{{ 118 Group: []dist.BuildpackRef{ 119 { 120 BuildpackInfo: bp1v1.Descriptor().Info, 121 Optional: true, 122 }, 123 { 124 BuildpackInfo: bp2v1.Descriptor().Info, 125 Optional: false, 126 }, 127 }, 128 }}, 129 }, 0644) 130 h.AssertNil(t, err) 131 }) 132 133 it.After(func() { 134 baseImage.Cleanup() 135 mockController.Finish() 136 }) 137 138 when("the base image is not valid", func() { 139 when("#FromImage", func() { 140 when("metadata isn't valid", func() { 141 it("returns an error", func() { 142 h.AssertNil(t, baseImage.SetLabel( 143 "io.buildpacks.builder.metadata", 144 `{"something-random": ,}`, 145 )) 146 147 _, err := builder.FromImage(baseImage) 148 h.AssertError(t, err, "getting label") 149 }) 150 }) 151 }) 152 153 when("#New", func() { 154 when("metadata isn't valid", func() { 155 it("returns an error", func() { 156 h.AssertNil(t, baseImage.SetLabel( 157 "io.buildpacks.builder.metadata", 158 `{"something-random": ,}`, 159 )) 160 161 _, err := builder.FromImage(baseImage) 162 h.AssertError(t, err, "getting label") 163 }) 164 }) 165 166 when("missing CNB_USER_ID", func() { 167 it("returns an error", func() { 168 _, err := builder.New(baseImage, "some/builder") 169 h.AssertError(t, err, "image 'base/image' missing required env var 'CNB_USER_ID'") 170 }) 171 }) 172 173 when("missing CNB_GROUP_ID", func() { 174 it.Before(func() { 175 h.AssertNil(t, baseImage.SetEnv("CNB_USER_ID", "1234")) 176 }) 177 178 it("returns an error", func() { 179 _, err := builder.New(baseImage, "some/builder") 180 h.AssertError(t, err, "image 'base/image' missing required env var 'CNB_GROUP_ID'") 181 }) 182 }) 183 184 when("CNB_USER_ID is not an int", func() { 185 it.Before(func() { 186 h.AssertNil(t, baseImage.SetEnv("CNB_USER_ID", "not an int")) 187 h.AssertNil(t, baseImage.SetEnv("CNB_GROUP_ID", "4321")) 188 }) 189 190 it("returns an error", func() { 191 _, err := builder.New(baseImage, "some/builder") 192 h.AssertError(t, err, "failed to parse 'CNB_USER_ID', value 'not an int' should be an integer") 193 }) 194 }) 195 196 when("CNB_GROUP_ID is not an int", func() { 197 it.Before(func() { 198 h.AssertNil(t, baseImage.SetEnv("CNB_USER_ID", "1234")) 199 h.AssertNil(t, baseImage.SetEnv("CNB_GROUP_ID", "not an int")) 200 }) 201 202 it("returns an error", func() { 203 _, err := builder.New(baseImage, "some/builder") 204 h.AssertError(t, err, "failed to parse 'CNB_GROUP_ID', value 'not an int' should be an integer") 205 }) 206 }) 207 208 when("missing stack id label", func() { 209 it.Before(func() { 210 h.AssertNil(t, baseImage.SetEnv("CNB_USER_ID", "1234")) 211 h.AssertNil(t, baseImage.SetEnv("CNB_GROUP_ID", "4321")) 212 }) 213 214 it("returns an error", func() { 215 _, err := builder.New(baseImage, "some/builder") 216 h.AssertError(t, err, "image 'base/image' missing label 'io.buildpacks.stack.id'") 217 }) 218 }) 219 220 when("mixins metadata is malformed", func() { 221 it.Before(func() { 222 h.AssertNil(t, baseImage.SetEnv("CNB_USER_ID", "1234")) 223 h.AssertNil(t, baseImage.SetEnv("CNB_GROUP_ID", "4321")) 224 h.AssertNil(t, baseImage.SetLabel("io.buildpacks.stack.id", "some-id")) 225 }) 226 227 it("returns an error", func() { 228 h.AssertNil(t, baseImage.SetLabel("io.buildpacks.stack.mixins", `{"mixinX", "mixinY", "build:mixinA"}`)) 229 _, err := builder.New(baseImage, "some/builder") 230 h.AssertError(t, err, "getting label io.buildpacks.stack.mixins") 231 }) 232 }) 233 234 when("order metadata is malformed", func() { 235 it.Before(func() { 236 h.AssertNil(t, baseImage.SetEnv("CNB_USER_ID", "1234")) 237 h.AssertNil(t, baseImage.SetEnv("CNB_GROUP_ID", "4321")) 238 h.AssertNil(t, baseImage.SetLabel("io.buildpacks.stack.id", "some-id")) 239 }) 240 241 it("returns an error", func() { 242 h.AssertNil(t, baseImage.SetLabel("io.buildpacks.buildpack.order", `{"something", }`)) 243 _, err := builder.New(baseImage, "some/builder") 244 h.AssertError(t, err, "getting label io.buildpacks.buildpack.order") 245 }) 246 }) 247 }) 248 }) 249 250 when("the base image is a valid build image", func() { 251 it.Before(func() { 252 var err error 253 h.AssertNil(t, baseImage.SetEnv("CNB_USER_ID", "1234")) 254 h.AssertNil(t, baseImage.SetEnv("CNB_GROUP_ID", "4321")) 255 h.AssertNil(t, baseImage.SetLabel("io.buildpacks.stack.id", "some.stack.id")) 256 h.AssertNil(t, baseImage.SetLabel("io.buildpacks.stack.mixins", `["mixinX", "mixinY", "build:mixinA"]`)) 257 subject, err = builder.New(baseImage, "some/builder") 258 h.AssertNil(t, err) 259 260 subject.SetLifecycle(mockLifecycle) 261 }) 262 263 it.After(func() { 264 baseImage.Cleanup() 265 }) 266 267 when("#Save", func() { 268 it("creates a builder from the image and renames it", func() { 269 h.AssertNil(t, subject.Save(logger, builder.CreatorMetadata{})) 270 h.AssertEq(t, baseImage.IsSaved(), true) 271 h.AssertEq(t, baseImage.Name(), "some/builder") 272 }) 273 274 it("adds creator metadata", func() { 275 testName := "test-name" 276 testVersion := "1.2.5" 277 h.AssertNil(t, subject.Save(logger, builder.CreatorMetadata{ 278 Name: testName, 279 Version: testVersion, 280 })) 281 h.AssertEq(t, baseImage.IsSaved(), true) 282 283 label, err := baseImage.Label("io.buildpacks.builder.metadata") 284 h.AssertNil(t, err) 285 286 var metadata builder.Metadata 287 h.AssertNil(t, json.Unmarshal([]byte(label), &metadata)) 288 289 h.AssertEq(t, metadata.CreatedBy.Name, testName) 290 h.AssertEq(t, metadata.CreatedBy.Version, testVersion) 291 }) 292 293 it("adds creator name if not provided", func() { 294 testVersion := "1.2.5" 295 h.AssertNil(t, subject.Save(logger, builder.CreatorMetadata{ 296 Version: testVersion, 297 })) 298 h.AssertEq(t, baseImage.IsSaved(), true) 299 300 label, err := baseImage.Label("io.buildpacks.builder.metadata") 301 h.AssertNil(t, err) 302 303 var metadata builder.Metadata 304 h.AssertNil(t, json.Unmarshal([]byte(label), &metadata)) 305 306 h.AssertEq(t, metadata.CreatedBy.Name, "Pack CLI") 307 h.AssertEq(t, metadata.CreatedBy.Version, testVersion) 308 }) 309 310 it("creates the workspace dir with CNB user and group", func() { 311 h.AssertNil(t, subject.Save(logger, builder.CreatorMetadata{})) 312 h.AssertEq(t, baseImage.IsSaved(), true) 313 314 layerTar, err := baseImage.FindLayerWithPath("/workspace") 315 h.AssertNil(t, err) 316 h.AssertOnTarEntry(t, layerTar, "/workspace", 317 h.IsDirectory(), 318 h.HasFileMode(0755), 319 h.HasOwnerAndGroup(1234, 4321), 320 h.HasModTime(archive.NormalizedDateTime), 321 ) 322 }) 323 324 it("creates the layers dir with CNB user and group", func() { 325 h.AssertNil(t, subject.Save(logger, builder.CreatorMetadata{})) 326 h.AssertEq(t, baseImage.IsSaved(), true) 327 328 layerTar, err := baseImage.FindLayerWithPath("/layers") 329 h.AssertNil(t, err) 330 h.AssertOnTarEntry(t, layerTar, "/layers", 331 h.IsDirectory(), 332 h.HasOwnerAndGroup(1234, 4321), 333 h.HasFileMode(0755), 334 h.HasModTime(archive.NormalizedDateTime), 335 ) 336 }) 337 338 it("creates the cnb dir", func() { 339 h.AssertNil(t, subject.Save(logger, builder.CreatorMetadata{})) 340 h.AssertEq(t, baseImage.IsSaved(), true) 341 342 layerTar, err := baseImage.FindLayerWithPath("/cnb") 343 h.AssertNil(t, err) 344 h.AssertOnTarEntry(t, layerTar, "/cnb", 345 h.IsDirectory(), 346 h.HasOwnerAndGroup(0, 0), 347 h.HasFileMode(0755), 348 h.HasModTime(archive.NormalizedDateTime), 349 ) 350 }) 351 352 it("creates the buildpacks dir", func() { 353 h.AssertNil(t, subject.Save(logger, builder.CreatorMetadata{})) 354 h.AssertEq(t, baseImage.IsSaved(), true) 355 356 layerTar, err := baseImage.FindLayerWithPath("/cnb/buildpacks") 357 h.AssertNil(t, err) 358 h.AssertOnTarEntry(t, layerTar, "/cnb/buildpacks", 359 h.IsDirectory(), 360 h.HasOwnerAndGroup(0, 0), 361 h.HasFileMode(0755), 362 h.HasModTime(archive.NormalizedDateTime), 363 ) 364 }) 365 366 it("creates the platform dir", func() { 367 h.AssertNil(t, subject.Save(logger, builder.CreatorMetadata{})) 368 h.AssertEq(t, baseImage.IsSaved(), true) 369 370 layerTar, err := baseImage.FindLayerWithPath("/platform") 371 h.AssertNil(t, err) 372 h.AssertOnTarEntry(t, layerTar, "/platform", 373 h.IsDirectory(), 374 h.HasOwnerAndGroup(0, 0), 375 h.HasFileMode(0755), 376 h.HasModTime(archive.NormalizedDateTime), 377 ) 378 h.AssertOnTarEntry(t, layerTar, "/platform/env", 379 h.IsDirectory(), 380 h.HasOwnerAndGroup(0, 0), 381 h.HasFileMode(0755), 382 h.HasModTime(archive.NormalizedDateTime), 383 ) 384 }) 385 386 it("sets the working dir to the layers dir", func() { 387 h.AssertNil(t, subject.Save(logger, builder.CreatorMetadata{})) 388 h.AssertEq(t, baseImage.IsSaved(), true) 389 390 h.AssertEq(t, baseImage.WorkingDir(), "/layers") 391 }) 392 393 it("does not overwrite the order layer when SetOrder has not been called", func() { 394 tmpDir, err := ioutil.TempDir("", "") 395 h.AssertNil(t, err) 396 defer os.RemoveAll(tmpDir) 397 398 layerFile := filepath.Join(tmpDir, "order.tar") 399 err = archive.CreateSingleFileTar(layerFile, "/cnb/order.toml", "some content") 400 h.AssertNil(t, err) 401 402 h.AssertNil(t, baseImage.AddLayer(layerFile)) 403 baseImage.Save() 404 405 h.AssertNil(t, subject.Save(logger, builder.CreatorMetadata{})) 406 h.AssertEq(t, baseImage.IsSaved(), true) 407 408 layerTar, err := baseImage.FindLayerWithPath("/cnb/order.toml") 409 h.AssertNil(t, err) 410 h.AssertOnTarEntry(t, layerTar, "/cnb/order.toml", h.ContentEquals("some content")) 411 }) 412 413 when("validating order", func() { 414 it.Before(func() { 415 subject.SetLifecycle(mockLifecycle) 416 }) 417 418 when("has single buildpack", func() { 419 it.Before(func() { 420 subject.AddBuildpack(bp1v1) 421 }) 422 423 it("should resolve unset version (to legacy label and order.toml)", func() { 424 subject.SetOrder(dist.Order{{ 425 Group: []dist.BuildpackRef{ 426 {BuildpackInfo: dist.BuildpackInfo{ID: bp1v1.Descriptor().Info.ID}}}, 427 }}) 428 429 err := subject.Save(logger, builder.CreatorMetadata{}) 430 h.AssertNil(t, err) 431 432 layerTar, err := baseImage.FindLayerWithPath("/cnb/order.toml") 433 h.AssertNil(t, err) 434 h.AssertOnTarEntry(t, layerTar, "/cnb/order.toml", h.ContentEquals(`[[order]] 435 436 [[order.group]] 437 id = "buildpack-1-id" 438 version = "buildpack-1-version-1" 439 `)) 440 }) 441 442 when("order points to missing buildpack id", func() { 443 it("should error", func() { 444 subject.SetOrder(dist.Order{{ 445 Group: []dist.BuildpackRef{ 446 {BuildpackInfo: dist.BuildpackInfo{ID: "missing-buildpack-id"}}}, 447 }}) 448 449 err := subject.Save(logger, builder.CreatorMetadata{}) 450 451 h.AssertError(t, err, "no versions of buildpack 'missing-buildpack-id' were found on the builder") 452 }) 453 }) 454 455 when("order points to missing buildpack version", func() { 456 it("should error", func() { 457 subject.SetOrder(dist.Order{{ 458 Group: []dist.BuildpackRef{ 459 {BuildpackInfo: dist.BuildpackInfo{ID: "buildpack-1-id", Version: "missing-buildpack-version"}}}, 460 }}) 461 462 err := subject.Save(logger, builder.CreatorMetadata{}) 463 464 h.AssertError(t, err, "buildpack 'buildpack-1-id' with version 'missing-buildpack-version' was not found on the builder") 465 }) 466 }) 467 }) 468 469 when("has repeated buildpacks with the same ID and version", func() { 470 it.Before(func() { 471 subject.AddBuildpack(bp1v1) 472 subject.AddBuildpack(bp1v1) 473 }) 474 475 when("order omits version", func() { 476 it("should de-duplicate identical buildpacks", func() { 477 subject.SetOrder(dist.Order{ 478 {Group: []dist.BuildpackRef{{ 479 BuildpackInfo: dist.BuildpackInfo{ 480 ID: bp1v1.Descriptor().Info.ID, 481 Homepage: bp1v1.Descriptor().Info.Homepage, 482 }}}, 483 }, 484 {Group: []dist.BuildpackRef{{ 485 BuildpackInfo: dist.BuildpackInfo{ 486 ID: bp1v1.Descriptor().Info.ID, 487 Homepage: bp1v1.Descriptor().Info.Homepage, 488 }}}, 489 }, 490 }) 491 492 err := subject.Save(logger, builder.CreatorMetadata{}) 493 h.AssertNil(t, err) 494 }) 495 }) 496 }) 497 498 when("has multiple buildpacks with same ID", func() { 499 it.Before(func() { 500 subject.AddBuildpack(bp1v1) 501 subject.AddBuildpack(bp1v2) 502 }) 503 504 when("order explicitly sets version", func() { 505 it("should keep order version", func() { 506 subject.SetOrder(dist.Order{{ 507 Group: []dist.BuildpackRef{ 508 {BuildpackInfo: bp1v1.Descriptor().Info}}, 509 }}) 510 511 err := subject.Save(logger, builder.CreatorMetadata{}) 512 h.AssertNil(t, err) 513 514 layerTar, err := baseImage.FindLayerWithPath("/cnb/order.toml") 515 h.AssertNil(t, err) 516 h.AssertOnTarEntry(t, layerTar, "/cnb/order.toml", h.ContentEquals(`[[order]] 517 518 [[order.group]] 519 id = "buildpack-1-id" 520 version = "buildpack-1-version-1" 521 `)) 522 }) 523 }) 524 525 when("order version is empty", func() { 526 it("return error", func() { 527 subject.SetOrder(dist.Order{{ 528 Group: []dist.BuildpackRef{ 529 {BuildpackInfo: dist.BuildpackInfo{ID: "buildpack-1-id"}}}, 530 }}) 531 532 err := subject.Save(logger, builder.CreatorMetadata{}) 533 h.AssertError(t, err, "multiple versions of 'buildpack-1-id' - must specify an explicit version") 534 }) 535 }) 536 }) 537 }) 538 539 when("validating buildpacks", func() { 540 when("nested buildpack does not exist", func() { 541 when("buildpack by id does not exist", func() { 542 it("returns an error", func() { 543 subject.AddBuildpack(bp1v1) 544 subject.AddBuildpack(bpOrder) 545 546 // order buildpack requires bp2v1 547 err := subject.Save(logger, builder.CreatorMetadata{}) 548 549 h.AssertError(t, err, "buildpack 'buildpack-2-id@buildpack-2-version-1' not found on the builder") 550 }) 551 }) 552 553 when("buildpack version does not exist", func() { 554 it("returns an error", func() { 555 subject.AddBuildpack(bp1v2) 556 subject.AddBuildpack(bp2v1) 557 558 // order buildpack requires bp1v1 rather than bp1v2 559 subject.AddBuildpack(bpOrder) 560 561 err := subject.Save(logger, builder.CreatorMetadata{}) 562 563 h.AssertError(t, err, "buildpack 'buildpack-1-id@buildpack-1-version-1' not found on the builder") 564 }) 565 }) 566 }) 567 568 when("buildpack stack id does not match", func() { 569 it("returns an error", func() { 570 bp, err := ifakes.NewFakeBuildpack(dist.BuildpackDescriptor{ 571 API: api.MustParse("0.2"), 572 Info: bp1v1.Descriptor().Info, 573 Stacks: []dist.Stack{{ID: "other.stack.id"}}, 574 }, 0644) 575 h.AssertNil(t, err) 576 577 subject.AddBuildpack(bp) 578 err = subject.Save(logger, builder.CreatorMetadata{}) 579 580 h.AssertError(t, err, "buildpack 'buildpack-1-id@buildpack-1-version-1' does not support stack 'some.stack.id'") 581 }) 582 }) 583 584 when("buildpack is not compatible with lifecycle", func() { 585 it("returns an error", func() { 586 bp, err := ifakes.NewFakeBuildpack(dist.BuildpackDescriptor{ 587 API: api.MustParse("0.1"), 588 Info: bp1v1.Descriptor().Info, 589 Stacks: []dist.Stack{{ID: "some.stack.id"}}, 590 }, 0644) 591 h.AssertNil(t, err) 592 593 subject.AddBuildpack(bp) 594 err = subject.Save(logger, builder.CreatorMetadata{}) 595 596 h.AssertError(t, 597 err, 598 "buildpack 'buildpack-1-id@buildpack-1-version-1' (Buildpack API 0.1) is incompatible with lifecycle '0.0.0' (Buildpack API(s) 0.2, 0.3, 0.4)") 599 }) 600 }) 601 602 when("buildpack mixins are not satisfied", func() { 603 it("returns an error", func() { 604 bp, err := ifakes.NewFakeBuildpack(dist.BuildpackDescriptor{ 605 API: api.MustParse("0.2"), 606 Info: bp1v1.Descriptor().Info, 607 Stacks: []dist.Stack{{ 608 ID: "some.stack.id", 609 Mixins: []string{"missing"}, 610 }}, 611 }, 0644) 612 h.AssertNil(t, err) 613 614 subject.AddBuildpack(bp) 615 err = subject.Save(logger, builder.CreatorMetadata{}) 616 617 h.AssertError(t, err, "buildpack 'buildpack-1-id@buildpack-1-version-1' requires missing mixin(s): missing") 618 }) 619 }) 620 }) 621 622 when("getting layers label", func() { 623 it("fails if layers label isn't set correctly", func() { 624 h.AssertNil(t, baseImage.SetLabel( 625 "io.buildpacks.buildpack.layers", 626 `{"something-here: }`, 627 )) 628 629 err := subject.Save(logger, builder.CreatorMetadata{}) 630 h.AssertError(t, err, "getting label io.buildpacks.buildpack.layers") 631 }) 632 }) 633 }) 634 635 when("#SetLifecycle", func() { 636 it.Before(func() { 637 h.AssertNil(t, subject.Save(logger, builder.CreatorMetadata{})) 638 h.AssertEq(t, baseImage.IsSaved(), true) 639 }) 640 641 it("should set the lifecycle version successfully", func() { 642 h.AssertEq(t, subject.LifecycleDescriptor().Info.Version.String(), "0.0.0") 643 }) 644 645 it("should add the lifecycle binaries as an image layer", func() { 646 layerTar, err := baseImage.FindLayerWithPath("/cnb/lifecycle") 647 h.AssertNil(t, err) 648 h.AssertOnTarEntry(t, layerTar, "/cnb/lifecycle", 649 h.IsDirectory(), 650 h.HasFileMode(0755), 651 h.HasModTime(archive.NormalizedDateTime), 652 ) 653 654 h.AssertOnTarEntry(t, layerTar, "/cnb/lifecycle/detector", 655 h.ContentEquals("detector"), 656 h.HasFileMode(0755), 657 h.HasModTime(archive.NormalizedDateTime), 658 ) 659 660 h.AssertOnTarEntry(t, layerTar, "/cnb/lifecycle/restorer", 661 h.ContentEquals("restorer"), 662 h.HasFileMode(0755), 663 h.HasModTime(archive.NormalizedDateTime), 664 ) 665 666 h.AssertOnTarEntry(t, layerTar, "/cnb/lifecycle/analyzer", 667 h.ContentEquals("analyzer"), 668 h.HasFileMode(0755), 669 h.HasModTime(archive.NormalizedDateTime), 670 ) 671 672 h.AssertOnTarEntry(t, layerTar, "/cnb/lifecycle/builder", 673 h.ContentEquals("builder"), 674 h.HasFileMode(0755), 675 h.HasModTime(archive.NormalizedDateTime), 676 ) 677 678 h.AssertOnTarEntry(t, layerTar, "/cnb/lifecycle/exporter", 679 h.ContentEquals("exporter"), 680 h.HasFileMode(0755), 681 h.HasModTime(archive.NormalizedDateTime), 682 ) 683 684 h.AssertOnTarEntry(t, layerTar, "/cnb/lifecycle/launcher", 685 h.ContentEquals("launcher"), 686 h.HasFileMode(0755), 687 h.HasModTime(archive.NormalizedDateTime), 688 ) 689 690 it("should add lifecycle symlink", func() { 691 h.AssertOnTarEntry(t, layerTar, "/lifecycle", 692 h.SymlinksTo("/cnb/lifecycle"), 693 h.HasFileMode(0644), 694 h.HasModTime(archive.NormalizedDateTime), 695 ) 696 }) 697 }) 698 699 it("sets the lifecycle version on the metadata", func() { 700 label, err := baseImage.Label("io.buildpacks.builder.metadata") 701 h.AssertNil(t, err) 702 703 var metadata builder.Metadata 704 h.AssertNil(t, json.Unmarshal([]byte(label), &metadata)) 705 h.AssertEq(t, metadata.Lifecycle.Version.String(), "0.0.0") 706 h.AssertEq(t, metadata.Lifecycle.API.BuildpackVersion.String(), "0.2") 707 h.AssertEq(t, metadata.Lifecycle.API.PlatformVersion.String(), "0.2") 708 h.AssertNotNil(t, metadata.Lifecycle.APIs) 709 h.AssertEq(t, metadata.Lifecycle.APIs.Buildpack.Deprecated.AsStrings(), []string{}) 710 h.AssertEq(t, metadata.Lifecycle.APIs.Buildpack.Supported.AsStrings(), []string{"0.2", "0.3", "0.4"}) 711 h.AssertEq(t, metadata.Lifecycle.APIs.Platform.Deprecated.AsStrings(), []string{"0.2"}) 712 h.AssertEq(t, metadata.Lifecycle.APIs.Platform.Supported.AsStrings(), []string{"0.3", "0.4"}) 713 }) 714 }) 715 716 when("#AddBuildpack", func() { 717 it.Before(func() { 718 subject.AddBuildpack(bp1v1) 719 subject.AddBuildpack(bp1v2) 720 subject.AddBuildpack(bp2v1) 721 subject.AddBuildpack(bpOrder) 722 }) 723 724 it("adds the buildpack as an image layer", func() { 725 h.AssertNil(t, subject.Save(logger, builder.CreatorMetadata{})) 726 h.AssertEq(t, baseImage.IsSaved(), true) 727 assertImageHasBPLayer(t, baseImage, bp1v1) 728 assertImageHasBPLayer(t, baseImage, bp1v2) 729 assertImageHasBPLayer(t, baseImage, bp2v1) 730 assertImageHasOrderBpLayer(t, baseImage, bpOrder) 731 }) 732 733 it("adds the buildpack metadata", func() { 734 h.AssertNil(t, subject.Save(logger, builder.CreatorMetadata{})) 735 h.AssertEq(t, baseImage.IsSaved(), true) 736 737 label, err := baseImage.Label("io.buildpacks.builder.metadata") 738 h.AssertNil(t, err) 739 740 var metadata builder.Metadata 741 h.AssertNil(t, json.Unmarshal([]byte(label), &metadata)) 742 h.AssertEq(t, len(metadata.Buildpacks), 4) 743 744 h.AssertEq(t, metadata.Buildpacks[0].ID, "buildpack-1-id") 745 h.AssertEq(t, metadata.Buildpacks[0].Version, "buildpack-1-version-1") 746 747 h.AssertEq(t, metadata.Buildpacks[1].ID, "buildpack-1-id") 748 h.AssertEq(t, metadata.Buildpacks[1].Version, "buildpack-1-version-2") 749 750 h.AssertEq(t, metadata.Buildpacks[2].ID, "buildpack-2-id") 751 h.AssertEq(t, metadata.Buildpacks[2].Version, "buildpack-2-version-1") 752 753 h.AssertEq(t, metadata.Buildpacks[3].ID, "order-buildpack-id") 754 h.AssertEq(t, metadata.Buildpacks[3].Version, "order-buildpack-version") 755 }) 756 757 it("adds the buildpack layers label", func() { 758 h.AssertNil(t, subject.Save(logger, builder.CreatorMetadata{})) 759 h.AssertEq(t, baseImage.IsSaved(), true) 760 761 label, err := baseImage.Label("io.buildpacks.buildpack.layers") 762 h.AssertNil(t, err) 763 764 var layers dist.BuildpackLayers 765 h.AssertNil(t, json.Unmarshal([]byte(label), &layers)) 766 h.AssertEq(t, len(layers), 3) 767 h.AssertEq(t, len(layers["buildpack-1-id"]), 2) 768 h.AssertEq(t, len(layers["buildpack-2-id"]), 1) 769 770 h.AssertEq(t, len(layers["buildpack-1-id"]["buildpack-1-version-1"].Order), 0) 771 h.AssertEq(t, len(layers["buildpack-1-id"]["buildpack-1-version-1"].Stacks), 1) 772 h.AssertEq(t, layers["buildpack-1-id"]["buildpack-1-version-1"].Stacks[0].ID, "some.stack.id") 773 h.AssertSliceContainsOnly(t, layers["buildpack-1-id"]["buildpack-1-version-1"].Stacks[0].Mixins, "mixinX", "mixinY") 774 775 h.AssertEq(t, len(layers["buildpack-1-id"]["buildpack-1-version-2"].Order), 0) 776 h.AssertEq(t, len(layers["buildpack-1-id"]["buildpack-1-version-2"].Stacks), 1) 777 h.AssertEq(t, layers["buildpack-1-id"]["buildpack-1-version-2"].Stacks[0].ID, "some.stack.id") 778 h.AssertSliceContainsOnly(t, layers["buildpack-1-id"]["buildpack-1-version-2"].Stacks[0].Mixins, "mixinX", "mixinY") 779 780 h.AssertEq(t, len(layers["buildpack-2-id"]["buildpack-2-version-1"].Order), 0) 781 h.AssertEq(t, len(layers["buildpack-2-id"]["buildpack-2-version-1"].Stacks), 1) 782 h.AssertEq(t, layers["buildpack-2-id"]["buildpack-2-version-1"].Stacks[0].ID, "some.stack.id") 783 h.AssertSliceContainsOnly(t, layers["buildpack-2-id"]["buildpack-2-version-1"].Stacks[0].Mixins, "build:mixinA", "run:mixinB") 784 785 h.AssertEq(t, len(layers["order-buildpack-id"]["order-buildpack-version"].Order), 1) 786 h.AssertEq(t, len(layers["order-buildpack-id"]["order-buildpack-version"].Order[0].Group), 2) 787 h.AssertEq(t, layers["order-buildpack-id"]["order-buildpack-version"].Order[0].Group[0].ID, "buildpack-1-id") 788 h.AssertEq(t, layers["order-buildpack-id"]["order-buildpack-version"].Order[0].Group[0].Version, "buildpack-1-version-1") 789 h.AssertEq(t, layers["order-buildpack-id"]["order-buildpack-version"].Order[0].Group[0].Optional, true) 790 h.AssertEq(t, layers["order-buildpack-id"]["order-buildpack-version"].Order[0].Group[1].ID, "buildpack-2-id") 791 h.AssertEq(t, layers["order-buildpack-id"]["order-buildpack-version"].Order[0].Group[1].Version, "buildpack-2-version-1") 792 h.AssertEq(t, layers["order-buildpack-id"]["order-buildpack-version"].Order[0].Group[1].Optional, false) 793 }) 794 795 when("base image already has buildpack layers label", func() { 796 it.Before(func() { 797 var mdJSON bytes.Buffer 798 h.AssertNil(t, json.Compact( 799 &mdJSON, 800 []byte(`{ 801 "buildpack-1-id": { 802 "buildpack-1-version-1": { 803 "layerDiffID": "sha256:buildpack-1-version-1-diff-id" 804 }, 805 "buildpack-1-version-2": { 806 "layerDiffID": "sha256:buildpack-1-version-2-diff-id" 807 } 808 } 809 } 810 `))) 811 812 h.AssertNil(t, baseImage.SetLabel( 813 "io.buildpacks.buildpack.layers", 814 mdJSON.String(), 815 )) 816 817 var err error 818 subject, err = builder.New(baseImage, "some/builder") 819 h.AssertNil(t, err) 820 821 subject.AddBuildpack(bp1v2) 822 subject.AddBuildpack(bp2v1) 823 824 subject.SetLifecycle(mockLifecycle) 825 }) 826 827 it("appends buildpack layer info", func() { 828 h.AssertNil(t, subject.Save(logger, builder.CreatorMetadata{})) 829 h.AssertEq(t, baseImage.IsSaved(), true) 830 831 label, err := baseImage.Label("io.buildpacks.buildpack.layers") 832 h.AssertNil(t, err) 833 834 var layers dist.BuildpackLayers 835 h.AssertNil(t, json.Unmarshal([]byte(label), &layers)) 836 h.AssertEq(t, len(layers), 2) 837 h.AssertEq(t, len(layers["buildpack-1-id"]), 2) 838 h.AssertEq(t, len(layers["buildpack-2-id"]), 1) 839 840 h.AssertEq(t, layers["buildpack-1-id"]["buildpack-1-version-1"].LayerDiffID, "sha256:buildpack-1-version-1-diff-id") 841 842 h.AssertUnique(t, 843 layers["buildpack-1-id"]["buildpack-1-version-1"].LayerDiffID, 844 layers["buildpack-1-id"]["buildpack-1-version-2"].LayerDiffID, 845 layers["buildpack-2-id"]["buildpack-2-version-1"].LayerDiffID, 846 ) 847 848 h.AssertEq(t, len(layers["buildpack-1-id"]["buildpack-1-version-1"].Order), 0) 849 h.AssertEq(t, len(layers["buildpack-1-id"]["buildpack-1-version-2"].Order), 0) 850 h.AssertEq(t, len(layers["buildpack-2-id"]["buildpack-2-version-1"].Order), 0) 851 }) 852 853 it("informs when overriding existing buildpack, and log level is DEBUG", func() { 854 logger := ilogging.NewLogWithWriters(&outBuf, &outBuf, ilogging.WithVerbose()) 855 856 h.AssertNil(t, subject.Save(logger, builder.CreatorMetadata{})) 857 h.AssertEq(t, baseImage.IsSaved(), true) 858 859 label, err := baseImage.Label("io.buildpacks.buildpack.layers") 860 h.AssertNil(t, err) 861 862 var layers dist.BuildpackLayers 863 h.AssertNil(t, json.Unmarshal([]byte(label), &layers)) 864 865 h.AssertContains(t, 866 outBuf.String(), 867 "buildpack 'buildpack-1-id@buildpack-1-version-2' already exists on builder and will be overwritten", 868 ) 869 h.AssertNotContains(t, layers["buildpack-1-id"]["buildpack-1-version-2"].LayerDiffID, "buildpack-1-version-2-diff-id") 870 }) 871 872 it("doesn't message when overriding existing buildpack when log level is INFO", func() { 873 h.AssertNil(t, subject.Save(logger, builder.CreatorMetadata{})) 874 h.AssertEq(t, baseImage.IsSaved(), true) 875 876 label, err := baseImage.Label("io.buildpacks.buildpack.layers") 877 h.AssertNil(t, err) 878 879 var layers dist.BuildpackLayers 880 h.AssertNil(t, json.Unmarshal([]byte(label), &layers)) 881 882 h.AssertNotContains(t, 883 outBuf.String(), 884 "buildpack 'buildpack-1-id@buildpack-1-version-2' already exists on builder and will be overwritten", 885 ) 886 h.AssertNotContains(t, layers["buildpack-1-id"]["buildpack-1-version-2"].LayerDiffID, "buildpack-1-version-2-diff-id") 887 }) 888 }) 889 890 when("base image already has metadata", func() { 891 it.Before(func() { 892 h.AssertNil(t, baseImage.SetLabel( 893 "io.buildpacks.builder.metadata", 894 `{ 895 "buildpacks":[{"id":"prev.id"}], 896 "groups":[{"buildpacks":[{"id":"prev.id"}]}], 897 "stack":{"runImage":{"image":"prev/run","mirrors":["prev/mirror"]}}, 898 "lifecycle":{"version":"6.6.6","apis":{"buildpack":{"deprecated":["0.1"],"supported":["0.2","0.3"]},"platform":{"deprecated":[],"supported":["2.3","2.4"]}}} 899 }`, 900 )) 901 902 var err error 903 subject, err = builder.New(baseImage, "some/builder") 904 h.AssertNil(t, err) 905 906 subject.AddBuildpack(bp1v1) 907 h.AssertNil(t, subject.Save(logger, builder.CreatorMetadata{})) 908 h.AssertEq(t, baseImage.IsSaved(), true) 909 }) 910 911 it("appends the buildpack to the metadata", func() { 912 label, err := baseImage.Label("io.buildpacks.builder.metadata") 913 h.AssertNil(t, err) 914 915 var metadata builder.Metadata 916 h.AssertNil(t, json.Unmarshal([]byte(label), &metadata)) 917 h.AssertEq(t, len(metadata.Buildpacks), 2) 918 919 // keeps original metadata 920 h.AssertEq(t, metadata.Buildpacks[0].ID, "prev.id") 921 h.AssertEq(t, metadata.Stack.RunImage.Image, "prev/run") 922 h.AssertEq(t, metadata.Stack.RunImage.Mirrors[0], "prev/mirror") 923 h.AssertEq(t, subject.LifecycleDescriptor().Info.Version.String(), "6.6.6") 924 925 // adds new buildpack 926 h.AssertEq(t, metadata.Buildpacks[1].ID, "buildpack-1-id") 927 h.AssertEq(t, metadata.Buildpacks[1].Version, "buildpack-1-version-1") 928 }) 929 }) 930 }) 931 932 when("#SetOrder", func() { 933 when("the buildpacks exist in the image", func() { 934 it.Before(func() { 935 subject.AddBuildpack(bp1v1) 936 subject.AddBuildpack(bp2v1) 937 subject.SetOrder(dist.Order{ 938 {Group: []dist.BuildpackRef{ 939 { 940 BuildpackInfo: dist.BuildpackInfo{ 941 ID: bp1v1.Descriptor().Info.ID, 942 // Version excluded intentionally 943 }, 944 }, 945 { 946 BuildpackInfo: bp2v1.Descriptor().Info, 947 Optional: true, 948 }, 949 }}, 950 }) 951 952 h.AssertNil(t, subject.Save(logger, builder.CreatorMetadata{})) 953 h.AssertEq(t, baseImage.IsSaved(), true) 954 }) 955 956 it("adds the order.toml to the image", func() { 957 layerTar, err := baseImage.FindLayerWithPath("/cnb/order.toml") 958 h.AssertNil(t, err) 959 h.AssertOnTarEntry(t, layerTar, "/cnb/order.toml", 960 h.ContentEquals(`[[order]] 961 962 [[order.group]] 963 id = "buildpack-1-id" 964 version = "buildpack-1-version-1" 965 966 [[order.group]] 967 id = "buildpack-2-id" 968 version = "buildpack-2-version-1" 969 optional = true 970 `), 971 h.HasModTime(archive.NormalizedDateTime), 972 ) 973 }) 974 975 it("adds the order to the order label", func() { 976 label, err := baseImage.Label("io.buildpacks.buildpack.order") 977 h.AssertNil(t, err) 978 979 var order dist.Order 980 h.AssertNil(t, json.Unmarshal([]byte(label), &order)) 981 h.AssertEq(t, len(order), 1) 982 h.AssertEq(t, len(order[0].Group), 2) 983 h.AssertEq(t, order[0].Group[0].ID, "buildpack-1-id") 984 h.AssertEq(t, order[0].Group[0].Version, "") 985 h.AssertEq(t, order[0].Group[0].Optional, false) 986 h.AssertEq(t, order[0].Group[1].ID, "buildpack-2-id") 987 h.AssertEq(t, order[0].Group[1].Version, "buildpack-2-version-1") 988 h.AssertEq(t, order[0].Group[1].Optional, true) 989 }) 990 }) 991 }) 992 993 when("#SetDescription", func() { 994 it.Before(func() { 995 subject.SetDescription("Some description") 996 h.AssertNil(t, subject.Save(logger, builder.CreatorMetadata{})) 997 h.AssertEq(t, baseImage.IsSaved(), true) 998 }) 999 1000 it("sets the description on the metadata", func() { 1001 label, err := baseImage.Label("io.buildpacks.builder.metadata") 1002 h.AssertNil(t, err) 1003 1004 var metadata builder.Metadata 1005 h.AssertNil(t, json.Unmarshal([]byte(label), &metadata)) 1006 h.AssertEq(t, metadata.Description, "Some description") 1007 }) 1008 }) 1009 1010 when("#SetStack", func() { 1011 it.Before(func() { 1012 subject.SetStack(pubbldr.StackConfig{ 1013 RunImage: "some/run", 1014 RunImageMirrors: []string{"some/mirror", "other/mirror"}, 1015 }) 1016 h.AssertNil(t, subject.Save(logger, builder.CreatorMetadata{})) 1017 h.AssertEq(t, baseImage.IsSaved(), true) 1018 }) 1019 1020 it("adds the stack.toml to the image", func() { 1021 layerTar, err := baseImage.FindLayerWithPath("/cnb/stack.toml") 1022 h.AssertNil(t, err) 1023 h.AssertOnTarEntry(t, layerTar, "/cnb/stack.toml", 1024 h.ContentEquals(`[run-image] 1025 image = "some/run" 1026 mirrors = ["some/mirror", "other/mirror"] 1027 `), 1028 h.HasModTime(archive.NormalizedDateTime), 1029 ) 1030 }) 1031 1032 it("adds the stack to the metadata", func() { 1033 label, err := baseImage.Label("io.buildpacks.builder.metadata") 1034 h.AssertNil(t, err) 1035 1036 var metadata builder.Metadata 1037 h.AssertNil(t, json.Unmarshal([]byte(label), &metadata)) 1038 h.AssertEq(t, metadata.Stack.RunImage.Image, "some/run") 1039 h.AssertEq(t, metadata.Stack.RunImage.Mirrors[0], "some/mirror") 1040 h.AssertEq(t, metadata.Stack.RunImage.Mirrors[1], "other/mirror") 1041 }) 1042 }) 1043 1044 when("#SetEnv", func() { 1045 it.Before(func() { 1046 subject.SetEnv(map[string]string{ 1047 "SOME_KEY": "some-val", 1048 "OTHER_KEY": "other-val", 1049 }) 1050 h.AssertNil(t, subject.Save(logger, builder.CreatorMetadata{})) 1051 h.AssertEq(t, baseImage.IsSaved(), true) 1052 }) 1053 1054 it("adds the env vars as files to the image", func() { 1055 layerTar, err := baseImage.FindLayerWithPath("/platform/env/SOME_KEY") 1056 h.AssertNil(t, err) 1057 h.AssertOnTarEntry(t, layerTar, "/platform/env/SOME_KEY", 1058 h.ContentEquals(`some-val`), 1059 h.HasModTime(archive.NormalizedDateTime), 1060 ) 1061 h.AssertOnTarEntry(t, layerTar, "/platform/env/OTHER_KEY", 1062 h.ContentEquals(`other-val`), 1063 h.HasModTime(archive.NormalizedDateTime), 1064 ) 1065 }) 1066 }) 1067 }) 1068 1069 when("builder exists", func() { 1070 var builderImage imgutil.Image 1071 1072 it.Before(func() { 1073 h.AssertNil(t, baseImage.SetEnv("CNB_USER_ID", "1234")) 1074 h.AssertNil(t, baseImage.SetEnv("CNB_GROUP_ID", "4321")) 1075 h.AssertNil(t, baseImage.SetLabel("io.buildpacks.stack.id", "some.stack.id")) 1076 h.AssertNil(t, baseImage.SetLabel("io.buildpacks.stack.mixins", `["mixinX", "mixinY", "build:mixinA"]`)) 1077 h.AssertNil(t, baseImage.SetLabel( 1078 "io.buildpacks.builder.metadata", 1079 `{"description": "some-description", "createdBy": {"name": "some-name", "version": "1.2.3"}, "buildpacks": [{"id": "buildpack-1-id"}, {"id": "buildpack-2-id"}], "groups": [{"buildpacks": [{"id": "buildpack-1-id", "version": "buildpack-1-version", "optional": false}, {"id": "buildpack-2-id", "version": "buildpack-2-version-1", "optional": true}]}], "stack": {"runImage": {"image": "prev/run", "mirrors": ["prev/mirror"]}}, "lifecycle": {"version": "6.6.6"}}`, 1080 )) 1081 h.AssertNil(t, baseImage.SetLabel( 1082 "io.buildpacks.buildpack.order", 1083 `[{"group": [{"id": "buildpack-1-id", "optional": false}, {"id": "buildpack-2-id", "version": "buildpack-2-version-1", "optional": true}]}]`, 1084 )) 1085 1086 builderImage = baseImage 1087 }) 1088 1089 when("#FromImage", func() { 1090 var bldr *builder.Builder 1091 1092 it.Before(func() { 1093 var err error 1094 bldr, err = builder.FromImage(builderImage) 1095 h.AssertNil(t, err) 1096 }) 1097 1098 it("gets builder from image", func() { 1099 h.AssertEq(t, bldr.Buildpacks()[0].ID, "buildpack-1-id") 1100 h.AssertEq(t, bldr.Buildpacks()[1].ID, "buildpack-2-id") 1101 1102 order := bldr.Order() 1103 h.AssertEq(t, len(order), 1) 1104 h.AssertEq(t, len(order[0].Group), 2) 1105 h.AssertEq(t, order[0].Group[0].ID, "buildpack-1-id") 1106 h.AssertEq(t, order[0].Group[0].Version, "") 1107 h.AssertEq(t, order[0].Group[0].Optional, false) 1108 h.AssertEq(t, order[0].Group[1].ID, "buildpack-2-id") 1109 h.AssertEq(t, order[0].Group[1].Version, "buildpack-2-version-1") 1110 h.AssertEq(t, order[0].Group[1].Optional, true) 1111 }) 1112 1113 it("gets mixins from image", func() { 1114 h.AssertSliceContainsOnly(t, bldr.Mixins(), "mixinX", "mixinY", "build:mixinA") 1115 }) 1116 1117 when("metadata is missing", func() { 1118 it.Before(func() { 1119 h.AssertNil(t, builderImage.SetLabel( 1120 "io.buildpacks.builder.metadata", 1121 "", 1122 )) 1123 }) 1124 1125 it("should error", func() { 1126 _, err := builder.FromImage(builderImage) 1127 h.AssertError(t, err, "missing label 'io.buildpacks.builder.metadata'") 1128 }) 1129 }) 1130 1131 when("#Description", func() { 1132 it("return description", func() { 1133 h.AssertEq(t, bldr.Description(), "some-description") 1134 }) 1135 }) 1136 1137 when("#CreatedBy", func() { 1138 it("return CreatedBy", func() { 1139 expectedCreatorMetadata := builder.CreatorMetadata{ 1140 Name: "some-name", 1141 Version: "1.2.3", 1142 } 1143 h.AssertEq(t, bldr.CreatedBy(), expectedCreatorMetadata) 1144 }) 1145 }) 1146 1147 when("#Name", func() { 1148 it("return Name", func() { 1149 h.AssertEq(t, bldr.Name(), "base/image") 1150 }) 1151 }) 1152 1153 when("#Image", func() { 1154 it("return Image", func() { 1155 h.AssertSameInstance(t, bldr.Image(), baseImage) 1156 }) 1157 }) 1158 1159 when("#Stack", func() { 1160 it("return Stack", func() { 1161 expectedStack := builder.StackMetadata{ 1162 RunImage: builder.RunImageMetadata{ 1163 Image: "prev/run", 1164 Mirrors: []string{"prev/mirror"}}} 1165 1166 h.AssertEq(t, bldr.Stack(), expectedStack) 1167 }) 1168 }) 1169 1170 when("#UID", func() { 1171 it("return UID", func() { 1172 h.AssertEq(t, bldr.UID(), 1234) 1173 }) 1174 }) 1175 1176 when("#GID", func() { 1177 it("return GID", func() { 1178 h.AssertEq(t, bldr.GID(), 4321) 1179 }) 1180 }) 1181 }) 1182 }) 1183 } 1184 1185 func assertImageHasBPLayer(t *testing.T, image *fakes.Image, bp dist.Buildpack) { 1186 t.Helper() 1187 1188 dirPath := fmt.Sprintf("/cnb/buildpacks/%s/%s", bp.Descriptor().Info.ID, bp.Descriptor().Info.Version) 1189 layerTar, err := image.FindLayerWithPath(dirPath) 1190 h.AssertNil(t, err) 1191 1192 h.AssertOnTarEntry(t, layerTar, dirPath, 1193 h.IsDirectory(), 1194 ) 1195 1196 h.AssertOnTarEntry(t, layerTar, path.Dir(dirPath), 1197 h.IsDirectory(), 1198 ) 1199 1200 h.AssertOnTarEntry(t, layerTar, dirPath+"/bin/build", 1201 h.ContentEquals("build-contents"), 1202 ) 1203 1204 h.AssertOnTarEntry(t, layerTar, dirPath+"/bin/detect", 1205 h.ContentEquals("detect-contents"), 1206 ) 1207 } 1208 1209 func assertImageHasOrderBpLayer(t *testing.T, image *fakes.Image, bp dist.Buildpack) { 1210 t.Helper() 1211 1212 dirPath := fmt.Sprintf("/cnb/buildpacks/%s/%s", bp.Descriptor().Info.ID, bp.Descriptor().Info.Version) 1213 layerTar, err := image.FindLayerWithPath(dirPath) 1214 h.AssertNil(t, err) 1215 1216 h.AssertOnTarEntry(t, layerTar, dirPath, 1217 h.IsDirectory(), 1218 ) 1219 1220 h.AssertOnTarEntry(t, layerTar, path.Dir(dirPath), 1221 h.IsDirectory(), 1222 ) 1223 }