github.com/YousefHaggyHeroku/pack@v1.5.5/internal/builder/label_manager_test.go (about) 1 package builder_test 2 3 import ( 4 "errors" 5 "fmt" 6 "testing" 7 8 "github.com/heroku/color" 9 "github.com/sclevine/spec" 10 "github.com/sclevine/spec/report" 11 12 "github.com/buildpacks/lifecycle/api" 13 14 "github.com/YousefHaggyHeroku/pack/internal/builder" 15 "github.com/YousefHaggyHeroku/pack/internal/builder/fakes" 16 "github.com/YousefHaggyHeroku/pack/internal/dist" 17 h "github.com/YousefHaggyHeroku/pack/testhelpers" 18 ) 19 20 func TestLabelManager(t *testing.T) { 21 color.Disable(true) 22 defer color.Disable(false) 23 spec.Run(t, "testLabelManager", testLabelManager, spec.Parallel(), spec.Report(report.Terminal{})) 24 } 25 26 func testLabelManager(t *testing.T, when spec.G, it spec.S) { 27 var assert = h.NewAssertionManager(t) 28 29 when("Metadata", func() { 30 const ( 31 buildpackFormat = `{ 32 "id": "%s", 33 "version": "%s", 34 "homepage": "%s" 35 }` 36 lifecycleFormat = `{ 37 "version": "%s", 38 "api": { 39 "buildpack": "%s", 40 "platform": "%s" 41 }, 42 "apis": { 43 "buildpack": {"deprecated": ["%s"], "supported": ["%s", "%s"]}, 44 "platform": {"deprecated": ["%s"], "supported": ["%s", "%s"]} 45 } 46 }` 47 metadataFormat = `{ 48 "description": "%s", 49 "stack": { 50 "runImage": { 51 "image": "%s", 52 "mirrors": ["%s"] 53 } 54 }, 55 "buildpacks": [ 56 %s, 57 %s 58 ], 59 "lifecycle": %s, 60 "createdBy": {"name": "%s", "version": "%s"} 61 }` 62 ) 63 64 var ( 65 expectedDescription = "Test image description" 66 expectedRunImage = "some/run-image" 67 expectedRunImageMirror = "gcr.io/some/default" 68 expectedBuildpacks = []dist.BuildpackInfo{ 69 { 70 ID: "test.buildpack", 71 Version: "test.buildpack.version", 72 Homepage: "http://geocities.com/test-bp", 73 }, 74 { 75 ID: "test.buildpack.two", 76 Version: "test.buildpack.two.version", 77 Homepage: "http://geocities.com/test-bp-two", 78 }, 79 } 80 expectedLifecycleVersion = builder.VersionMustParse("1.2.3") 81 expectedBuildpackAPI = api.MustParse("0.1") 82 expectedPlatformAPI = api.MustParse("2.3") 83 expectedBuildpackDeprecated = "0.1" 84 expectedBuildpackSupported = []string{"1.2", "1.3"} 85 expectedPlatformDeprecated = "1.2" 86 expectedPlatformSupported = []string{"2.3", "2.4"} 87 expectedCreatorName = "pack" 88 expectedVersion = "2.3.4" 89 90 rawMetadata = fmt.Sprintf( 91 metadataFormat, 92 expectedDescription, 93 expectedRunImage, 94 expectedRunImageMirror, 95 fmt.Sprintf( 96 buildpackFormat, 97 expectedBuildpacks[0].ID, 98 expectedBuildpacks[0].Version, 99 expectedBuildpacks[0].Homepage, 100 ), 101 fmt.Sprintf( 102 buildpackFormat, 103 expectedBuildpacks[1].ID, 104 expectedBuildpacks[1].Version, 105 expectedBuildpacks[1].Homepage, 106 ), 107 fmt.Sprintf( 108 lifecycleFormat, 109 expectedLifecycleVersion, 110 expectedBuildpackAPI, 111 expectedPlatformAPI, 112 expectedBuildpackDeprecated, 113 expectedBuildpackSupported[0], 114 expectedBuildpackSupported[1], 115 expectedPlatformDeprecated, 116 expectedPlatformSupported[0], 117 expectedPlatformSupported[1], 118 ), 119 expectedCreatorName, 120 expectedVersion, 121 ) 122 ) 123 124 it("returns full metadata", func() { 125 inspectable := newInspectable(returnForLabel(rawMetadata)) 126 127 labelManager := builder.NewLabelManager(inspectable) 128 metadata, err := labelManager.Metadata() 129 assert.Nil(err) 130 assert.Equal(metadata.Description, expectedDescription) 131 assert.Equal(metadata.Stack.RunImage.Image, expectedRunImage) 132 assert.Equal(metadata.Stack.RunImage.Mirrors, []string{expectedRunImageMirror}) 133 assert.Equal(metadata.Buildpacks, expectedBuildpacks) 134 assert.Equal(metadata.Lifecycle.Version, expectedLifecycleVersion) 135 assert.Equal(metadata.Lifecycle.API.BuildpackVersion, expectedBuildpackAPI) 136 assert.Equal(metadata.Lifecycle.API.PlatformVersion, expectedPlatformAPI) 137 assert.Equal(metadata.Lifecycle.APIs.Buildpack.Deprecated.AsStrings(), []string{expectedBuildpackDeprecated}) 138 assert.Equal(metadata.Lifecycle.APIs.Buildpack.Supported.AsStrings(), expectedBuildpackSupported) 139 assert.Equal(metadata.Lifecycle.APIs.Platform.Deprecated.AsStrings(), []string{expectedPlatformDeprecated}) 140 assert.Equal(metadata.Lifecycle.APIs.Platform.Supported.AsStrings(), expectedPlatformSupported) 141 assert.Equal(metadata.CreatedBy.Name, expectedCreatorName) 142 assert.Equal(metadata.CreatedBy.Version, expectedVersion) 143 }) 144 145 it("requests the expected label", func() { 146 inspectable := newInspectable(returnForLabel(rawMetadata)) 147 148 labelManager := builder.NewLabelManager(inspectable) 149 _, err := labelManager.Metadata() 150 assert.Nil(err) 151 152 assert.Equal(inspectable.ReceivedName, "io.buildpacks.builder.metadata") 153 }) 154 155 when("inspectable returns an error for `Label`", func() { 156 it("returns a wrapped error", func() { 157 expectedError := errors.New("couldn't find label") 158 159 inspectable := newInspectable(errorForLabel(expectedError)) 160 161 labelManager := builder.NewLabelManager(inspectable) 162 _, err := labelManager.Metadata() 163 164 assert.ErrorWithMessage( 165 err, 166 "getting label io.buildpacks.builder.metadata: couldn't find label", 167 ) 168 }) 169 }) 170 171 when("inspectable returns invalid json for `Label`", func() { 172 it("returns a wrapped error", func() { 173 inspectable := newInspectable(returnForLabel("{")) 174 175 labelManager := builder.NewLabelManager(inspectable) 176 _, err := labelManager.Metadata() 177 178 assert.ErrorWithMessage( 179 err, 180 "parsing label content for io.buildpacks.builder.metadata: unexpected end of JSON input", 181 ) 182 }) 183 }) 184 185 when("inspectable returns empty content for `Label`", func() { 186 it("returns an error suggesting rebuilding the builder", func() { 187 inspectable := newInspectable(returnForLabel("")) 188 189 labelManager := builder.NewLabelManager(inspectable) 190 _, err := labelManager.Metadata() 191 192 assert.ErrorWithMessage( 193 err, 194 "builder missing label io.buildpacks.builder.metadata -- try recreating builder", 195 ) 196 }) 197 }) 198 }) 199 200 when("StackID", func() { 201 it("returns the stack ID", func() { 202 inspectable := newInspectable(returnForLabel("some.stack.id")) 203 204 labelManager := builder.NewLabelManager(inspectable) 205 stackID, err := labelManager.StackID() 206 assert.Nil(err) 207 208 assert.Equal(stackID, "some.stack.id") 209 }) 210 211 it("requests the expected label", func() { 212 inspectable := newInspectable(returnForLabel("some.stack.id")) 213 214 labelManager := builder.NewLabelManager(inspectable) 215 _, err := labelManager.StackID() 216 assert.Nil(err) 217 218 assert.Equal(inspectable.ReceivedName, "io.buildpacks.stack.id") 219 }) 220 221 when("inspectable return empty content for `Label`", func() { 222 it("returns an error suggesting rebuilding the builder", func() { 223 inspectable := newInspectable(returnForLabel("")) 224 225 labelManager := builder.NewLabelManager(inspectable) 226 _, err := labelManager.StackID() 227 228 assert.ErrorWithMessage( 229 err, 230 "builder missing label io.buildpacks.stack.id -- try recreating builder", 231 ) 232 }) 233 }) 234 235 when("inspectable returns an error for `Label`", func() { 236 it("returns a wrapped error", func() { 237 expectedError := errors.New("couldn't find label") 238 239 inspectable := newInspectable(errorForLabel(expectedError)) 240 241 labelManager := builder.NewLabelManager(inspectable) 242 _, err := labelManager.StackID() 243 244 assert.ErrorWithMessage( 245 err, 246 "getting label io.buildpacks.stack.id: couldn't find label", 247 ) 248 }) 249 }) 250 }) 251 252 when("Mixins", func() { 253 it("returns the mixins", func() { 254 inspectable := newInspectable(returnForLabel(`["mixinX", "mixinY", "build:mixinA"]`)) 255 256 labelManager := builder.NewLabelManager(inspectable) 257 mixins, err := labelManager.Mixins() 258 assert.Nil(err) 259 260 assert.Equal(mixins, []string{"mixinX", "mixinY", "build:mixinA"}) 261 }) 262 263 it("requests the expected label", func() { 264 inspectable := newInspectable(returnForLabel(`["mixinX", "mixinY", "build:mixinA"]`)) 265 266 labelManager := builder.NewLabelManager(inspectable) 267 _, err := labelManager.Mixins() 268 assert.Nil(err) 269 270 assert.Equal(inspectable.ReceivedName, "io.buildpacks.stack.mixins") 271 }) 272 273 when("inspectable return empty content for `Label`", func() { 274 it("returns empty stack mixins", func() { 275 inspectable := newInspectable(returnForLabel("")) 276 277 labelManager := builder.NewLabelManager(inspectable) 278 mixins, err := labelManager.Mixins() 279 assert.Nil(err) 280 281 assert.Equal(mixins, []string{}) 282 }) 283 }) 284 285 when("inspectable returns an error for `Label`", func() { 286 it("returns a wrapped error", func() { 287 expectedError := errors.New("couldn't find label") 288 289 inspectable := newInspectable(errorForLabel(expectedError)) 290 291 labelManager := builder.NewLabelManager(inspectable) 292 _, err := labelManager.Mixins() 293 294 assert.ErrorWithMessage( 295 err, 296 "getting label io.buildpacks.stack.mixins: couldn't find label", 297 ) 298 }) 299 }) 300 301 when("inspectable returns invalid json for `Label`", func() { 302 it("returns a wrapped error", func() { 303 inspectable := newInspectable(returnForLabel("{")) 304 305 labelManager := builder.NewLabelManager(inspectable) 306 _, err := labelManager.Mixins() 307 308 assert.ErrorWithMessage( 309 err, 310 "parsing label content for io.buildpacks.stack.mixins: unexpected end of JSON input", 311 ) 312 }) 313 }) 314 }) 315 316 when("Order", func() { 317 var rawOrder = `[{"group": [{"id": "buildpack-1-id", "optional": false}, {"id": "buildpack-2-id", "version": "buildpack-2-version-1", "optional": true}]}]` 318 319 it("returns the order", func() { 320 inspectable := newInspectable(returnForLabel(rawOrder)) 321 322 labelManager := builder.NewLabelManager(inspectable) 323 mixins, err := labelManager.Order() 324 assert.Nil(err) 325 326 expectedOrder := dist.Order{ 327 { 328 Group: []dist.BuildpackRef{ 329 { 330 BuildpackInfo: dist.BuildpackInfo{ 331 ID: "buildpack-1-id", 332 }, 333 }, 334 { 335 BuildpackInfo: dist.BuildpackInfo{ 336 ID: "buildpack-2-id", 337 Version: "buildpack-2-version-1", 338 }, 339 Optional: true, 340 }, 341 }, 342 }, 343 } 344 345 assert.Equal(mixins, expectedOrder) 346 }) 347 348 it("requests the expected label", func() { 349 inspectable := newInspectable(returnForLabel(rawOrder)) 350 351 labelManager := builder.NewLabelManager(inspectable) 352 _, err := labelManager.Order() 353 assert.Nil(err) 354 355 assert.Equal(inspectable.ReceivedName, "io.buildpacks.buildpack.order") 356 }) 357 358 when("inspectable return empty content for `Label`", func() { 359 it("returns an empty order object", func() { 360 inspectable := newInspectable(returnForLabel("")) 361 362 labelManager := builder.NewLabelManager(inspectable) 363 order, err := labelManager.Order() 364 assert.Nil(err) 365 366 assert.Equal(order, dist.Order{}) 367 }) 368 }) 369 370 when("inspectable returns an error for `Label`", func() { 371 it("returns a wrapped error", func() { 372 expectedError := errors.New("couldn't find label") 373 374 inspectable := newInspectable(errorForLabel(expectedError)) 375 376 labelManager := builder.NewLabelManager(inspectable) 377 _, err := labelManager.Order() 378 379 assert.ErrorWithMessage( 380 err, 381 "getting label io.buildpacks.buildpack.order: couldn't find label", 382 ) 383 }) 384 }) 385 386 when("inspectable returns invalid json for `Label`", func() { 387 it("returns a wrapped error", func() { 388 inspectable := newInspectable(returnForLabel("{")) 389 390 labelManager := builder.NewLabelManager(inspectable) 391 _, err := labelManager.Order() 392 393 assert.ErrorWithMessage( 394 err, 395 "parsing label content for io.buildpacks.buildpack.order: unexpected end of JSON input", 396 ) 397 }) 398 }) 399 }) 400 401 when("BuildpackLayers", func() { 402 var rawLayers = ` 403 { 404 "buildpack-1-id": { 405 "buildpack-1-version-1": { 406 "api": "0.1", 407 "layerDiffID": "sha256:buildpack-1-version-1-diff-id" 408 }, 409 "buildpack-1-version-2": { 410 "api": "0.2", 411 "layerDiffID": "sha256:buildpack-1-version-2-diff-id" 412 } 413 } 414 } 415 ` 416 417 it("returns the layers", func() { 418 inspectable := newInspectable(returnForLabel(rawLayers)) 419 420 labelManager := builder.NewLabelManager(inspectable) 421 layers, err := labelManager.BuildpackLayers() 422 assert.Nil(err) 423 424 expectedLayers := dist.BuildpackLayers{ 425 "buildpack-1-id": { 426 "buildpack-1-version-1": dist.BuildpackLayerInfo{ 427 API: api.MustParse("0.1"), 428 LayerDiffID: "sha256:buildpack-1-version-1-diff-id", 429 }, 430 "buildpack-1-version-2": dist.BuildpackLayerInfo{ 431 API: api.MustParse("0.2"), 432 LayerDiffID: "sha256:buildpack-1-version-2-diff-id", 433 }, 434 }, 435 } 436 437 assert.Equal(layers, expectedLayers) 438 }) 439 440 it("requests the expected label", func() { 441 inspectable := newInspectable(returnForLabel(rawLayers)) 442 443 labelManager := builder.NewLabelManager(inspectable) 444 _, err := labelManager.BuildpackLayers() 445 assert.Nil(err) 446 447 assert.Equal(inspectable.ReceivedName, "io.buildpacks.buildpack.layers") 448 }) 449 450 when("inspectable return empty content for `Label`", func() { 451 it("returns an empty buildpack layers object", func() { 452 inspectable := newInspectable(returnForLabel("")) 453 454 labelManager := builder.NewLabelManager(inspectable) 455 layers, err := labelManager.BuildpackLayers() 456 assert.Nil(err) 457 458 assert.Equal(layers, dist.BuildpackLayers{}) 459 }) 460 }) 461 462 when("inspectable returns an error for `Label`", func() { 463 it("returns a wrapped error", func() { 464 expectedError := errors.New("couldn't find label") 465 466 inspectable := newInspectable(errorForLabel(expectedError)) 467 468 labelManager := builder.NewLabelManager(inspectable) 469 _, err := labelManager.BuildpackLayers() 470 471 assert.ErrorWithMessage( 472 err, 473 "getting label io.buildpacks.buildpack.layers: couldn't find label", 474 ) 475 }) 476 }) 477 478 when("inspectable returns invalid json for `Label`", func() { 479 it("returns a wrapped error", func() { 480 inspectable := newInspectable(returnForLabel("{")) 481 482 labelManager := builder.NewLabelManager(inspectable) 483 _, err := labelManager.BuildpackLayers() 484 485 assert.ErrorWithMessage( 486 err, 487 "parsing label content for io.buildpacks.buildpack.layers: unexpected end of JSON input", 488 ) 489 }) 490 }) 491 }) 492 } 493 494 type inspectableModifier func(i *fakes.FakeInspectable) 495 496 func returnForLabel(response string) inspectableModifier { 497 return func(i *fakes.FakeInspectable) { 498 i.ReturnForLabel = response 499 } 500 } 501 502 func errorForLabel(err error) inspectableModifier { 503 return func(i *fakes.FakeInspectable) { 504 i.ErrorForLabel = err 505 } 506 } 507 508 func newInspectable(modifiers ...inspectableModifier) *fakes.FakeInspectable { 509 inspectable := &fakes.FakeInspectable{} 510 511 for _, mod := range modifiers { 512 mod(inspectable) 513 } 514 515 return inspectable 516 }