github.com/buildpacks/pack@v0.33.3-0.20240516162812-884dd1837311/internal/inspectimage/writer/yaml_test.go (about) 1 package writer_test 2 3 import ( 4 "bytes" 5 "testing" 6 7 "github.com/buildpacks/lifecycle/buildpack" 8 "github.com/buildpacks/lifecycle/launch" 9 "github.com/buildpacks/lifecycle/platform/files" 10 "github.com/heroku/color" 11 "github.com/sclevine/spec" 12 "github.com/sclevine/spec/report" 13 14 "github.com/buildpacks/pack/internal/config" 15 "github.com/buildpacks/pack/internal/inspectimage" 16 "github.com/buildpacks/pack/internal/inspectimage/writer" 17 "github.com/buildpacks/pack/pkg/client" 18 "github.com/buildpacks/pack/pkg/logging" 19 h "github.com/buildpacks/pack/testhelpers" 20 ) 21 22 func TestYAML(t *testing.T) { 23 color.Disable(true) 24 defer color.Disable(false) 25 spec.Run(t, "YAML Writer", testYAML, spec.Parallel(), spec.Report(report.Terminal{})) 26 } 27 28 func testYAML(t *testing.T, when spec.G, it spec.S) { 29 var ( 30 assert = h.NewAssertionManager(t) 31 outBuf bytes.Buffer 32 33 remoteInfo *client.ImageInfo 34 remoteInfoNoRebasable *client.ImageInfo 35 localInfo *client.ImageInfo 36 localInfoNoRebasable *client.ImageInfo 37 38 expectedLocalOutput = `--- 39 local_info: 40 stack: test.stack.id.local 41 rebasable: true 42 base_image: 43 top_layer: some-local-top-layer 44 reference: some-local-run-image-reference 45 run_images: 46 - name: user-configured-mirror-for-local 47 user_configured: true 48 - name: some-local-run-image 49 - name: some-local-mirror 50 - name: other-local-mirror 51 buildpacks: 52 - homepage: https://some-homepage-one 53 id: test.bp.one.local 54 version: 1.0.0 55 - homepage: https://some-homepage-two 56 id: test.bp.two.local 57 version: 2.0.0 58 extensions: [] 59 processes: 60 - type: some-local-type 61 shell: bash 62 command: "/some/local command" 63 default: true 64 args: 65 - some 66 - local 67 - args 68 working-dir: /some-test-work-dir 69 - type: other-local-type 70 shell: '' 71 command: "/other/local/command" 72 default: false 73 args: 74 - other 75 - local 76 - args 77 working-dir: /other-test-work-dir 78 ` 79 expectedLocalNoRebasableOutput = `--- 80 local_info: 81 stack: test.stack.id.local 82 rebasable: false 83 base_image: 84 top_layer: some-local-top-layer 85 reference: some-local-run-image-reference 86 run_images: 87 - name: user-configured-mirror-for-local 88 user_configured: true 89 - name: some-local-run-image 90 - name: some-local-mirror 91 - name: other-local-mirror 92 buildpacks: 93 - homepage: https://some-homepage-one 94 id: test.bp.one.local 95 version: 1.0.0 96 - homepage: https://some-homepage-two 97 id: test.bp.two.local 98 version: 2.0.0 99 extensions: [] 100 processes: 101 - type: some-local-type 102 shell: bash 103 command: "/some/local command" 104 default: true 105 args: 106 - some 107 - local 108 - args 109 working-dir: /some-test-work-dir 110 - type: other-local-type 111 shell: '' 112 command: "/other/local/command" 113 default: false 114 args: 115 - other 116 - local 117 - args 118 working-dir: /other-test-work-dir 119 ` 120 expectedRemoteOutput = `--- 121 remote_info: 122 stack: test.stack.id.remote 123 rebasable: true 124 base_image: 125 top_layer: some-remote-top-layer 126 reference: some-remote-run-image-reference 127 run_images: 128 - name: user-configured-mirror-for-remote 129 user_configured: true 130 - name: some-remote-run-image 131 - name: some-remote-mirror 132 - name: other-remote-mirror 133 buildpacks: 134 - homepage: https://some-homepage-one 135 id: test.bp.one.remote 136 version: 1.0.0 137 - homepage: https://some-homepage-two 138 id: test.bp.two.remote 139 version: 2.0.0 140 extensions: [] 141 processes: 142 - type: some-remote-type 143 shell: bash 144 command: "/some/remote command" 145 default: true 146 args: 147 - some 148 - remote 149 - args 150 working-dir: /some-test-work-dir 151 - type: other-remote-type 152 shell: '' 153 command: "/other/remote/command" 154 default: false 155 args: 156 - other 157 - remote 158 - args 159 working-dir: /other-test-work-dir 160 ` 161 expectedRemoteNoRebasableOutput = `--- 162 remote_info: 163 stack: test.stack.id.remote 164 rebasable: false 165 base_image: 166 top_layer: some-remote-top-layer 167 reference: some-remote-run-image-reference 168 run_images: 169 - name: user-configured-mirror-for-remote 170 user_configured: true 171 - name: some-remote-run-image 172 - name: some-remote-mirror 173 - name: other-remote-mirror 174 buildpacks: 175 - homepage: https://some-homepage-one 176 id: test.bp.one.remote 177 version: 1.0.0 178 - homepage: https://some-homepage-two 179 id: test.bp.two.remote 180 version: 2.0.0 181 extensions: [] 182 processes: 183 - type: some-remote-type 184 shell: bash 185 command: "/some/remote command" 186 default: true 187 args: 188 - some 189 - remote 190 - args 191 working-dir: /some-test-work-dir 192 - type: other-remote-type 193 shell: '' 194 command: "/other/remote/command" 195 default: false 196 args: 197 - other 198 - remote 199 - args 200 working-dir: /other-test-work-dir 201 ` 202 ) 203 204 when("Print", func() { 205 it.Before(func() { 206 type someData struct { 207 String string 208 Bool bool 209 Int int 210 Nested struct { 211 String string 212 } 213 } 214 215 remoteInfo = &client.ImageInfo{ 216 StackID: "test.stack.id.remote", 217 Buildpacks: []buildpack.GroupElement{ 218 {ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, 219 {ID: "test.bp.two.remote", Version: "2.0.0", Homepage: "https://some-homepage-two"}, 220 }, 221 Base: files.RunImageForRebase{ 222 TopLayer: "some-remote-top-layer", 223 Reference: "some-remote-run-image-reference", 224 }, 225 Stack: files.Stack{ 226 RunImage: files.RunImageForExport{ 227 Image: "some-remote-run-image", 228 Mirrors: []string{"some-remote-mirror", "other-remote-mirror"}, 229 }, 230 }, 231 BOM: []buildpack.BOMEntry{{ 232 Require: buildpack.Require{ 233 Name: "name-1", 234 Version: "version-1", 235 Metadata: map[string]interface{}{ 236 "RemoteData": someData{ 237 String: "aString", 238 Bool: true, 239 Int: 123, 240 Nested: struct { 241 String string 242 }{ 243 String: "anotherString", 244 }, 245 }, 246 }, 247 }, 248 Buildpack: buildpack.GroupElement{ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, 249 }}, 250 Processes: client.ProcessDetails{ 251 DefaultProcess: &launch.Process{ 252 Type: "some-remote-type", 253 Command: launch.RawCommand{Entries: []string{"/some/remote command"}}, 254 Args: []string{"some", "remote", "args"}, 255 Direct: false, 256 WorkingDirectory: "/some-test-work-dir", 257 }, 258 OtherProcesses: []launch.Process{ 259 { 260 Type: "other-remote-type", 261 Command: launch.RawCommand{Entries: []string{"/other/remote/command"}}, 262 Args: []string{"other", "remote", "args"}, 263 Direct: true, 264 WorkingDirectory: "/other-test-work-dir", 265 }, 266 }, 267 }, 268 Rebasable: true, 269 } 270 remoteInfoNoRebasable = &client.ImageInfo{ 271 StackID: "test.stack.id.remote", 272 Buildpacks: []buildpack.GroupElement{ 273 {ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, 274 {ID: "test.bp.two.remote", Version: "2.0.0", Homepage: "https://some-homepage-two"}, 275 }, 276 Base: files.RunImageForRebase{ 277 TopLayer: "some-remote-top-layer", 278 Reference: "some-remote-run-image-reference", 279 }, 280 Stack: files.Stack{ 281 RunImage: files.RunImageForExport{ 282 Image: "some-remote-run-image", 283 Mirrors: []string{"some-remote-mirror", "other-remote-mirror"}, 284 }, 285 }, 286 BOM: []buildpack.BOMEntry{{ 287 Require: buildpack.Require{ 288 Name: "name-1", 289 Version: "version-1", 290 Metadata: map[string]interface{}{ 291 "RemoteData": someData{ 292 String: "aString", 293 Bool: true, 294 Int: 123, 295 Nested: struct { 296 String string 297 }{ 298 String: "anotherString", 299 }, 300 }, 301 }, 302 }, 303 Buildpack: buildpack.GroupElement{ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, 304 }}, 305 Processes: client.ProcessDetails{ 306 DefaultProcess: &launch.Process{ 307 Type: "some-remote-type", 308 Command: launch.RawCommand{Entries: []string{"/some/remote command"}}, 309 Args: []string{"some", "remote", "args"}, 310 Direct: false, 311 WorkingDirectory: "/some-test-work-dir", 312 }, 313 OtherProcesses: []launch.Process{ 314 { 315 Type: "other-remote-type", 316 Command: launch.RawCommand{Entries: []string{"/other/remote/command"}}, 317 Args: []string{"other", "remote", "args"}, 318 Direct: true, 319 WorkingDirectory: "/other-test-work-dir", 320 }, 321 }, 322 }, 323 Rebasable: false, 324 } 325 326 localInfo = &client.ImageInfo{ 327 StackID: "test.stack.id.local", 328 Buildpacks: []buildpack.GroupElement{ 329 {ID: "test.bp.one.local", Version: "1.0.0", Homepage: "https://some-homepage-one"}, 330 {ID: "test.bp.two.local", Version: "2.0.0", Homepage: "https://some-homepage-two"}, 331 }, 332 Base: files.RunImageForRebase{ 333 TopLayer: "some-local-top-layer", 334 Reference: "some-local-run-image-reference", 335 }, 336 Stack: files.Stack{ 337 RunImage: files.RunImageForExport{ 338 Image: "some-local-run-image", 339 Mirrors: []string{"some-local-mirror", "other-local-mirror"}, 340 }, 341 }, 342 BOM: []buildpack.BOMEntry{{ 343 Require: buildpack.Require{ 344 Name: "name-1", 345 Version: "version-1", 346 Metadata: map[string]interface{}{ 347 "LocalData": someData{ 348 Bool: false, 349 Int: 456, 350 }, 351 }, 352 }, 353 Buildpack: buildpack.GroupElement{ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, 354 }}, 355 Processes: client.ProcessDetails{ 356 DefaultProcess: &launch.Process{ 357 Type: "some-local-type", 358 Command: launch.RawCommand{Entries: []string{"/some/local command"}}, 359 Args: []string{"some", "local", "args"}, 360 Direct: false, 361 WorkingDirectory: "/some-test-work-dir", 362 }, 363 OtherProcesses: []launch.Process{ 364 { 365 Type: "other-local-type", 366 Command: launch.RawCommand{Entries: []string{"/other/local/command"}}, 367 Args: []string{"other", "local", "args"}, 368 Direct: true, 369 WorkingDirectory: "/other-test-work-dir", 370 }, 371 }, 372 }, 373 Rebasable: true, 374 } 375 localInfoNoRebasable = &client.ImageInfo{ 376 StackID: "test.stack.id.local", 377 Buildpacks: []buildpack.GroupElement{ 378 {ID: "test.bp.one.local", Version: "1.0.0", Homepage: "https://some-homepage-one"}, 379 {ID: "test.bp.two.local", Version: "2.0.0", Homepage: "https://some-homepage-two"}, 380 }, 381 Base: files.RunImageForRebase{ 382 TopLayer: "some-local-top-layer", 383 Reference: "some-local-run-image-reference", 384 }, 385 Stack: files.Stack{ 386 RunImage: files.RunImageForExport{ 387 Image: "some-local-run-image", 388 Mirrors: []string{"some-local-mirror", "other-local-mirror"}, 389 }, 390 }, 391 BOM: []buildpack.BOMEntry{{ 392 Require: buildpack.Require{ 393 Name: "name-1", 394 Version: "version-1", 395 Metadata: map[string]interface{}{ 396 "LocalData": someData{ 397 Bool: false, 398 Int: 456, 399 }, 400 }, 401 }, 402 Buildpack: buildpack.GroupElement{ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, 403 }}, 404 Processes: client.ProcessDetails{ 405 DefaultProcess: &launch.Process{ 406 Type: "some-local-type", 407 Command: launch.RawCommand{Entries: []string{"/some/local command"}}, 408 Args: []string{"some", "local", "args"}, 409 Direct: false, 410 WorkingDirectory: "/some-test-work-dir", 411 }, 412 OtherProcesses: []launch.Process{ 413 { 414 Type: "other-local-type", 415 Command: launch.RawCommand{Entries: []string{"/other/local/command"}}, 416 Args: []string{"other", "local", "args"}, 417 Direct: true, 418 WorkingDirectory: "/other-test-work-dir", 419 }, 420 }, 421 }, 422 Rebasable: false, 423 } 424 425 outBuf = bytes.Buffer{} 426 }) 427 428 when("local and remote image exits", func() { 429 it("prints both local and remote image info in a YAML format", func() { 430 runImageMirrors := []config.RunImage{ 431 { 432 Image: "un-used-run-image", 433 Mirrors: []string{"un-used"}, 434 }, 435 { 436 Image: "some-local-run-image", 437 Mirrors: []string{"user-configured-mirror-for-local"}, 438 }, 439 { 440 Image: "some-remote-run-image", 441 Mirrors: []string{"user-configured-mirror-for-remote"}, 442 }, 443 } 444 sharedImageInfo := inspectimage.GeneralInfo{ 445 Name: "test-image", 446 RunImageMirrors: runImageMirrors, 447 } 448 yamlWriter := writer.NewYAML() 449 450 logger := logging.NewLogWithWriters(&outBuf, &outBuf) 451 err := yamlWriter.Print(logger, sharedImageInfo, localInfo, remoteInfo, nil, nil) 452 assert.Nil(err) 453 454 assert.ContainsYAML(outBuf.String(), `"image_name": "test-image"`) 455 assert.ContainsYAML(outBuf.String(), expectedLocalOutput) 456 assert.ContainsYAML(outBuf.String(), expectedRemoteOutput) 457 }) 458 it("prints both local and remote no rebasable images info in a YAML format", func() { 459 runImageMirrors := []config.RunImage{ 460 { 461 Image: "un-used-run-image", 462 Mirrors: []string{"un-used"}, 463 }, 464 { 465 Image: "some-local-run-image", 466 Mirrors: []string{"user-configured-mirror-for-local"}, 467 }, 468 { 469 Image: "some-remote-run-image", 470 Mirrors: []string{"user-configured-mirror-for-remote"}, 471 }, 472 } 473 sharedImageInfo := inspectimage.GeneralInfo{ 474 Name: "test-image", 475 RunImageMirrors: runImageMirrors, 476 } 477 yamlWriter := writer.NewYAML() 478 479 logger := logging.NewLogWithWriters(&outBuf, &outBuf) 480 err := yamlWriter.Print(logger, sharedImageInfo, localInfoNoRebasable, remoteInfoNoRebasable, nil, nil) 481 assert.Nil(err) 482 483 assert.ContainsYAML(outBuf.String(), `"image_name": "test-image"`) 484 assert.ContainsYAML(outBuf.String(), expectedLocalNoRebasableOutput) 485 assert.ContainsYAML(outBuf.String(), expectedRemoteNoRebasableOutput) 486 }) 487 }) 488 489 when("only local image exists", func() { 490 it("prints local image info in YAML format", func() { 491 runImageMirrors := []config.RunImage{ 492 { 493 Image: "un-used-run-image", 494 Mirrors: []string{"un-used"}, 495 }, 496 { 497 Image: "some-local-run-image", 498 Mirrors: []string{"user-configured-mirror-for-local"}, 499 }, 500 { 501 Image: "some-remote-run-image", 502 Mirrors: []string{"user-configured-mirror-for-remote"}, 503 }, 504 } 505 sharedImageInfo := inspectimage.GeneralInfo{ 506 Name: "test-image", 507 RunImageMirrors: runImageMirrors, 508 } 509 yamlWriter := writer.NewYAML() 510 511 logger := logging.NewLogWithWriters(&outBuf, &outBuf) 512 err := yamlWriter.Print(logger, sharedImageInfo, localInfo, nil, nil, nil) 513 assert.Nil(err) 514 515 assert.ContainsYAML(outBuf.String(), `"image_name": "test-image"`) 516 assert.ContainsYAML(outBuf.String(), expectedLocalOutput) 517 assert.NotContains(outBuf.String(), "test.stack.id.remote") 518 }) 519 }) 520 521 when("only remote image exists", func() { 522 it("prints remote image info in YAML format", func() { 523 runImageMirrors := []config.RunImage{ 524 { 525 Image: "un-used-run-image", 526 Mirrors: []string{"un-used"}, 527 }, 528 { 529 Image: "some-local-run-image", 530 Mirrors: []string{"user-configured-mirror-for-local"}, 531 }, 532 { 533 Image: "some-remote-run-image", 534 Mirrors: []string{"user-configured-mirror-for-remote"}, 535 }, 536 } 537 sharedImageInfo := inspectimage.GeneralInfo{ 538 Name: "test-image", 539 RunImageMirrors: runImageMirrors, 540 } 541 yamlWriter := writer.NewYAML() 542 543 logger := logging.NewLogWithWriters(&outBuf, &outBuf) 544 err := yamlWriter.Print(logger, sharedImageInfo, nil, remoteInfo, nil, nil) 545 assert.Nil(err) 546 547 assert.ContainsYAML(outBuf.String(), `"image_name": "test-image"`) 548 assert.NotContains(outBuf.String(), "test.stack.id.local") 549 assert.ContainsYAML(outBuf.String(), expectedRemoteOutput) 550 }) 551 }) 552 }) 553 }