From 26535882a448c82e2ce489e617c2d643167a0cf5 Mon Sep 17 00:00:00 2001 From: Domenico Luciani Date: Fri, 16 Jun 2023 08:45:15 +0200 Subject: [PATCH 01/11] Introduces the rebasable label into the human readable output for local rebasable images Signed-off-by: Domenico Luciani --- internal/inspectimage/info_display.go | 2 + .../inspectimage/writer/human_readable.go | 14 ++- .../writer/human_readable_test.go | 111 +++++++++++++++++- pkg/client/inspect_image.go | 3 + 4 files changed, 126 insertions(+), 4 deletions(-) diff --git a/internal/inspectimage/info_display.go b/internal/inspectimage/info_display.go index f7b1e4056..db842812d 100644 --- a/internal/inspectimage/info_display.go +++ b/internal/inspectimage/info_display.go @@ -46,6 +46,7 @@ type InfoDisplay struct { Buildpacks []dist.ModuleInfo `json:"buildpacks" yaml:"buildpacks" toml:"buildpacks"` Extensions []dist.ModuleInfo `json:"extensions" yaml:"extensions" toml:"extensions"` Processes []ProcessDisplay `json:"processes" yaml:"processes" toml:"processes"` + Rebasable bool `json:"rebasable" yaml:"rebasable" toml:"rebasable"` } type InspectOutput struct { @@ -74,6 +75,7 @@ func NewInfoDisplay(info *client.ImageInfo, generalInfo GeneralInfo) *InfoDispla RunImageMirrors: displayMirrors(info, generalInfo), Buildpacks: displayBuildpacks(info.Buildpacks), Processes: displayProcesses(info.Processes), + Rebasable: info.Rebasable, } } diff --git a/internal/inspectimage/writer/human_readable.go b/internal/inspectimage/writer/human_readable.go index 3883b2501..4215a06d3 100644 --- a/internal/inspectimage/writer/human_readable.go +++ b/internal/inspectimage/writer/human_readable.go @@ -58,13 +58,15 @@ func writeImageInfo( Funcs(template.FuncMap{"StringsJoin": strings.Join}). Funcs(template.FuncMap{"StringsValueOrDefault": strs.ValueOrDefault}). Parse(runImagesTemplate)) - imgTpl = template.Must(imgTpl.New("buildpacks"). - Parse(buildpacksTemplate)) + imgTpl = template.Must(imgTpl.New("buildpacks").Parse(buildpacksTemplate)) if info != nil && info.Extensions != nil { imgTpl = template.Must(imgTpl.New("extensions").Parse(extensionsTemplate)) } imgTpl = template.Must(imgTpl.New("processes"). Parse(processesTemplate)) + + imgTpl = template.Must(imgTpl.New("rebasable").Parse(rebasableTemplate)) + if info != nil && info.Extensions != nil { imgTpl = template.Must(imgTpl.New("image"). Parse(imageWithExtensionTemplate)) @@ -72,6 +74,7 @@ func writeImageInfo( imgTpl = template.Must(imgTpl.New("image"). Parse(imageTemplate)) } + if err != nil { logger.Errorf("%s\n", err) return nil @@ -158,6 +161,12 @@ Processes: {{- end }} {{- end }}` +var rebasableTemplate = ` +{{- if .Info.Rebasable -}} +{{- "\n\n" -}} +Rebasable: true +{{- end -}}` + var imageTemplate = ` Stack: {{ .Info.StackID }} @@ -167,6 +176,7 @@ Base Image: {{- end}} Top Layer: {{ .Info.Base.TopLayer }} {{ template "runImages" . }} +{{- template "rebasable" . }} {{ template "buildpacks" . }}{{ template "processes" . }}` var imageWithExtensionTemplate = ` diff --git a/internal/inspectimage/writer/human_readable_test.go b/internal/inspectimage/writer/human_readable_test.go index 54369b79d..5624035c4 100644 --- a/internal/inspectimage/writer/human_readable_test.go +++ b/internal/inspectimage/writer/human_readable_test.go @@ -32,8 +32,9 @@ func testHumanReadable(t *testing.T, when spec.G, it spec.S) { assert = h.NewAssertionManager(t) outBuf bytes.Buffer - remoteInfo *client.ImageInfo - localInfo *client.ImageInfo + remoteInfo *client.ImageInfo + localInfo *client.ImageInfo + localInfoWithRebasable *client.ImageInfo remoteWithExtensionInfo *client.ImageInfo localWithExtensionInfo *client.ImageInfo @@ -77,6 +78,33 @@ Run Images: some-local-mirror other-local-mirror +Buildpacks: + ID VERSION HOMEPAGE + test.bp.one.local 1.0.0 https://some-homepage-one + test.bp.two.local 2.0.0 https://some-homepage-two + test.bp.three.local 3.0.0 - + +Processes: + TYPE SHELL COMMAND ARGS WORK DIR + some-local-type (default) bash /some/local command some local args /some-test-work-dir + other-local-type /other/local/command other local args /other-test-work-dir` + + expectedLocalOutputWithRebasable = `LOCAL: + +Stack: test.stack.id.local + +Base Image: + Reference: some-local-run-image-reference + Top Layer: some-local-top-layer + +Run Images: + user-configured-mirror-for-local (user-configured) + some-local-run-image + some-local-mirror + other-local-mirror + +Rebasable: true + Buildpacks: ID VERSION HOMEPAGE test.bp.one.local 1.0.0 https://some-homepage-one @@ -270,6 +298,57 @@ Processes: }, } + localInfoWithRebasable = &client.ImageInfo{ + StackID: "test.stack.id.local", + Buildpacks: []buildpack.GroupElement{ + {ID: "test.bp.one.local", Version: "1.0.0", Homepage: "https://some-homepage-one"}, + {ID: "test.bp.two.local", Version: "2.0.0", Homepage: "https://some-homepage-two"}, + {ID: "test.bp.three.local", Version: "3.0.0"}, + }, + Base: platform.RunImageForRebase{ + TopLayer: "some-local-top-layer", + Reference: "some-local-run-image-reference", + }, + Stack: platform.StackMetadata{ + RunImage: platform.RunImageForExport{ + Image: "some-local-run-image", + Mirrors: []string{"some-local-mirror", "other-local-mirror"}, + }, + }, + BOM: []buildpack.BOMEntry{{ + Require: buildpack.Require{ + Name: "name-1", + Version: "version-1", + Metadata: map[string]interface{}{ + "LocalData": someData{ + Bool: false, + Int: 456, + }, + }, + }, + Buildpack: buildpack.GroupElement{ID: "test.bp.one.remote", Version: "1.0.0"}, + }}, + Processes: client.ProcessDetails{ + DefaultProcess: &launch.Process{ + Type: "some-local-type", + Command: launch.RawCommand{Entries: []string{"/some/local command"}}, + Args: []string{"some", "local", "args"}, + Direct: false, + WorkingDirectory: "/some-test-work-dir", + }, + OtherProcesses: []launch.Process{ + { + Type: "other-local-type", + Command: launch.RawCommand{Entries: []string{"/other/local/command"}}, + Args: []string{"other", "local", "args"}, + Direct: true, + WorkingDirectory: "/other-test-work-dir", + }, + }, + }, + Rebasable: true, + } + remoteWithExtensionInfo = &client.ImageInfo{ StackID: "test.stack.id.remote", Buildpacks: []buildpack.GroupElement{ @@ -480,6 +559,34 @@ Processes: assert.Contains(outBuf.String(), expectedLocalOutput) assert.NotContains(outBuf.String(), expectedRemoteOutput) }) + it("prints local rebasable image info in a human readable format", func() { + runImageMirrors := []config.RunImage{ + { + Image: "un-used-run-image", + Mirrors: []string{"un-used"}, + }, + { + Image: "some-local-run-image", + Mirrors: []string{"user-configured-mirror-for-local"}, + }, + { + Image: "some-remote-run-image", + Mirrors: []string{"user-configured-mirror-for-remote"}, + }, + } + sharedImageInfo := inspectimage.GeneralInfo{ + Name: "test-image", + RunImageMirrors: runImageMirrors, + } + humanReadableWriter := writer.NewHumanReadable() + + logger := logging.NewLogWithWriters(&outBuf, &outBuf) + err := humanReadableWriter.Print(logger, sharedImageInfo, localInfoWithRebasable, nil, nil, nil) + assert.Nil(err) + + assert.Contains(outBuf.String(), expectedLocalOutputWithRebasable) + assert.NotContains(outBuf.String(), expectedRemoteOutput) + }) }) when("only localWithExtension image exists", func() { diff --git a/pkg/client/inspect_image.go b/pkg/client/inspect_image.go index e56ef4b6b..abd3df128 100644 --- a/pkg/client/inspect_image.go +++ b/pkg/client/inspect_image.go @@ -55,6 +55,9 @@ type ImageInfo struct { // Processes lists all processes contributed by buildpacks. Processes ProcessDetails + + // If the image can be rebased + Rebasable bool } // ProcessDetails is a collection of all start command metadata From 83bbe1f754ec858818763629288f1230f83c0506 Mon Sep 17 00:00:00 2001 From: Domenico Luciani Date: Fri, 16 Jun 2023 09:57:23 +0200 Subject: [PATCH 02/11] Adds test for the remote rebasable image Signed-off-by: Domenico Luciani --- .../writer/human_readable_test.go | 119 +++++++++++++++++- 1 file changed, 116 insertions(+), 3 deletions(-) diff --git a/internal/inspectimage/writer/human_readable_test.go b/internal/inspectimage/writer/human_readable_test.go index 5624035c4..4ffd0b259 100644 --- a/internal/inspectimage/writer/human_readable_test.go +++ b/internal/inspectimage/writer/human_readable_test.go @@ -32,9 +32,10 @@ func testHumanReadable(t *testing.T, when spec.G, it spec.S) { assert = h.NewAssertionManager(t) outBuf bytes.Buffer - remoteInfo *client.ImageInfo - localInfo *client.ImageInfo - localInfoWithRebasable *client.ImageInfo + remoteInfo *client.ImageInfo + remoteInfoWithRebasable *client.ImageInfo + localInfo *client.ImageInfo + localInfoWithRebasable *client.ImageInfo remoteWithExtensionInfo *client.ImageInfo localWithExtensionInfo *client.ImageInfo @@ -53,6 +54,33 @@ Run Images: some-remote-mirror other-remote-mirror +Buildpacks: + ID VERSION HOMEPAGE + test.bp.one.remote 1.0.0 https://some-homepage-one + test.bp.two.remote 2.0.0 https://some-homepage-two + test.bp.three.remote 3.0.0 - + +Processes: + TYPE SHELL COMMAND ARGS WORK DIR + some-remote-type (default) bash /some/remote command some remote args /some-test-work-dir + other-remote-type /other/remote/command other remote args /other-test-work-dir` + + expectedRemoteOutputWithRebasable = `REMOTE: + +Stack: test.stack.id.remote + +Base Image: + Reference: some-remote-run-image-reference + Top Layer: some-remote-top-layer + +Run Images: + user-configured-mirror-for-remote (user-configured) + some-remote-run-image + some-remote-mirror + other-remote-mirror + +Rebasable: true + Buildpacks: ID VERSION HOMEPAGE test.bp.one.remote 1.0.0 https://some-homepage-one @@ -248,6 +276,63 @@ Processes: }, } + remoteInfoWithRebasable = &client.ImageInfo{ + StackID: "test.stack.id.remote", + Buildpacks: []buildpack.GroupElement{ + {ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, + {ID: "test.bp.two.remote", Version: "2.0.0", Homepage: "https://some-homepage-two"}, + {ID: "test.bp.three.remote", Version: "3.0.0"}, + }, + Base: platform.RunImageForRebase{ + TopLayer: "some-remote-top-layer", + Reference: "some-remote-run-image-reference", + }, + Stack: platform.StackMetadata{ + RunImage: platform.RunImageForExport{ + Image: "some-remote-run-image", + Mirrors: []string{"some-remote-mirror", "other-remote-mirror"}, + }, + }, + BOM: []buildpack.BOMEntry{{ + Require: buildpack.Require{ + Name: "name-1", + Version: "version-1", + Metadata: map[string]interface{}{ + "RemoteData": someData{ + String: "aString", + Bool: true, + Int: 123, + Nested: struct { + String string + }{ + String: "anotherString", + }, + }, + }, + }, + Buildpack: buildpack.GroupElement{ID: "test.bp.one.remote", Version: "1.0.0"}, + }}, + Processes: client.ProcessDetails{ + DefaultProcess: &launch.Process{ + Type: "some-remote-type", + Command: launch.RawCommand{Entries: []string{"/some/remote command"}}, + Args: []string{"some", "remote", "args"}, + Direct: false, + WorkingDirectory: "/some-test-work-dir", + }, + OtherProcesses: []launch.Process{ + { + Type: "other-remote-type", + Command: launch.RawCommand{Entries: []string{"/other/remote/command"}}, + Args: []string{"other", "remote", "args"}, + Direct: true, + WorkingDirectory: "/other-test-work-dir", + }, + }, + }, + Rebasable: true, + } + localInfo = &client.ImageInfo{ StackID: "test.stack.id.local", Buildpacks: []buildpack.GroupElement{ @@ -649,6 +734,34 @@ Processes: assert.NotContains(outBuf.String(), expectedLocalOutput) assert.Contains(outBuf.String(), expectedRemoteOutput) }) + it("prints remote rebasable image info in a human readable format", func() { + runImageMirrors := []config.RunImage{ + { + Image: "un-used-run-image", + Mirrors: []string{"un-used"}, + }, + { + Image: "some-local-run-image", + Mirrors: []string{"user-configured-mirror-for-local"}, + }, + { + Image: "some-remote-run-image", + Mirrors: []string{"user-configured-mirror-for-remote"}, + }, + } + sharedImageInfo := inspectimage.GeneralInfo{ + Name: "test-image", + RunImageMirrors: runImageMirrors, + } + humanReadableWriter := writer.NewHumanReadable() + + logger := logging.NewLogWithWriters(&outBuf, &outBuf) + err := humanReadableWriter.Print(logger, sharedImageInfo, nil, remoteInfoWithRebasable, nil, nil) + assert.Nil(err) + + assert.Contains(outBuf.String(), expectedRemoteOutputWithRebasable) + assert.NotContains(outBuf.String(), expectedLocalOutput) + }) when("buildpack metadata is missing", func() { it.Before(func() { From 23174d127f061ff397c5aa37f095d451138f5a4b Mon Sep 17 00:00:00 2001 From: Domenico Luciani Date: Fri, 16 Jun 2023 10:00:52 +0200 Subject: [PATCH 03/11] Fixs toml tests and adds tests fort the local and remote rebasable images Signed-off-by: Domenico Luciani --- internal/inspectimage/writer/toml_test.go | 284 +++++++++++++++++++++- 1 file changed, 282 insertions(+), 2 deletions(-) diff --git a/internal/inspectimage/writer/toml_test.go b/internal/inspectimage/writer/toml_test.go index 0e1406df6..bae26d643 100644 --- a/internal/inspectimage/writer/toml_test.go +++ b/internal/inspectimage/writer/toml_test.go @@ -30,11 +30,70 @@ func testTOML(t *testing.T, when spec.G, it spec.S) { assert = h.NewAssertionManager(t) outBuf bytes.Buffer - remoteInfo *client.ImageInfo - localInfo *client.ImageInfo + remoteInfo *client.ImageInfo + remoteInfoWithRebasable *client.ImageInfo + localInfo *client.ImageInfo + localInfoWithRebasable *client.ImageInfo expectedLocalOutput = `[local_info] stack = 'test.stack.id.local' +rebasable = false + +[local_info.base_image] +top_layer = 'some-local-top-layer' +reference = 'some-local-run-image-reference' + +[[local_info.run_images]] +name = 'user-configured-mirror-for-local' +user_configured = true + +[[local_info.run_images]] +name = 'some-local-run-image' + +[[local_info.run_images]] +name = 'some-local-mirror' + +[[local_info.run_images]] +name = 'other-local-mirror' + +[[local_info.buildpacks]] +id = 'test.bp.one.local' +version = '1.0.0' +homepage = 'https://some-homepage-one' + +[[local_info.buildpacks]] +id = 'test.bp.two.local' +version = '2.0.0' +homepage = 'https://some-homepage-two' + +[[local_info.processes]] +type = 'some-local-type' +shell = 'bash' +command = '/some/local command' +default = true +args = [ + 'some', + 'local', + 'args', +] +working-dir = "/some-test-work-dir" + +[[local_info.processes]] +type = 'other-local-type' +shell = '' +command = '/other/local/command' +default = false +args = [ + 'other', + 'local', + 'args', +] +working-dir = "/other-test-work-dir" +` + + expectedLocalOutputWithRebasable = `[local_info] +stack = 'test.stack.id.local' +rebasable = true [local_info.base_image] top_layer = 'some-local-top-layer' @@ -91,6 +150,64 @@ working-dir = "/other-test-work-dir" expectedRemoteOutput = ` [remote_info] stack = 'test.stack.id.remote' +rebasable = false + +[remote_info.base_image] +top_layer = 'some-remote-top-layer' +reference = 'some-remote-run-image-reference' + +[[remote_info.run_images]] +name = 'user-configured-mirror-for-remote' +user_configured = true + +[[remote_info.run_images]] +name = 'some-remote-run-image' + +[[remote_info.run_images]] +name = 'some-remote-mirror' + +[[remote_info.run_images]] +name = 'other-remote-mirror' + +[[remote_info.buildpacks]] +id = 'test.bp.one.remote' +version = '1.0.0' +homepage = 'https://some-homepage-one' + +[[remote_info.buildpacks]] +id = 'test.bp.two.remote' +version = '2.0.0' +homepage = 'https://some-homepage-two' + +[[remote_info.processes]] +type = 'some-remote-type' +shell = 'bash' +command = '/some/remote command' +default = true +args = [ + 'some', + 'remote', + 'args', +] +working-dir = "/some-test-work-dir" + +[[remote_info.processes]] +type = 'other-remote-type' +shell = '' +command = '/other/remote/command' +default = false +args = [ + 'other', + 'remote', + 'args', +] +working-dir = "/other-test-work-dir" +` + + expectedRemoteOutputWithRebasable = ` +[remote_info] +stack = 'test.stack.id.remote' +rebasable = true [remote_info.base_image] top_layer = 'some-remote-top-layer' @@ -210,6 +327,61 @@ working-dir = "/other-test-work-dir" }, }, } + remoteInfoWithRebasable = &client.ImageInfo{ + StackID: "test.stack.id.remote", + Buildpacks: []buildpack.GroupElement{ + {ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, + {ID: "test.bp.two.remote", Version: "2.0.0", Homepage: "https://some-homepage-two"}, + }, + Base: platform.RunImageForRebase{ + TopLayer: "some-remote-top-layer", + Reference: "some-remote-run-image-reference", + }, + Stack: platform.StackMetadata{ + RunImage: platform.RunImageForExport{ + Image: "some-remote-run-image", + Mirrors: []string{"some-remote-mirror", "other-remote-mirror"}, + }, + }, + BOM: []buildpack.BOMEntry{{ + Require: buildpack.Require{ + Name: "name-1", + Version: "version-1", + Metadata: map[string]interface{}{ + "RemoteData": someData{ + String: "aString", + Bool: true, + Int: 123, + Nested: struct { + String string + }{ + String: "anotherString", + }, + }, + }, + }, + Buildpack: buildpack.GroupElement{ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, + }}, + Processes: client.ProcessDetails{ + DefaultProcess: &launch.Process{ + Type: "some-remote-type", + Command: launch.RawCommand{Entries: []string{"/some/remote command"}}, + Args: []string{"some", "remote", "args"}, + Direct: false, + WorkingDirectory: "/some-test-work-dir", + }, + OtherProcesses: []launch.Process{ + { + Type: "other-remote-type", + Command: launch.RawCommand{Entries: []string{"/other/remote/command"}}, + Args: []string{"other", "remote", "args"}, + Direct: true, + WorkingDirectory: "/other-test-work-dir", + }, + }, + }, + Rebasable: true, + } localInfo = &client.ImageInfo{ StackID: "test.stack.id.local", @@ -260,6 +432,56 @@ working-dir = "/other-test-work-dir" }, } + localInfoWithRebasable = &client.ImageInfo{ + StackID: "test.stack.id.local", + Buildpacks: []buildpack.GroupElement{ + {ID: "test.bp.one.local", Version: "1.0.0", Homepage: "https://some-homepage-one"}, + {ID: "test.bp.two.local", Version: "2.0.0", Homepage: "https://some-homepage-two"}, + }, + Base: platform.RunImageForRebase{ + TopLayer: "some-local-top-layer", + Reference: "some-local-run-image-reference", + }, + Stack: platform.StackMetadata{ + RunImage: platform.RunImageForExport{ + Image: "some-local-run-image", + Mirrors: []string{"some-local-mirror", "other-local-mirror"}, + }, + }, + BOM: []buildpack.BOMEntry{{ + Require: buildpack.Require{ + Name: "name-1", + Version: "version-1", + Metadata: map[string]interface{}{ + "LocalData": someData{ + Bool: false, + Int: 456, + }, + }, + }, + Buildpack: buildpack.GroupElement{ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, + }}, + Processes: client.ProcessDetails{ + DefaultProcess: &launch.Process{ + Type: "some-local-type", + Command: launch.RawCommand{Entries: []string{"/some/local command"}}, + Args: []string{"some", "local", "args"}, + Direct: false, + WorkingDirectory: "/some-test-work-dir", + }, + OtherProcesses: []launch.Process{ + { + Type: "other-local-type", + Command: launch.RawCommand{Entries: []string{"/other/local/command"}}, + Args: []string{"other", "local", "args"}, + Direct: true, + WorkingDirectory: "/other-test-work-dir", + }, + }, + }, + Rebasable: true, + } + outBuf = bytes.Buffer{} }) @@ -325,6 +547,35 @@ working-dir = "/other-test-work-dir" assert.NotContains(outBuf.String(), "test.stack.id.remote") assert.ContainsTOML(outBuf.String(), expectedLocalOutput) }) + it("prints local rebasable image info in TOML format", func() { + runImageMirrors := []config.RunImage{ + { + Image: "un-used-run-image", + Mirrors: []string{"un-used"}, + }, + { + Image: "some-local-run-image", + Mirrors: []string{"user-configured-mirror-for-local"}, + }, + { + Image: "some-remote-run-image", + Mirrors: []string{"user-configured-mirror-for-remote"}, + }, + } + sharedImageInfo := inspectimage.GeneralInfo{ + Name: "test-image", + RunImageMirrors: runImageMirrors, + } + tomlWriter := writer.NewTOML() + + logger := logging.NewLogWithWriters(&outBuf, &outBuf) + err := tomlWriter.Print(logger, sharedImageInfo, localInfoWithRebasable, nil, nil, nil) + assert.Nil(err) + + assert.ContainsTOML(outBuf.String(), `image_name = "test-image"`) + assert.NotContains(outBuf.String(), "test.stack.id.remote") + assert.ContainsTOML(outBuf.String(), expectedLocalOutputWithRebasable) + }) }) when("only remote image exists", func() { @@ -357,6 +608,35 @@ working-dir = "/other-test-work-dir" assert.NotContains(outBuf.String(), "test.stack.id.local") assert.ContainsTOML(outBuf.String(), expectedRemoteOutput) }) + it("prints remote rebasable image info in TOML format", func() { + runImageMirrors := []config.RunImage{ + { + Image: "un-used-run-image", + Mirrors: []string{"un-used"}, + }, + { + Image: "some-local-run-image", + Mirrors: []string{"user-configured-mirror-for-local"}, + }, + { + Image: "some-remote-run-image", + Mirrors: []string{"user-configured-mirror-for-remote"}, + }, + } + sharedImageInfo := inspectimage.GeneralInfo{ + Name: "test-image", + RunImageMirrors: runImageMirrors, + } + tomlWriter := writer.NewTOML() + + logger := logging.NewLogWithWriters(&outBuf, &outBuf) + err := tomlWriter.Print(logger, sharedImageInfo, nil, remoteInfoWithRebasable, nil, nil) + assert.Nil(err) + + assert.ContainsTOML(outBuf.String(), `image_name = "test-image"`) + assert.NotContains(outBuf.String(), "test.stack.id.local") + assert.ContainsTOML(outBuf.String(), expectedRemoteOutputWithRebasable) + }) }) }) } From 56566db5a4deb266c1eda741950f5a0eefb040cb Mon Sep 17 00:00:00 2001 From: Domenico Luciani Date: Fri, 16 Jun 2023 11:54:15 +0200 Subject: [PATCH 04/11] Fixs yaml tests and adds test for local and remote the rebasable images Signed-off-by: Domenico Luciani --- internal/inspectimage/writer/yaml_test.go | 254 +++++++++++++++++++++- 1 file changed, 251 insertions(+), 3 deletions(-) diff --git a/internal/inspectimage/writer/yaml_test.go b/internal/inspectimage/writer/yaml_test.go index 3a422eb52..13d676c96 100644 --- a/internal/inspectimage/writer/yaml_test.go +++ b/internal/inspectimage/writer/yaml_test.go @@ -30,12 +30,56 @@ func testYAML(t *testing.T, when spec.G, it spec.S) { assert = h.NewAssertionManager(t) outBuf bytes.Buffer - remoteInfo *client.ImageInfo - localInfo *client.ImageInfo + remoteInfo *client.ImageInfo + remoteInfoWithRebasable *client.ImageInfo + localInfo *client.ImageInfo + localInfoWithRebasable *client.ImageInfo expectedLocalOutput = `--- local_info: stack: test.stack.id.local + rebasable: false + base_image: + top_layer: some-local-top-layer + reference: some-local-run-image-reference + run_images: + - name: user-configured-mirror-for-local + user_configured: true + - name: some-local-run-image + - name: some-local-mirror + - name: other-local-mirror + buildpacks: + - homepage: https://some-homepage-one + id: test.bp.one.local + version: 1.0.0 + - homepage: https://some-homepage-two + id: test.bp.two.local + version: 2.0.0 + extensions: [] + processes: + - type: some-local-type + shell: bash + command: "/some/local command" + default: true + args: + - some + - local + - args + working-dir: /some-test-work-dir + - type: other-local-type + shell: '' + command: "/other/local/command" + default: false + args: + - other + - local + - args + working-dir: /other-test-work-dir +` + expectedLocalOutputWithRebasable = `--- +local_info: + stack: test.stack.id.local + rebasable: true base_image: top_layer: some-local-top-layer reference: some-local-run-image-reference @@ -76,6 +120,48 @@ local_info: expectedRemoteOutput = `--- remote_info: stack: test.stack.id.remote + rebasable: false + base_image: + top_layer: some-remote-top-layer + reference: some-remote-run-image-reference + run_images: + - name: user-configured-mirror-for-remote + user_configured: true + - name: some-remote-run-image + - name: some-remote-mirror + - name: other-remote-mirror + buildpacks: + - homepage: https://some-homepage-one + id: test.bp.one.remote + version: 1.0.0 + - homepage: https://some-homepage-two + id: test.bp.two.remote + version: 2.0.0 + extensions: [] + processes: + - type: some-remote-type + shell: bash + command: "/some/remote command" + default: true + args: + - some + - remote + - args + working-dir: /some-test-work-dir + - type: other-remote-type + shell: '' + command: "/other/remote/command" + default: false + args: + - other + - remote + - args + working-dir: /other-test-work-dir +` + expectedRemoteOutputWithRebasable = `--- +remote_info: + stack: test.stack.id.remote + rebasable: true base_image: top_layer: some-remote-top-layer reference: some-remote-run-image-reference @@ -181,6 +267,62 @@ remote_info: }, } + remoteInfoWithRebasable = &client.ImageInfo{ + StackID: "test.stack.id.remote", + Buildpacks: []buildpack.GroupElement{ + {ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, + {ID: "test.bp.two.remote", Version: "2.0.0", Homepage: "https://some-homepage-two"}, + }, + Base: platform.RunImageForRebase{ + TopLayer: "some-remote-top-layer", + Reference: "some-remote-run-image-reference", + }, + Stack: platform.StackMetadata{ + RunImage: platform.RunImageForExport{ + Image: "some-remote-run-image", + Mirrors: []string{"some-remote-mirror", "other-remote-mirror"}, + }, + }, + BOM: []buildpack.BOMEntry{{ + Require: buildpack.Require{ + Name: "name-1", + Version: "version-1", + Metadata: map[string]interface{}{ + "RemoteData": someData{ + String: "aString", + Bool: true, + Int: 123, + Nested: struct { + String string + }{ + String: "anotherString", + }, + }, + }, + }, + Buildpack: buildpack.GroupElement{ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, + }}, + Processes: client.ProcessDetails{ + DefaultProcess: &launch.Process{ + Type: "some-remote-type", + Command: launch.RawCommand{Entries: []string{"/some/remote command"}}, + Args: []string{"some", "remote", "args"}, + Direct: false, + WorkingDirectory: "/some-test-work-dir", + }, + OtherProcesses: []launch.Process{ + { + Type: "other-remote-type", + Command: launch.RawCommand{Entries: []string{"/other/remote/command"}}, + Args: []string{"other", "remote", "args"}, + Direct: true, + WorkingDirectory: "/other-test-work-dir", + }, + }, + }, + Rebasable: true, + } + localInfo = &client.ImageInfo{ StackID: "test.stack.id.local", Buildpacks: []buildpack.GroupElement{ @@ -230,6 +372,56 @@ remote_info: }, } + localInfoWithRebasable = &client.ImageInfo{ + StackID: "test.stack.id.local", + Buildpacks: []buildpack.GroupElement{ + {ID: "test.bp.one.local", Version: "1.0.0", Homepage: "https://some-homepage-one"}, + {ID: "test.bp.two.local", Version: "2.0.0", Homepage: "https://some-homepage-two"}, + }, + Base: platform.RunImageForRebase{ + TopLayer: "some-local-top-layer", + Reference: "some-local-run-image-reference", + }, + Stack: platform.StackMetadata{ + RunImage: platform.RunImageForExport{ + Image: "some-local-run-image", + Mirrors: []string{"some-local-mirror", "other-local-mirror"}, + }, + }, + BOM: []buildpack.BOMEntry{{ + Require: buildpack.Require{ + Name: "name-1", + Version: "version-1", + Metadata: map[string]interface{}{ + "LocalData": someData{ + Bool: false, + Int: 456, + }, + }, + }, + Buildpack: buildpack.GroupElement{ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, + }}, + Processes: client.ProcessDetails{ + DefaultProcess: &launch.Process{ + Type: "some-local-type", + Command: launch.RawCommand{Entries: []string{"/some/local command"}}, + Args: []string{"some", "local", "args"}, + Direct: false, + WorkingDirectory: "/some-test-work-dir", + }, + OtherProcesses: []launch.Process{ + { + Type: "other-local-type", + Command: launch.RawCommand{Entries: []string{"/other/local/command"}}, + Args: []string{"other", "local", "args"}, + Direct: true, + WorkingDirectory: "/other-test-work-dir", + }, + }, + }, + Rebasable: true, + } + outBuf = bytes.Buffer{} }) @@ -293,9 +485,36 @@ remote_info: assert.ContainsYAML(outBuf.String(), `"image_name": "test-image"`) assert.ContainsYAML(outBuf.String(), expectedLocalOutput) + assert.NotContains(outBuf.String(), "test.stack.id.remote") + }) + it("prints local rebasable image info in YAML format", func() { + runImageMirrors := []config.RunImage{ + { + Image: "un-used-run-image", + Mirrors: []string{"un-used"}, + }, + { + Image: "some-local-run-image", + Mirrors: []string{"user-configured-mirror-for-local"}, + }, + { + Image: "some-remote-run-image", + Mirrors: []string{"user-configured-mirror-for-remote"}, + }, + } + sharedImageInfo := inspectimage.GeneralInfo{ + Name: "test-image", + RunImageMirrors: runImageMirrors, + } + yamlWriter := writer.NewYAML() + + logger := logging.NewLogWithWriters(&outBuf, &outBuf) + err := yamlWriter.Print(logger, sharedImageInfo, localInfoWithRebasable, nil, nil, nil) + assert.Nil(err) + assert.ContainsYAML(outBuf.String(), `"image_name": "test-image"`) + assert.ContainsYAML(outBuf.String(), expectedLocalOutputWithRebasable) assert.NotContains(outBuf.String(), "test.stack.id.remote") - assert.ContainsYAML(outBuf.String(), expectedLocalOutput) }) }) @@ -329,6 +548,35 @@ remote_info: assert.NotContains(outBuf.String(), "test.stack.id.local") assert.ContainsYAML(outBuf.String(), expectedRemoteOutput) }) + it("prints remote rebasable image info in YAML format", func() { + runImageMirrors := []config.RunImage{ + { + Image: "un-used-run-image", + Mirrors: []string{"un-used"}, + }, + { + Image: "some-local-run-image", + Mirrors: []string{"user-configured-mirror-for-local"}, + }, + { + Image: "some-remote-run-image", + Mirrors: []string{"user-configured-mirror-for-remote"}, + }, + } + sharedImageInfo := inspectimage.GeneralInfo{ + Name: "test-image", + RunImageMirrors: runImageMirrors, + } + yamlWriter := writer.NewYAML() + + logger := logging.NewLogWithWriters(&outBuf, &outBuf) + err := yamlWriter.Print(logger, sharedImageInfo, nil, remoteInfoWithRebasable, nil, nil) + assert.Nil(err) + + assert.ContainsYAML(outBuf.String(), `"image_name": "test-image"`) + assert.ContainsYAML(outBuf.String(), expectedRemoteOutputWithRebasable) + assert.NotContains(outBuf.String(), "test.stack.id.local") + }) }) }) } From 88272d813f796ca2031832a6fd57fedcfed8a697 Mon Sep 17 00:00:00 2001 From: Domenico Luciani Date: Fri, 16 Jun 2023 11:58:33 +0200 Subject: [PATCH 05/11] Fixs json tests and adds tests for local and remote the rebasable images Signed-off-by: Domenico Luciani --- internal/inspectimage/writer/json_test.go | 300 +++++++++++++++++++++- 1 file changed, 298 insertions(+), 2 deletions(-) diff --git a/internal/inspectimage/writer/json_test.go b/internal/inspectimage/writer/json_test.go index b08e1a108..519a8609c 100644 --- a/internal/inspectimage/writer/json_test.go +++ b/internal/inspectimage/writer/json_test.go @@ -30,12 +30,79 @@ func testJSON(t *testing.T, when spec.G, it spec.S) { assert = h.NewAssertionManager(t) outBuf bytes.Buffer - remoteInfo *client.ImageInfo - localInfo *client.ImageInfo + remoteInfo *client.ImageInfo + remoteInfoWithRebasable *client.ImageInfo + localInfo *client.ImageInfo + localInfoWithRebasable *client.ImageInfo expectedLocalOutput = `{ "local_info": { "stack": "test.stack.id.local", + "rebasable": false, + "base_image": { + "top_layer": "some-local-top-layer", + "reference": "some-local-run-image-reference" + }, + "run_images": [ + { + "name": "user-configured-mirror-for-local", + "user_configured": true + }, + { + "name": "some-local-run-image" + }, + { + "name": "some-local-mirror" + }, + { + "name": "other-local-mirror" + } + ], + "buildpacks": [ + { + "homepage": "https://some-homepage-one", + "id": "test.bp.one.local", + "version": "1.0.0" + }, + { + "homepage": "https://some-homepage-two", + "id": "test.bp.two.local", + "version": "2.0.0" + } + ], + "extensions": null, + "processes": [ + { + "type": "some-local-type", + "shell": "bash", + "command": "/some/local command", + "default": true, + "args": [ + "some", + "local", + "args" + ], + "working-dir": "/some-test-work-dir" + }, + { + "type": "other-local-type", + "shell": "", + "command": "/other/local/command", + "default": false, + "args": [ + "other", + "local", + "args" + ], + "working-dir": "/other-test-work-dir" + } + ] + } +}` + expectedLocalOutputWithRebasable = `{ + "local_info": { + "stack": "test.stack.id.local", + "rebasable": true, "base_image": { "top_layer": "some-local-top-layer", "reference": "some-local-run-image-reference" @@ -99,6 +166,71 @@ func testJSON(t *testing.T, when spec.G, it spec.S) { expectedRemoteOutput = `{ "remote_info": { "stack": "test.stack.id.remote", + "rebasable": false, + "base_image": { + "top_layer": "some-remote-top-layer", + "reference": "some-remote-run-image-reference" + }, + "run_images": [ + { + "name": "user-configured-mirror-for-remote", + "user_configured": true + }, + { + "name": "some-remote-run-image" + }, + { + "name": "some-remote-mirror" + }, + { + "name": "other-remote-mirror" + } + ], + "buildpacks": [ + { + "id": "test.bp.one.remote", + "version": "1.0.0", + "homepage": "https://some-homepage-one" + }, + { + "id": "test.bp.two.remote", + "version": "2.0.0", + "homepage": "https://some-homepage-two" + } + ], + "extensions": null, + "processes": [ + { + "type": "some-remote-type", + "shell": "bash", + "command": "/some/remote command", + "default": true, + "args": [ + "some", + "remote", + "args" + ], + "working-dir": "/some-test-work-dir" + }, + { + "type": "other-remote-type", + "shell": "", + "command": "/other/remote/command", + "default": false, + "args": [ + "other", + "remote", + "args" + ], + "working-dir": "/other-test-work-dir" + } + ] + } +}` + expectedRemoteOutputWithRebasable = `{ + "remote_info": { + "stack": "test.stack.id.remote", + "rebasable": true, "base_image": { "top_layer": "some-remote-top-layer", "reference": "some-remote-run-image-reference" @@ -227,6 +359,62 @@ func testJSON(t *testing.T, when spec.G, it spec.S) { }, } + remoteInfoWithRebasable = &client.ImageInfo{ + StackID: "test.stack.id.remote", + Buildpacks: []buildpack.GroupElement{ + {ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, + {ID: "test.bp.two.remote", Version: "2.0.0", Homepage: "https://some-homepage-two"}, + }, + Base: platform.RunImageForRebase{ + TopLayer: "some-remote-top-layer", + Reference: "some-remote-run-image-reference", + }, + Stack: platform.StackMetadata{ + RunImage: platform.RunImageForExport{ + Image: "some-remote-run-image", + Mirrors: []string{"some-remote-mirror", "other-remote-mirror"}, + }, + }, + BOM: []buildpack.BOMEntry{{ + Require: buildpack.Require{ + Name: "name-1", + Version: "version-1", + Metadata: map[string]interface{}{ + "RemoteData": someData{ + String: "aString", + Bool: true, + Int: 123, + Nested: struct { + String string + }{ + String: "anotherString", + }, + }, + }, + }, + Buildpack: buildpack.GroupElement{ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, + }}, + Processes: client.ProcessDetails{ + DefaultProcess: &launch.Process{ + Type: "some-remote-type", + Command: launch.RawCommand{Entries: []string{"/some/remote command"}}, + Args: []string{"some", "remote", "args"}, + Direct: false, + WorkingDirectory: "/some-test-work-dir", + }, + OtherProcesses: []launch.Process{ + { + Type: "other-remote-type", + Command: launch.RawCommand{Entries: []string{"/other/remote/command"}}, + Args: []string{"other", "remote", "args"}, + Direct: true, + WorkingDirectory: "/other-test-work-dir", + }, + }, + }, + Rebasable: true, + } + localInfo = &client.ImageInfo{ StackID: "test.stack.id.local", Buildpacks: []buildpack.GroupElement{ @@ -276,6 +464,56 @@ func testJSON(t *testing.T, when spec.G, it spec.S) { }, } + localInfoWithRebasable = &client.ImageInfo{ + StackID: "test.stack.id.local", + Buildpacks: []buildpack.GroupElement{ + {ID: "test.bp.one.local", Version: "1.0.0", Homepage: "https://some-homepage-one"}, + {ID: "test.bp.two.local", Version: "2.0.0", Homepage: "https://some-homepage-two"}, + }, + Base: platform.RunImageForRebase{ + TopLayer: "some-local-top-layer", + Reference: "some-local-run-image-reference", + }, + Stack: platform.StackMetadata{ + RunImage: platform.RunImageForExport{ + Image: "some-local-run-image", + Mirrors: []string{"some-local-mirror", "other-local-mirror"}, + }, + }, + BOM: []buildpack.BOMEntry{{ + Require: buildpack.Require{ + Name: "name-1", + Version: "version-1", + Metadata: map[string]interface{}{ + "LocalData": someData{ + Bool: false, + Int: 456, + }, + }, + }, + Buildpack: buildpack.GroupElement{ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, + }}, + Processes: client.ProcessDetails{ + DefaultProcess: &launch.Process{ + Type: "some-local-type", + Command: launch.RawCommand{Entries: []string{"/some/local command"}}, + Args: []string{"some", "local", "args"}, + Direct: false, + WorkingDirectory: "/some-test-work-dir", + }, + OtherProcesses: []launch.Process{ + { + Type: "other-local-type", + Command: launch.RawCommand{Entries: []string{"/other/local/command"}}, + Args: []string{"other", "local", "args"}, + Direct: true, + WorkingDirectory: "/other-test-work-dir", + }, + }, + }, + Rebasable: true, + } + outBuf = bytes.Buffer{} }) @@ -343,6 +581,35 @@ func testJSON(t *testing.T, when spec.G, it spec.S) { assert.NotContains(outBuf.String(), "test.stack.id.remote") assert.ContainsJSON(outBuf.String(), expectedLocalOutput) }) + it("prints local rebasable image info in JSON format", func() { + runImageMirrors := []config.RunImage{ + { + Image: "un-used-run-image", + Mirrors: []string{"un-used"}, + }, + { + Image: "some-local-run-image", + Mirrors: []string{"user-configured-mirror-for-local"}, + }, + { + Image: "some-remote-run-image", + Mirrors: []string{"user-configured-mirror-for-remote"}, + }, + } + sharedImageInfo := inspectimage.GeneralInfo{ + Name: "test-image", + RunImageMirrors: runImageMirrors, + } + jsonWriter := writer.NewJSON() + + logger := logging.NewLogWithWriters(&outBuf, &outBuf) + err := jsonWriter.Print(logger, sharedImageInfo, localInfoWithRebasable, nil, nil, nil) + assert.Nil(err) + + assert.ContainsJSON(outBuf.String(), `{ "image_name": "test-image" }`) + assert.ContainsJSON(outBuf.String(), expectedLocalOutputWithRebasable) + assert.NotContains(outBuf.String(), "test.stack.id.remote") + }) }) when("only remote image exists", func() { @@ -375,6 +642,35 @@ func testJSON(t *testing.T, when spec.G, it spec.S) { assert.NotContains(outBuf.String(), "test.stack.id.local") assert.ContainsJSON(outBuf.String(), expectedRemoteOutput) }) + it("prints remote rebasable image info in JSON format", func() { + runImageMirrors := []config.RunImage{ + { + Image: "un-used-run-image", + Mirrors: []string{"un-used"}, + }, + { + Image: "some-local-run-image", + Mirrors: []string{"user-configured-mirror-for-local"}, + }, + { + Image: "some-remote-run-image", + Mirrors: []string{"user-configured-mirror-for-remote"}, + }, + } + sharedImageInfo := inspectimage.GeneralInfo{ + Name: "test-image", + RunImageMirrors: runImageMirrors, + } + jsonWriter := writer.NewJSON() + + logger := logging.NewLogWithWriters(&outBuf, &outBuf) + err := jsonWriter.Print(logger, sharedImageInfo, nil, remoteInfoWithRebasable, nil, nil) + assert.Nil(err) + + assert.ContainsJSON(outBuf.String(), `{ "image_name": "test-image" }`) + assert.NotContains(outBuf.String(), "test.stack.id.local") + assert.ContainsJSON(outBuf.String(), expectedRemoteOutputWithRebasable) + }) }) }) } From 22de7ccae1bf1343bf232f4862b84a81368c1d8b Mon Sep 17 00:00:00 2001 From: Domenico Luciani Date: Fri, 16 Jun 2023 18:06:25 +0200 Subject: [PATCH 06/11] Fixs acceptance tests and implements rebasable on the inspect command Signed-off-by: Domenico Luciani --- acceptance/acceptance_test.go | 2 + .../inspect_image_local_output.json | 1 + .../inspect_image_local_output.toml | 1 + .../inspect_image_local_output.yaml | 1 + .../inspect_image_published_output.json | 1 + .../inspect_image_published_output.toml | 1 + .../inspect_image_published_output.yaml | 1 + pkg/client/inspect_image.go | 7 + pkg/client/inspect_image_test.go | 170 ++++++++++++++++-- 9 files changed, 174 insertions(+), 11 deletions(-) diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go index 837b95036..8bcb686df 100644 --- a/acceptance/acceptance_test.go +++ b/acceptance/acceptance_test.go @@ -1153,6 +1153,7 @@ func testAcceptance( "hello_args": helloArgs, "hello_args_prefix": helloArgsPrefix, "image_workdir": imageWorkdir, + "rebasable": false, }, ) @@ -1826,6 +1827,7 @@ func testAcceptance( "hello_args": helloArgs, "hello_args_prefix": helloArgsPrefix, "image_workdir": imageWorkdir, + "rebasable": false, }, ) diff --git a/acceptance/testdata/pack_fixtures/inspect_image_local_output.json b/acceptance/testdata/pack_fixtures/inspect_image_local_output.json index 94fb3afc8..08bee028c 100644 --- a/acceptance/testdata/pack_fixtures/inspect_image_local_output.json +++ b/acceptance/testdata/pack_fixtures/inspect_image_local_output.json @@ -3,6 +3,7 @@ "remote_info": null, "local_info": { "stack": "pack.test.stack", + "rebasable": false, "base_image": { "top_layer": "{{.base_image_top_layer}}", "reference": "{{.base_image_id}}" diff --git a/acceptance/testdata/pack_fixtures/inspect_image_local_output.toml b/acceptance/testdata/pack_fixtures/inspect_image_local_output.toml index 97be50630..4a2f816db 100644 --- a/acceptance/testdata/pack_fixtures/inspect_image_local_output.toml +++ b/acceptance/testdata/pack_fixtures/inspect_image_local_output.toml @@ -2,6 +2,7 @@ image_name = "{{.image_name}}" [local_info] stack = "pack.test.stack" +rebasable = false [local_info.base_image] top_layer = "{{.base_image_top_layer}}" diff --git a/acceptance/testdata/pack_fixtures/inspect_image_local_output.yaml b/acceptance/testdata/pack_fixtures/inspect_image_local_output.yaml index 05e8135e5..b3d8b757f 100644 --- a/acceptance/testdata/pack_fixtures/inspect_image_local_output.yaml +++ b/acceptance/testdata/pack_fixtures/inspect_image_local_output.yaml @@ -3,6 +3,7 @@ image_name: "{{.image_name}}" remote_info: local_info: stack: pack.test.stack + rebasable: false base_image: top_layer: "{{.base_image_top_layer}}" reference: "{{.base_image_id}}" diff --git a/acceptance/testdata/pack_fixtures/inspect_image_published_output.json b/acceptance/testdata/pack_fixtures/inspect_image_published_output.json index 38d2cc07a..4945e2f81 100644 --- a/acceptance/testdata/pack_fixtures/inspect_image_published_output.json +++ b/acceptance/testdata/pack_fixtures/inspect_image_published_output.json @@ -3,6 +3,7 @@ "local_info": null, "remote_info": { "stack": "pack.test.stack", + "rebasable": false, "base_image": { "top_layer": "{{.base_image_top_layer}}", "reference": "{{.base_image_ref}}" diff --git a/acceptance/testdata/pack_fixtures/inspect_image_published_output.toml b/acceptance/testdata/pack_fixtures/inspect_image_published_output.toml index 734eaad21..4d86d0d8f 100644 --- a/acceptance/testdata/pack_fixtures/inspect_image_published_output.toml +++ b/acceptance/testdata/pack_fixtures/inspect_image_published_output.toml @@ -2,6 +2,7 @@ image_name = "{{.image_name}}" [remote_info] stack = "pack.test.stack" +rebasable = false [remote_info.base_image] top_layer = "{{.base_image_top_layer}}" diff --git a/acceptance/testdata/pack_fixtures/inspect_image_published_output.yaml b/acceptance/testdata/pack_fixtures/inspect_image_published_output.yaml index 290f7a6bb..cbcdb3e6e 100644 --- a/acceptance/testdata/pack_fixtures/inspect_image_published_output.yaml +++ b/acceptance/testdata/pack_fixtures/inspect_image_published_output.yaml @@ -3,6 +3,7 @@ image_name: "{{.image_name}}" local_info: null remote_info: stack: pack.test.stack + rebasable: false base_image: top_layer: "{{.base_image_top_layer}}" reference: "{{.base_image_ref}}" diff --git a/pkg/client/inspect_image.go b/pkg/client/inspect_image.go index abd3df128..dbb227f34 100644 --- a/pkg/client/inspect_image.go +++ b/pkg/client/inspect_image.go @@ -123,6 +123,11 @@ func (c *Client) InspectImage(name string, daemon bool) (*ImageInfo, error) { return nil, err } + var rebasable bool + if _, err := dist.GetLabel(img, platform.RebaseableLabel, &rebasable); err != nil { + return nil, err + } + platformAPI, err := img.Env(platformAPIEnv) if err != nil { return nil, errors.Wrap(err, "reading platform api") @@ -196,6 +201,7 @@ func (c *Client) InspectImage(name string, daemon bool) (*ImageInfo, error) { Buildpacks: buildMD.Buildpacks, Extensions: buildMD.Extensions, Processes: processDetails, + Rebasable: rebasable, }, nil } @@ -206,5 +212,6 @@ func (c *Client) InspectImage(name string, daemon bool) (*ImageInfo, error) { BOM: buildMD.BOM, Buildpacks: buildMD.Buildpacks, Processes: processDetails, + Rebasable: rebasable, }, nil } diff --git a/pkg/client/inspect_image_test.go b/pkg/client/inspect_image_test.go index fe71947aa..ee786043a 100644 --- a/pkg/client/inspect_image_test.go +++ b/pkg/client/inspect_image_test.go @@ -37,13 +37,15 @@ var ignorePlatformAPI = []cmp.Option{ func testInspectImage(t *testing.T, when spec.G, it spec.S) { var ( - subject *Client - mockImageFetcher *testmocks.MockImageFetcher - mockDockerClient *testmocks.MockCommonAPIClient - mockController *gomock.Controller - mockImage *testmocks.MockImage - mockImageWithExtension *testmocks.MockImage - out bytes.Buffer + subject *Client + mockImageFetcher *testmocks.MockImageFetcher + mockDockerClient *testmocks.MockCommonAPIClient + mockController *gomock.Controller + mockImage *testmocks.MockImage + mockRebasableImage *testmocks.MockImage + mockImageWithExtension *testmocks.MockImage + mockRebasableImageWithExtension *testmocks.MockImage + out bytes.Buffer ) it.Before(func() { @@ -114,6 +116,66 @@ func testInspectImage(t *testing.T, when spec.G, it spec.S) { }`, )) + mockRebasableImage = testmocks.NewImage("some/rebasableImage", "", nil) + h.AssertNil(t, mockRebasableImage.SetWorkingDir("/test-workdir")) + h.AssertNil(t, mockRebasableImage.SetLabel("io.buildpacks.stack.id", "test.stack.id")) + h.AssertNil(t, mockRebasableImage.SetLabel( + "io.buildpacks.lifecycle.metadata", + `{ + "stack": { + "runImage": { + "image": "some-run-image", + "mirrors": [ + "some-mirror", + "other-mirror" + ] + } + }, + "runImage": { + "topLayer": "some-top-layer", + "reference": "some-run-image-reference" + } +}`, + )) + h.AssertNil(t, mockRebasableImage.SetLabel( + "io.buildpacks.build.metadata", + `{ + "bom": [ + { + "name": "some-bom-element" + } + ], + "buildpacks": [ + { + "id": "some-buildpack", + "version": "some-version" + }, + { + "id": "other-buildpack", + "version": "other-version" + } + ], + "processes": [ + { + "type": "other-process", + "command": "/other/process", + "args": ["opt", "1"], + "direct": true + }, + { + "type": "web", + "command": "/start/web-process", + "args": ["-p", "1234"], + "direct": false + } + ], + "launcher": { + "version": "0.5.0" + } +}`, + )) + h.AssertNil(t, mockRebasableImage.SetLabel("io.buildpacks.rebasable", "true")) + mockImageWithExtension = testmocks.NewImage("some/imageWithExtension", "", nil) h.AssertNil(t, mockImageWithExtension.SetWorkingDir("/test-workdir")) h.AssertNil(t, mockImageWithExtension.SetLabel("io.buildpacks.stack.id", "test.stack.id")) @@ -182,6 +244,76 @@ func testInspectImage(t *testing.T, when spec.G, it spec.S) { } }`, )) + + mockRebasableImageWithExtension = testmocks.NewImage("some/rebasableImageWithExtension", "", nil) + h.AssertNil(t, mockRebasableImageWithExtension.SetWorkingDir("/test-workdir")) + h.AssertNil(t, mockRebasableImageWithExtension.SetLabel("io.buildpacks.stack.id", "test.stack.id")) + h.AssertNil(t, mockRebasableImageWithExtension.SetLabel( + "io.buildpacks.lifecycle.metadata", + `{ + "stack": { + "runImage": { + "image": "some-run-image", + "mirrors": [ + "some-mirror", + "other-mirror" + ] + } + }, + "runImage": { + "topLayer": "some-top-layer", + "reference": "some-run-image-reference" + } +}`, + )) + h.AssertNil(t, mockRebasableImageWithExtension.SetLabel( + "io.buildpacks.build.metadata", + `{ + "bom": [ + { + "name": "some-bom-element" + } + ], + "buildpacks": [ + { + "id": "some-buildpack", + "version": "some-version" + }, + { + "id": "other-buildpack", + "version": "other-version" + } + ], + "extensions": [ + { + "id": "some-extension", + "version": "some-version" + }, + { + "id": "other-extension", + "version": "other-version" + } + ], + "processes": [ + { + "type": "other-process", + "command": "/other/process", + "args": ["opt", "1"], + "direct": true + }, + { + "type": "web", + "command": "/start/web-process", + "args": ["-p", "1234"], + "direct": false + } + ], + "launcher": { + "version": "0.5.0" + } +}`, + )) + h.AssertNil(t, mockRebasableImageWithExtension.SetLabel("io.buildpacks.rebasable", "true")) }) it.After(func() { @@ -195,10 +327,14 @@ func testInspectImage(t *testing.T, when spec.G, it spec.S) { it.Before(func() { if useDaemon { mockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/image", image.FetchOptions{Daemon: true, PullPolicy: image.PullNever}).Return(mockImage, nil).AnyTimes() + mockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/rebasableImage", image.FetchOptions{Daemon: true, PullPolicy: image.PullNever}).Return(mockRebasableImage, nil).AnyTimes() mockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/imageWithExtension", image.FetchOptions{Daemon: true, PullPolicy: image.PullNever}).Return(mockImageWithExtension, nil).AnyTimes() + mockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/rebasableImageWithExtension", image.FetchOptions{Daemon: true, PullPolicy: image.PullNever}).Return(mockRebasableImageWithExtension, nil).AnyTimes() } else { mockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/image", image.FetchOptions{Daemon: false, PullPolicy: image.PullNever}).Return(mockImage, nil).AnyTimes() + mockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/rebasableImage", image.FetchOptions{Daemon: false, PullPolicy: image.PullNever}).Return(mockRebasableImage, nil).AnyTimes() mockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/imageWithExtension", image.FetchOptions{Daemon: false, PullPolicy: image.PullNever}).Return(mockImageWithExtension, nil).AnyTimes() + mockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/rebasableImageWithExtension", image.FetchOptions{Daemon: false, PullPolicy: image.PullNever}).Return(mockRebasableImageWithExtension, nil).AnyTimes() } }) @@ -208,7 +344,7 @@ func testInspectImage(t *testing.T, when spec.G, it spec.S) { h.AssertEq(t, info.StackID, "test.stack.id") }) - it("returns the stack ID", func() { + it("returns the stack ID with extension", func() { infoWithExtension, err := subject.InspectImage("some/imageWithExtension", useDaemon) h.AssertNil(t, err) h.AssertEq(t, infoWithExtension.StackID, "test.stack.id") @@ -247,7 +383,7 @@ func testInspectImage(t *testing.T, when spec.G, it spec.S) { ) }) - it("returns the stack", func() { + it("returns the stack with extension", func() { infoWithExtension, err := subject.InspectImage("some/imageWithExtension", useDaemon) h.AssertNil(t, err) h.AssertEq(t, infoWithExtension.Stack, @@ -274,7 +410,7 @@ func testInspectImage(t *testing.T, when spec.G, it spec.S) { ) }) - it("returns the base image", func() { + it("returns the base image with extension", func() { infoWithExtension, err := subject.InspectImage("some/imageWithExtension", useDaemon) h.AssertNil(t, err) h.AssertEq(t, infoWithExtension.Base, @@ -285,6 +421,18 @@ func testInspectImage(t *testing.T, when spec.G, it spec.S) { ) }) + it("returns the rebasable image", func() { + info, err := subject.InspectImage("some/rebasableImage", useDaemon) + h.AssertNil(t, err) + h.AssertEq(t, info.Rebasable, true) + }) + + it("returns the rebasable image with Extension", func() { + infoRebasableWithExtension, err := subject.InspectImage("some/rebasableImageWithExtension", useDaemon) + h.AssertNil(t, err) + h.AssertEq(t, infoRebasableWithExtension.Rebasable, true) + }) + it("returns the BOM", func() { info, err := subject.InspectImage("some/image", useDaemon) h.AssertNil(t, err) @@ -314,7 +462,7 @@ func testInspectImage(t *testing.T, when spec.G, it spec.S) { h.AssertEq(t, info.Buildpacks[1].Version, "other-version") }) - it("returns the buildpacks", func() { + it("returns the buildpacks with extension", func() { infoWithExtension, err := subject.InspectImage("some/imageWithExtension", useDaemon) h.AssertNil(t, err) From fe6051a50de540e2a873da2240acc3f609020016 Mon Sep 17 00:00:00 2001 From: Domenico Luciani Date: Mon, 19 Jun 2023 11:24:22 +0200 Subject: [PATCH 07/11] Refactors the Print method improving the readibility and separation of concerns Signed-off-by: Domenico Luciani --- .../inspectimage/writer/human_readable.go | 110 ++++++++++++------ 1 file changed, 75 insertions(+), 35 deletions(-) diff --git a/internal/inspectimage/writer/human_readable.go b/internal/inspectimage/writer/human_readable.go index 4215a06d3..1f41e64fd 100644 --- a/internal/inspectimage/writer/human_readable.go +++ b/internal/inspectimage/writer/human_readable.go @@ -30,18 +30,39 @@ func (h *HumanReadable) Print( if local == nil && remote == nil { return fmt.Errorf("unable to find image '%s' locally or remotely", generalInfo.Name) } - localDisplay := inspectimage.NewInfoDisplay(local, generalInfo) - remoteDisplay := inspectimage.NewInfoDisplay(remote, generalInfo) logger.Infof("Inspecting image: %s\n", style.Symbol(generalInfo.Name)) - logger.Info("\nREMOTE:\n") - err := writeImageInfo(logger, remoteDisplay, remoteErr) - if err != nil { - return fmt.Errorf("writing remote builder info: %w", err) + if err := writeRemoteImageInfo(logger, generalInfo, remote, remoteErr); err != nil { + return err } + + if err := writeLocalImageInfo(logger, generalInfo, local, localErr); err != nil { + return err + } + + return nil +} + +func writeLocalImageInfo( + logger logging.Logger, + generalInfo inspectimage.GeneralInfo, + local *client.ImageInfo, + localErr error) error { logger.Info("\nLOCAL:\n") - err = writeImageInfo(logger, localDisplay, localErr) + + if localErr != nil { + logger.Errorf("%s\n", localErr) + return nil + } + + localDisplay := inspectimage.NewInfoDisplay(local, generalInfo) + if localDisplay == nil { + logger.Info("(not present)\n") + return nil + } + + err := writeImageInfo(logger, localDisplay) if err != nil { return fmt.Errorf("writing local builder info: %w", err) } @@ -49,51 +70,70 @@ func (h *HumanReadable) Print( return nil } +func writeRemoteImageInfo( + logger logging.Logger, + generalInfo inspectimage.GeneralInfo, + remote *client.ImageInfo, + remoteErr error) error { + logger.Info("\nREMOTE:\n") + + if remoteErr != nil { + logger.Errorf("%s\n", remoteErr) + return nil + } + + remoteDisplay := inspectimage.NewInfoDisplay(remote, generalInfo) + if remoteDisplay == nil { + logger.Info("(not present)\n") + return nil + } + + err := writeImageInfo(logger, remoteDisplay) + if err != nil { + return fmt.Errorf("writing remote builder info: %w", err) + } + + return nil +} + func writeImageInfo( logger logging.Logger, info *inspectimage.InfoDisplay, - err error, ) error { + imgTpl := getImageTemplate(info) + remoteOutput, err := getInspectImageOutput(imgTpl, info) + if err != nil { + logger.Error(err.Error()) + return err + } else { + logger.Info(remoteOutput.String()) + return nil + } +} + +func getImageTemplate(info *inspectimage.InfoDisplay) *template.Template { imgTpl := template.Must(template.New("runImages"). Funcs(template.FuncMap{"StringsJoin": strings.Join}). Funcs(template.FuncMap{"StringsValueOrDefault": strs.ValueOrDefault}). Parse(runImagesTemplate)) imgTpl = template.Must(imgTpl.New("buildpacks").Parse(buildpacksTemplate)) - if info != nil && info.Extensions != nil { - imgTpl = template.Must(imgTpl.New("extensions").Parse(extensionsTemplate)) - } - imgTpl = template.Must(imgTpl.New("processes"). - Parse(processesTemplate)) + + imgTpl = template.Must(imgTpl.New("processes").Parse(processesTemplate)) imgTpl = template.Must(imgTpl.New("rebasable").Parse(rebasableTemplate)) if info != nil && info.Extensions != nil { - imgTpl = template.Must(imgTpl.New("image"). - Parse(imageWithExtensionTemplate)) - } else { - imgTpl = template.Must(imgTpl.New("image"). - Parse(imageTemplate)) - } - - if err != nil { - logger.Errorf("%s\n", err) - return nil - } - - if info == nil { - logger.Info("(not present)\n") - return nil - } - remoteOutput, err := inspectImageOutput(info, imgTpl) - if err != nil { - logger.Error(err.Error()) + imgTpl = template.Must(imgTpl.New("extensions").Parse(extensionsTemplate)) + imgTpl = template.Must(imgTpl.New("image").Parse(imageWithExtensionTemplate)) } else { - logger.Info(remoteOutput.String()) + imgTpl = template.Must(imgTpl.New("image").Parse(imageTemplate)) } - return nil + return imgTpl } -func inspectImageOutput(info *inspectimage.InfoDisplay, tpl *template.Template) (*bytes.Buffer, error) { +func getInspectImageOutput( + tpl *template.Template, + info *inspectimage.InfoDisplay) (*bytes.Buffer, error) { if info == nil { return bytes.NewBuffer([]byte("(not present)")), nil } From ded989475b28d4b7aa68b8b4946d68b4ca418479 Mon Sep 17 00:00:00 2001 From: Domenico Luciani Date: Mon, 19 Jun 2023 17:01:55 +0200 Subject: [PATCH 08/11] Extracts mocked image generators into helper functions Signed-off-by: Domenico Luciani --- .../writer/human_readable_test.go | 578 ++++++++---------- 1 file changed, 240 insertions(+), 338 deletions(-) diff --git a/internal/inspectimage/writer/human_readable_test.go b/internal/inspectimage/writer/human_readable_test.go index 4ffd0b259..16a3b0172 100644 --- a/internal/inspectimage/writer/human_readable_test.go +++ b/internal/inspectimage/writer/human_readable_test.go @@ -211,344 +211,14 @@ Processes: when("Print", func() { it.Before(func() { - type someData struct { - String string - Bool bool - Int int - Nested struct { - String string - } - } - - remoteInfo = &client.ImageInfo{ - StackID: "test.stack.id.remote", - Buildpacks: []buildpack.GroupElement{ - {ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, - {ID: "test.bp.two.remote", Version: "2.0.0", Homepage: "https://some-homepage-two"}, - {ID: "test.bp.three.remote", Version: "3.0.0"}, - }, - Base: files.RunImageForRebase{ - TopLayer: "some-remote-top-layer", - Reference: "some-remote-run-image-reference", - }, - Stack: files.Stack{ - RunImage: files.RunImageForExport{ - Image: "some-remote-run-image", - Mirrors: []string{"some-remote-mirror", "other-remote-mirror"}, - }, - }, - BOM: []buildpack.BOMEntry{{ - Require: buildpack.Require{ - Name: "name-1", - Version: "version-1", - Metadata: map[string]interface{}{ - "RemoteData": someData{ - String: "aString", - Bool: true, - Int: 123, - Nested: struct { - String string - }{ - String: "anotherString", - }, - }, - }, - }, - Buildpack: buildpack.GroupElement{ID: "test.bp.one.remote", Version: "1.0.0"}, - }}, - Processes: client.ProcessDetails{ - DefaultProcess: &launch.Process{ - Type: "some-remote-type", - Command: launch.RawCommand{Entries: []string{"/some/remote command"}}, - Args: []string{"some", "remote", "args"}, - Direct: false, - WorkingDirectory: "/some-test-work-dir", - }, - OtherProcesses: []launch.Process{ - { - Type: "other-remote-type", - Command: launch.RawCommand{Entries: []string{"/other/remote/command"}}, - Args: []string{"other", "remote", "args"}, - Direct: true, - WorkingDirectory: "/other-test-work-dir", - }, - }, - }, - } - - remoteInfoWithRebasable = &client.ImageInfo{ - StackID: "test.stack.id.remote", - Buildpacks: []buildpack.GroupElement{ - {ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, - {ID: "test.bp.two.remote", Version: "2.0.0", Homepage: "https://some-homepage-two"}, - {ID: "test.bp.three.remote", Version: "3.0.0"}, - }, - Base: platform.RunImageForRebase{ - TopLayer: "some-remote-top-layer", - Reference: "some-remote-run-image-reference", - }, - Stack: platform.StackMetadata{ - RunImage: platform.RunImageForExport{ - Image: "some-remote-run-image", - Mirrors: []string{"some-remote-mirror", "other-remote-mirror"}, - }, - }, - BOM: []buildpack.BOMEntry{{ - Require: buildpack.Require{ - Name: "name-1", - Version: "version-1", - Metadata: map[string]interface{}{ - "RemoteData": someData{ - String: "aString", - Bool: true, - Int: 123, - Nested: struct { - String string - }{ - String: "anotherString", - }, - }, - }, - }, - Buildpack: buildpack.GroupElement{ID: "test.bp.one.remote", Version: "1.0.0"}, - }}, - Processes: client.ProcessDetails{ - DefaultProcess: &launch.Process{ - Type: "some-remote-type", - Command: launch.RawCommand{Entries: []string{"/some/remote command"}}, - Args: []string{"some", "remote", "args"}, - Direct: false, - WorkingDirectory: "/some-test-work-dir", - }, - OtherProcesses: []launch.Process{ - { - Type: "other-remote-type", - Command: launch.RawCommand{Entries: []string{"/other/remote/command"}}, - Args: []string{"other", "remote", "args"}, - Direct: true, - WorkingDirectory: "/other-test-work-dir", - }, - }, - }, - Rebasable: true, - } - - localInfo = &client.ImageInfo{ - StackID: "test.stack.id.local", - Buildpacks: []buildpack.GroupElement{ - {ID: "test.bp.one.local", Version: "1.0.0", Homepage: "https://some-homepage-one"}, - {ID: "test.bp.two.local", Version: "2.0.0", Homepage: "https://some-homepage-two"}, - {ID: "test.bp.three.local", Version: "3.0.0"}, - }, - Base: files.RunImageForRebase{ - TopLayer: "some-local-top-layer", - Reference: "some-local-run-image-reference", - }, - Stack: files.Stack{ - RunImage: files.RunImageForExport{ - Image: "some-local-run-image", - Mirrors: []string{"some-local-mirror", "other-local-mirror"}, - }, - }, - BOM: []buildpack.BOMEntry{{ - Require: buildpack.Require{ - Name: "name-1", - Version: "version-1", - Metadata: map[string]interface{}{ - "LocalData": someData{ - Bool: false, - Int: 456, - }, - }, - }, - Buildpack: buildpack.GroupElement{ID: "test.bp.one.remote", Version: "1.0.0"}, - }}, - Processes: client.ProcessDetails{ - DefaultProcess: &launch.Process{ - Type: "some-local-type", - Command: launch.RawCommand{Entries: []string{"/some/local command"}}, - Args: []string{"some", "local", "args"}, - Direct: false, - WorkingDirectory: "/some-test-work-dir", - }, - OtherProcesses: []launch.Process{ - { - Type: "other-local-type", - Command: launch.RawCommand{Entries: []string{"/other/local/command"}}, - Args: []string{"other", "local", "args"}, - Direct: true, - WorkingDirectory: "/other-test-work-dir", - }, - }, - }, - } - - localInfoWithRebasable = &client.ImageInfo{ - StackID: "test.stack.id.local", - Buildpacks: []buildpack.GroupElement{ - {ID: "test.bp.one.local", Version: "1.0.0", Homepage: "https://some-homepage-one"}, - {ID: "test.bp.two.local", Version: "2.0.0", Homepage: "https://some-homepage-two"}, - {ID: "test.bp.three.local", Version: "3.0.0"}, - }, - Base: platform.RunImageForRebase{ - TopLayer: "some-local-top-layer", - Reference: "some-local-run-image-reference", - }, - Stack: platform.StackMetadata{ - RunImage: platform.RunImageForExport{ - Image: "some-local-run-image", - Mirrors: []string{"some-local-mirror", "other-local-mirror"}, - }, - }, - BOM: []buildpack.BOMEntry{{ - Require: buildpack.Require{ - Name: "name-1", - Version: "version-1", - Metadata: map[string]interface{}{ - "LocalData": someData{ - Bool: false, - Int: 456, - }, - }, - }, - Buildpack: buildpack.GroupElement{ID: "test.bp.one.remote", Version: "1.0.0"}, - }}, - Processes: client.ProcessDetails{ - DefaultProcess: &launch.Process{ - Type: "some-local-type", - Command: launch.RawCommand{Entries: []string{"/some/local command"}}, - Args: []string{"some", "local", "args"}, - Direct: false, - WorkingDirectory: "/some-test-work-dir", - }, - OtherProcesses: []launch.Process{ - { - Type: "other-local-type", - Command: launch.RawCommand{Entries: []string{"/other/local/command"}}, - Args: []string{"other", "local", "args"}, - Direct: true, - WorkingDirectory: "/other-test-work-dir", - }, - }, - }, - Rebasable: true, - } - - remoteWithExtensionInfo = &client.ImageInfo{ - StackID: "test.stack.id.remote", - Buildpacks: []buildpack.GroupElement{ - {ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, - {ID: "test.bp.two.remote", Version: "2.0.0", Homepage: "https://some-homepage-two"}, - {ID: "test.bp.three.remote", Version: "3.0.0"}, - }, - Extensions: []buildpack.GroupElement{ - {ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, - {ID: "test.bp.two.remote", Version: "2.0.0", Homepage: "https://some-homepage-two"}, - {ID: "test.bp.three.remote", Version: "3.0.0"}, - }, - Base: files.RunImageForRebase{ - TopLayer: "some-remote-top-layer", - Reference: "some-remote-run-image-reference", - }, - Stack: files.Stack{ - RunImage: files.RunImageForExport{ - Image: "some-remote-run-image", - Mirrors: []string{"some-remote-mirror", "other-remote-mirror"}, - }, - }, - BOM: []buildpack.BOMEntry{{ - Require: buildpack.Require{ - Name: "name-1", - Version: "version-1", - Metadata: map[string]interface{}{ - "RemoteData": someData{ - String: "aString", - Bool: true, - Int: 123, - Nested: struct { - String string - }{ - String: "anotherString", - }, - }, - }, - }, - Buildpack: buildpack.GroupElement{ID: "test.bp.one.remote", Version: "1.0.0"}, - }}, - Processes: client.ProcessDetails{ - DefaultProcess: &launch.Process{ - Type: "some-remote-type", - Command: launch.RawCommand{Entries: []string{"/some/remote command"}}, - Args: []string{"some", "remote", "args"}, - Direct: false, - WorkingDirectory: "/some-test-work-dir", - }, - OtherProcesses: []launch.Process{ - { - Type: "other-remote-type", - Command: launch.RawCommand{Entries: []string{"/other/remote/command"}}, - Args: []string{"other", "remote", "args"}, - Direct: true, - WorkingDirectory: "/other-test-work-dir", - }, - }, - }, - } - - localWithExtensionInfo = &client.ImageInfo{ - StackID: "test.stack.id.local", - Buildpacks: []buildpack.GroupElement{ - {ID: "test.bp.one.local", Version: "1.0.0", Homepage: "https://some-homepage-one"}, - {ID: "test.bp.two.local", Version: "2.0.0", Homepage: "https://some-homepage-two"}, - {ID: "test.bp.three.local", Version: "3.0.0"}, - }, - Extensions: []buildpack.GroupElement{ - {ID: "test.bp.one.local", Version: "1.0.0", Homepage: "https://some-homepage-one"}, - {ID: "test.bp.two.local", Version: "2.0.0", Homepage: "https://some-homepage-two"}, - {ID: "test.bp.three.local", Version: "3.0.0"}, - }, - Base: files.RunImageForRebase{ - TopLayer: "some-local-top-layer", - Reference: "some-local-run-image-reference", - }, - Stack: files.Stack{ - RunImage: files.RunImageForExport{ - Image: "some-local-run-image", - Mirrors: []string{"some-local-mirror", "other-local-mirror"}, - }, - }, - BOM: []buildpack.BOMEntry{{ - Require: buildpack.Require{ - Name: "name-1", - Version: "version-1", - Metadata: map[string]interface{}{ - "LocalData": someData{ - Bool: false, - Int: 456, - }, - }, - }, - Buildpack: buildpack.GroupElement{ID: "test.bp.one.remote", Version: "1.0.0"}, - }}, - Processes: client.ProcessDetails{ - DefaultProcess: &launch.Process{ - Type: "some-local-type", - Command: launch.RawCommand{Entries: []string{"/some/local command"}}, - Args: []string{"some", "local", "args"}, - Direct: false, - WorkingDirectory: "/some-test-work-dir", - }, - OtherProcesses: []launch.Process{ - { - Type: "other-local-type", - Command: launch.RawCommand{Entries: []string{"/other/local/command"}}, - Args: []string{"other", "local", "args"}, - Direct: true, - WorkingDirectory: "/other-test-work-dir", - }, - }, - }, - } + + remoteInfo = getRemoteBasicImageInfo() + remoteInfoWithRebasable = getRemoteImageInfoWithRebasable() + remoteWithExtensionInfo = getRemoteImageInfoWithExtension() + + localInfo = getBasicLocalImageInfo() + localInfoWithRebasable = getLocalImageInfoWithRebasable() + localWithExtensionInfo = getLocalImageInfoWithExtension() outBuf = bytes.Buffer{} }) @@ -1032,3 +702,235 @@ Processes: }) }) } + +func getRemoteBasicImageInfo() *client.ImageInfo { + return getRemoteImageInfo(false, false) +} +func getRemoteImageInfoWithExtension() *client.ImageInfo { + return getRemoteImageInfo(true, false) +} + +func getRemoteImageInfoWithRebasable() *client.ImageInfo { + return getRemoteImageInfo(false, true) +} + +func getRemoteImageInfo(extension bool, rebasable bool) *client.ImageInfo { + mockedStackID := "test.stack.id.remote" + + mockedBuildpacks := []buildpack.GroupElement{ + {ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, + {ID: "test.bp.two.remote", Version: "2.0.0", Homepage: "https://some-homepage-two"}, + {ID: "test.bp.three.remote", Version: "3.0.0"}, + } + + mockedBase := files.RunImageForRebase{ + TopLayer: "some-remote-top-layer", + Reference: "some-remote-run-image-reference", + } + + mockedStack := files.Stack{ + RunImage: files.RunImageForExport{ + Image: "some-remote-run-image", + Mirrors: []string{"some-remote-mirror", "other-remote-mirror"}, + }, + } + + type someData struct { + String string + Bool bool + Int int + Nested struct { + String string + } + } + mockedMetadata := map[string]interface{}{ + "RemoteData": someData{ + String: "aString", + Bool: true, + Int: 123, + Nested: struct { + String string + }{ + String: "anotherString", + }, + }, + } + + mockedBOM := []buildpack.BOMEntry{{ + Require: buildpack.Require{ + Name: "name-1", + Metadata: mockedMetadata, + }, + Buildpack: buildpack.GroupElement{ID: "test.bp.one.remote", Version: "1.0.0"}, + }} + + mockedProcesses := client.ProcessDetails{ + DefaultProcess: &launch.Process{ + Type: "some-remote-type", + Command: launch.RawCommand{Entries: []string{"/some/remote command"}}, + Args: []string{"some", "remote", "args"}, + Direct: false, + WorkingDirectory: "/some-test-work-dir", + }, + OtherProcesses: []launch.Process{ + { + Type: "other-remote-type", + Command: launch.RawCommand{Entries: []string{"/other/remote/command"}}, + Args: []string{"other", "remote", "args"}, + Direct: true, + WorkingDirectory: "/other-test-work-dir", + }, + }, + } + + mockedExtension := []buildpack.GroupElement{ + {ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, + {ID: "test.bp.two.remote", Version: "2.0.0", Homepage: "https://some-homepage-two"}, + {ID: "test.bp.three.remote", Version: "3.0.0"}, + } + + if extension { + return &client.ImageInfo{ + StackID: mockedStackID, + Buildpacks: mockedBuildpacks, + Base: mockedBase, + Stack: mockedStack, + BOM: mockedBOM, + Processes: mockedProcesses, + Extensions: mockedExtension, + } + } else if rebasable { + return &client.ImageInfo{ + StackID: mockedStackID, + Buildpacks: mockedBuildpacks, + Base: mockedBase, + Stack: mockedStack, + BOM: mockedBOM, + Processes: mockedProcesses, + Rebasable: true, + } + } else { + return &client.ImageInfo{ + StackID: mockedStackID, + Buildpacks: mockedBuildpacks, + Base: mockedBase, + Stack: mockedStack, + BOM: mockedBOM, + Processes: mockedProcesses, + } + } +} + +func getBasicLocalImageInfo() *client.ImageInfo { + return getLocalImageInfo(false, false) +} + +func getLocalImageInfoWithExtension() *client.ImageInfo { + return getLocalImageInfo(true, false) +} + +func getLocalImageInfoWithRebasable() *client.ImageInfo { + return getLocalImageInfo(false, true) +} + +func getLocalImageInfo(extension bool, rebasable bool) *client.ImageInfo { + mockedStackID := "test.stack.id.local" + + mockedBuildpacks := []buildpack.GroupElement{ + {ID: "test.bp.one.local", Version: "1.0.0", Homepage: "https://some-homepage-one"}, + {ID: "test.bp.two.local", Version: "2.0.0", Homepage: "https://some-homepage-two"}, + {ID: "test.bp.three.local", Version: "3.0.0"}, + } + + mockedBase := files.RunImageForRebase{ + TopLayer: "some-local-top-layer", + Reference: "some-local-run-image-reference", + } + + mockedPlatform := files.Stack{ + RunImage: files.RunImageForExport{ + Image: "some-local-run-image", + Mirrors: []string{"some-local-mirror", "other-local-mirror"}, + }, + } + + type someData struct { + String string + Bool bool + Int int + Nested struct { + String string + } + } + mockedMetadata := map[string]interface{}{ + "LocalData": someData{ + Bool: false, + Int: 456, + }, + } + + mockedBOM := []buildpack.BOMEntry{{ + Require: buildpack.Require{ + Name: "name-1", + Version: "version-1", + Metadata: mockedMetadata, + }, + Buildpack: buildpack.GroupElement{ID: "test.bp.one.remote", Version: "1.0.0"}, + }} + + mockedProcesses := client.ProcessDetails{ + DefaultProcess: &launch.Process{ + Type: "some-local-type", + Command: launch.RawCommand{Entries: []string{"/some/local command"}}, + Args: []string{"some", "local", "args"}, + Direct: false, + WorkingDirectory: "/some-test-work-dir", + }, + OtherProcesses: []launch.Process{ + { + Type: "other-local-type", + Command: launch.RawCommand{Entries: []string{"/other/local/command"}}, + Args: []string{"other", "local", "args"}, + Direct: true, + WorkingDirectory: "/other-test-work-dir", + }, + }, + } + + mockedExtension := []buildpack.GroupElement{ + {ID: "test.bp.one.local", Version: "1.0.0", Homepage: "https://some-homepage-one"}, + {ID: "test.bp.two.local", Version: "2.0.0", Homepage: "https://some-homepage-two"}, + {ID: "test.bp.three.local", Version: "3.0.0"}, + } + + if extension { + return &client.ImageInfo{ + StackID: mockedStackID, + Buildpacks: mockedBuildpacks, + Base: mockedBase, + Stack: mockedPlatform, + BOM: mockedBOM, + Processes: mockedProcesses, + Extensions: mockedExtension, + } + } else if rebasable { + return &client.ImageInfo{ + StackID: mockedStackID, + Buildpacks: mockedBuildpacks, + Base: mockedBase, + Stack: mockedPlatform, + BOM: mockedBOM, + Processes: mockedProcesses, + Rebasable: true, + } + } else { + return &client.ImageInfo{ + StackID: mockedStackID, + Buildpacks: mockedBuildpacks, + Base: mockedBase, + Stack: mockedPlatform, + BOM: mockedBOM, + Processes: mockedProcesses, + } + } +} From 0a22bf2168845b940b23ac51a2f1d2cf15039b33 Mon Sep 17 00:00:00 2001 From: Domenico Luciani Date: Mon, 19 Jun 2023 17:42:10 +0200 Subject: [PATCH 09/11] Adds implementation for extension and rebasable Signed-off-by: Domenico Luciani --- internal/inspectimage/info_display.go | 1 + .../inspectimage/writer/human_readable.go | 1 + .../writer/human_readable_test.go | 277 ++++++++++++------ 3 files changed, 196 insertions(+), 83 deletions(-) diff --git a/internal/inspectimage/info_display.go b/internal/inspectimage/info_display.go index db842812d..141ce3395 100644 --- a/internal/inspectimage/info_display.go +++ b/internal/inspectimage/info_display.go @@ -67,6 +67,7 @@ func NewInfoDisplay(info *client.ImageInfo, generalInfo GeneralInfo) *InfoDispla Buildpacks: displayBuildpacks(info.Buildpacks), Extensions: displayExtensions(info.Extensions), Processes: displayProcesses(info.Processes), + Rebasable: info.Rebasable, } } return &InfoDisplay{ diff --git a/internal/inspectimage/writer/human_readable.go b/internal/inspectimage/writer/human_readable.go index 1f41e64fd..0f0431878 100644 --- a/internal/inspectimage/writer/human_readable.go +++ b/internal/inspectimage/writer/human_readable.go @@ -228,6 +228,7 @@ Base Image: {{- end}} Top Layer: {{ .Info.Base.TopLayer }} {{ template "runImages" . }} +{{- template "rebasable" . }} {{ template "buildpacks" . }} {{ template "extensions" . }} {{ template "processes" . }}` diff --git a/internal/inspectimage/writer/human_readable_test.go b/internal/inspectimage/writer/human_readable_test.go index 16a3b0172..6f79b3355 100644 --- a/internal/inspectimage/writer/human_readable_test.go +++ b/internal/inspectimage/writer/human_readable_test.go @@ -32,13 +32,15 @@ func testHumanReadable(t *testing.T, when spec.G, it spec.S) { assert = h.NewAssertionManager(t) outBuf bytes.Buffer - remoteInfo *client.ImageInfo - remoteInfoWithRebasable *client.ImageInfo - localInfo *client.ImageInfo - localInfoWithRebasable *client.ImageInfo + remoteInfo *client.ImageInfo + remoteInfoWithRebasable *client.ImageInfo + remoteWithExtensionInfo *client.ImageInfo + remoteWithExtensionAndRebasableInfo *client.ImageInfo - remoteWithExtensionInfo *client.ImageInfo - localWithExtensionInfo *client.ImageInfo + localInfo *client.ImageInfo + localInfoWithRebasable *client.ImageInfo + localWithExtensionInfo *client.ImageInfo + localWithExtensionAndRebasableInfo *client.ImageInfo expectedRemoteOutput = `REMOTE: @@ -87,6 +89,72 @@ Buildpacks: test.bp.two.remote 2.0.0 https://some-homepage-two test.bp.three.remote 3.0.0 - +Processes: + TYPE SHELL COMMAND ARGS WORK DIR + some-remote-type (default) bash /some/remote command some remote args /some-test-work-dir + other-remote-type /other/remote/command other remote args /other-test-work-dir` + + expectedRemoteWithExtensionOutput = `REMOTE: + +Stack: test.stack.id.remote + +Base Image: + Reference: some-remote-run-image-reference + Top Layer: some-remote-top-layer + +Run Images: + user-configured-mirror-for-remote (user-configured) + some-remote-run-image + some-remote-mirror + other-remote-mirror + +Buildpacks: + ID VERSION HOMEPAGE + test.bp.one.remote 1.0.0 https://some-homepage-one + test.bp.two.remote 2.0.0 https://some-homepage-two + test.bp.three.remote 3.0.0 - + +Extensions: + ID VERSION HOMEPAGE + test.bp.one.remote 1.0.0 https://some-homepage-one + test.bp.two.remote 2.0.0 https://some-homepage-two + test.bp.three.remote 3.0.0 - + + +Processes: + TYPE SHELL COMMAND ARGS WORK DIR + some-remote-type (default) bash /some/remote command some remote args /some-test-work-dir + other-remote-type /other/remote/command other remote args /other-test-work-dir` + + expectedRemoteWithExtensionAndRebasableOutput = `REMOTE: + +Stack: test.stack.id.remote + +Base Image: + Reference: some-remote-run-image-reference + Top Layer: some-remote-top-layer + +Run Images: + user-configured-mirror-for-remote (user-configured) + some-remote-run-image + some-remote-mirror + other-remote-mirror + +Rebasable: true + +Buildpacks: + ID VERSION HOMEPAGE + test.bp.one.remote 1.0.0 https://some-homepage-one + test.bp.two.remote 2.0.0 https://some-homepage-two + test.bp.three.remote 3.0.0 - + +Extensions: + ID VERSION HOMEPAGE + test.bp.one.remote 1.0.0 https://some-homepage-one + test.bp.two.remote 2.0.0 https://some-homepage-two + test.bp.three.remote 3.0.0 - + + Processes: TYPE SHELL COMMAND ARGS WORK DIR some-remote-type (default) bash /some/remote command some remote args /some-test-work-dir @@ -144,39 +212,39 @@ Processes: some-local-type (default) bash /some/local command some local args /some-test-work-dir other-local-type /other/local/command other local args /other-test-work-dir` - expectedRemoteWithExtensionOutput = `REMOTE: + expectedLocalWithExtensionOutput = `LOCAL: -Stack: test.stack.id.remote +Stack: test.stack.id.local Base Image: - Reference: some-remote-run-image-reference - Top Layer: some-remote-top-layer + Reference: some-local-run-image-reference + Top Layer: some-local-top-layer Run Images: - user-configured-mirror-for-remote (user-configured) - some-remote-run-image - some-remote-mirror - other-remote-mirror + user-configured-mirror-for-local (user-configured) + some-local-run-image + some-local-mirror + other-local-mirror Buildpacks: - ID VERSION HOMEPAGE - test.bp.one.remote 1.0.0 https://some-homepage-one - test.bp.two.remote 2.0.0 https://some-homepage-two - test.bp.three.remote 3.0.0 - + ID VERSION HOMEPAGE + test.bp.one.local 1.0.0 https://some-homepage-one + test.bp.two.local 2.0.0 https://some-homepage-two + test.bp.three.local 3.0.0 - Extensions: - ID VERSION HOMEPAGE - test.bp.one.remote 1.0.0 https://some-homepage-one - test.bp.two.remote 2.0.0 https://some-homepage-two - test.bp.three.remote 3.0.0 - + ID VERSION HOMEPAGE + test.bp.one.local 1.0.0 https://some-homepage-one + test.bp.two.local 2.0.0 https://some-homepage-two + test.bp.three.local 3.0.0 - Processes: - TYPE SHELL COMMAND ARGS WORK DIR - some-remote-type (default) bash /some/remote command some remote args /some-test-work-dir - other-remote-type /other/remote/command other remote args /other-test-work-dir` + TYPE SHELL COMMAND ARGS WORK DIR + some-local-type (default) bash /some/local command some local args /some-test-work-dir + other-local-type /other/local/command other local args /other-test-work-dir` - expectedLocalWithExtensionOutput = `LOCAL: + expectedLocalWithExtensionAndRebasableOutput = `LOCAL: Stack: test.stack.id.local @@ -190,6 +258,8 @@ Run Images: some-local-mirror other-local-mirror +Rebasable: true + Buildpacks: ID VERSION HOMEPAGE test.bp.one.local 1.0.0 https://some-homepage-one @@ -211,14 +281,15 @@ Processes: when("Print", func() { it.Before(func() { - remoteInfo = getRemoteBasicImageInfo() remoteInfoWithRebasable = getRemoteImageInfoWithRebasable() remoteWithExtensionInfo = getRemoteImageInfoWithExtension() + remoteWithExtensionAndRebasableInfo = getRemoteImageInfoWithExtensionAndRebasable() localInfo = getBasicLocalImageInfo() localInfoWithRebasable = getLocalImageInfoWithRebasable() localWithExtensionInfo = getLocalImageInfoWithExtension() + localWithExtensionAndRebasableInfo = getLocalImageInfoWithExtensionAndRebasable() outBuf = bytes.Buffer{} }) @@ -373,6 +444,34 @@ Processes: assert.Contains(outBuf.String(), expectedLocalWithExtensionOutput) assert.NotContains(outBuf.String(), expectedRemoteWithExtensionOutput) }) + it("prints localWithExtension and localWithRebasable image info in a human readable format", func() { + runImageMirrors := []config.RunImage{ + { + Image: "un-used-run-image", + Mirrors: []string{"un-used"}, + }, + { + Image: "some-local-run-image", + Mirrors: []string{"user-configured-mirror-for-local"}, + }, + { + Image: "some-remote-run-image", + Mirrors: []string{"user-configured-mirror-for-remote"}, + }, + } + sharedImageInfo := inspectimage.GeneralInfo{ + Name: "test-image", + RunImageMirrors: runImageMirrors, + } + humanReadableWriter := writer.NewHumanReadable() + + logger := logging.NewLogWithWriters(&outBuf, &outBuf) + err := humanReadableWriter.Print(logger, sharedImageInfo, localWithExtensionAndRebasableInfo, nil, nil, nil) + assert.Nil(err) + + assert.Contains(outBuf.String(), expectedLocalWithExtensionAndRebasableOutput) + assert.NotContains(outBuf.String(), expectedRemoteWithExtensionOutput) + }) }) when("only remote image exists", func() { @@ -503,6 +602,34 @@ Processes: assert.NotContains(outBuf.String(), expectedLocalWithExtensionOutput) assert.Contains(outBuf.String(), expectedRemoteWithExtensionOutput) }) + it("prints remoteWithExtension and remoteWithRebasable image info in a human readable format", func() { + runImageMirrors := []config.RunImage{ + { + Image: "un-used-run-image", + Mirrors: []string{"un-used"}, + }, + { + Image: "some-local-run-image", + Mirrors: []string{"user-configured-mirror-for-local"}, + }, + { + Image: "some-remote-run-image", + Mirrors: []string{"user-configured-mirror-for-remote"}, + }, + } + sharedImageInfo := inspectimage.GeneralInfo{ + Name: "test-image", + RunImageMirrors: runImageMirrors, + } + humanReadableWriter := writer.NewHumanReadable() + + logger := logging.NewLogWithWriters(&outBuf, &outBuf) + err := humanReadableWriter.Print(logger, sharedImageInfo, nil, remoteWithExtensionAndRebasableInfo, nil, nil) + assert.Nil(err) + + assert.NotContains(outBuf.String(), expectedLocalOutput) + assert.Contains(outBuf.String(), expectedRemoteWithExtensionAndRebasableOutput) + }) when("buildpack metadata is missing", func() { it.Before(func() { @@ -714,6 +841,10 @@ func getRemoteImageInfoWithRebasable() *client.ImageInfo { return getRemoteImageInfo(false, true) } +func getRemoteImageInfoWithExtensionAndRebasable() *client.ImageInfo { + return getRemoteImageInfo(true, true) +} + func getRemoteImageInfo(extension bool, rebasable bool) *client.ImageInfo { mockedStackID := "test.stack.id.remote" @@ -789,36 +920,24 @@ func getRemoteImageInfo(extension bool, rebasable bool) *client.ImageInfo { {ID: "test.bp.three.remote", Version: "3.0.0"}, } + imageInfo := &client.ImageInfo{ + StackID: mockedStackID, + Buildpacks: mockedBuildpacks, + Base: mockedBase, + Stack: mockedStack, + BOM: mockedBOM, + Processes: mockedProcesses, + } + if extension { - return &client.ImageInfo{ - StackID: mockedStackID, - Buildpacks: mockedBuildpacks, - Base: mockedBase, - Stack: mockedStack, - BOM: mockedBOM, - Processes: mockedProcesses, - Extensions: mockedExtension, - } - } else if rebasable { - return &client.ImageInfo{ - StackID: mockedStackID, - Buildpacks: mockedBuildpacks, - Base: mockedBase, - Stack: mockedStack, - BOM: mockedBOM, - Processes: mockedProcesses, - Rebasable: true, - } - } else { - return &client.ImageInfo{ - StackID: mockedStackID, - Buildpacks: mockedBuildpacks, - Base: mockedBase, - Stack: mockedStack, - BOM: mockedBOM, - Processes: mockedProcesses, - } + imageInfo.Extensions = mockedExtension + } + + if rebasable { + imageInfo.Rebasable = true } + + return imageInfo } func getBasicLocalImageInfo() *client.ImageInfo { @@ -833,6 +952,10 @@ func getLocalImageInfoWithRebasable() *client.ImageInfo { return getLocalImageInfo(false, true) } +func getLocalImageInfoWithExtensionAndRebasable() *client.ImageInfo { + return getLocalImageInfo(true, true) +} + func getLocalImageInfo(extension bool, rebasable bool) *client.ImageInfo { mockedStackID := "test.stack.id.local" @@ -903,34 +1026,22 @@ func getLocalImageInfo(extension bool, rebasable bool) *client.ImageInfo { {ID: "test.bp.three.local", Version: "3.0.0"}, } + imageInfo := &client.ImageInfo{ + StackID: mockedStackID, + Buildpacks: mockedBuildpacks, + Base: mockedBase, + Stack: mockedPlatform, + BOM: mockedBOM, + Processes: mockedProcesses, + } + if extension { - return &client.ImageInfo{ - StackID: mockedStackID, - Buildpacks: mockedBuildpacks, - Base: mockedBase, - Stack: mockedPlatform, - BOM: mockedBOM, - Processes: mockedProcesses, - Extensions: mockedExtension, - } - } else if rebasable { - return &client.ImageInfo{ - StackID: mockedStackID, - Buildpacks: mockedBuildpacks, - Base: mockedBase, - Stack: mockedPlatform, - BOM: mockedBOM, - Processes: mockedProcesses, - Rebasable: true, - } - } else { - return &client.ImageInfo{ - StackID: mockedStackID, - Buildpacks: mockedBuildpacks, - Base: mockedBase, - Stack: mockedPlatform, - BOM: mockedBOM, - Processes: mockedProcesses, - } + imageInfo.Extensions = mockedExtension } + + if rebasable { + imageInfo.Rebasable = true + } + + return imageInfo } From 64e2364c9ba4614c1768be0251b7234081a6cabd Mon Sep 17 00:00:00 2001 From: Domenico Luciani Date: Wed, 21 Jun 2023 14:01:58 +0200 Subject: [PATCH 10/11] Now the rebasable label value changes depending on the image rebasability which until now was always set as a true Signed-off-by: Domenico Luciani --- internal/inspectimage/writer/human_readable.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/inspectimage/writer/human_readable.go b/internal/inspectimage/writer/human_readable.go index 0f0431878..b3ad6f8d2 100644 --- a/internal/inspectimage/writer/human_readable.go +++ b/internal/inspectimage/writer/human_readable.go @@ -204,7 +204,7 @@ Processes: var rebasableTemplate = ` {{- if .Info.Rebasable -}} {{- "\n\n" -}} -Rebasable: true +Rebasable: {{ .Info.Rebasable }} {{- end -}}` var imageTemplate = ` From fe499fb5ca5f4a7fe91b35412708a984b3913cb6 Mon Sep 17 00:00:00 2001 From: Domenico Luciani Date: Wed, 21 Jun 2023 15:31:55 +0200 Subject: [PATCH 11/11] Change the tests and the implementation of the template to follow the assumption that the rebasable is true when true or not set, false otherwise Signed-off-by: Domenico Luciani --- acceptance/acceptance_test.go | 4 +- .../inspectimage/writer/human_readable.go | 11 +- .../writer/human_readable_test.go | 228 ++++-------------- internal/inspectimage/writer/json_test.go | 97 +++----- internal/inspectimage/writer/toml_test.go | 94 +++----- internal/inspectimage/writer/yaml_test.go | 93 +++---- pkg/client/inspect_image.go | 2 +- pkg/client/inspect_image_test.go | 119 +++------ 8 files changed, 184 insertions(+), 464 deletions(-) diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go index 8bcb686df..a92035260 100644 --- a/acceptance/acceptance_test.go +++ b/acceptance/acceptance_test.go @@ -1153,7 +1153,7 @@ func testAcceptance( "hello_args": helloArgs, "hello_args_prefix": helloArgsPrefix, "image_workdir": imageWorkdir, - "rebasable": false, + "rebasable": true, }, ) @@ -1827,7 +1827,7 @@ func testAcceptance( "hello_args": helloArgs, "hello_args_prefix": helloArgsPrefix, "image_workdir": imageWorkdir, - "rebasable": false, + "rebasable": true, }, ) diff --git a/internal/inspectimage/writer/human_readable.go b/internal/inspectimage/writer/human_readable.go index b3ad6f8d2..d9b58ee82 100644 --- a/internal/inspectimage/writer/human_readable.go +++ b/internal/inspectimage/writer/human_readable.go @@ -202,10 +202,11 @@ Processes: {{- end }}` var rebasableTemplate = ` -{{- if .Info.Rebasable -}} -{{- "\n\n" -}} -Rebasable: {{ .Info.Rebasable }} -{{- end -}}` + +Rebasable: +{{- if or .Info.Rebasable (eq .Info.Rebasable true) }} true +{{- else }} false +{{- end }}` var imageTemplate = ` Stack: {{ .Info.StackID }} @@ -230,5 +231,5 @@ Base Image: {{ template "runImages" . }} {{- template "rebasable" . }} {{ template "buildpacks" . }} -{{ template "extensions" . }} +{{ template "extensions" . -}} {{ template "processes" . }}` diff --git a/internal/inspectimage/writer/human_readable_test.go b/internal/inspectimage/writer/human_readable_test.go index 6f79b3355..e77cec639 100644 --- a/internal/inspectimage/writer/human_readable_test.go +++ b/internal/inspectimage/writer/human_readable_test.go @@ -32,45 +32,18 @@ func testHumanReadable(t *testing.T, when spec.G, it spec.S) { assert = h.NewAssertionManager(t) outBuf bytes.Buffer - remoteInfo *client.ImageInfo - remoteInfoWithRebasable *client.ImageInfo - remoteWithExtensionInfo *client.ImageInfo - remoteWithExtensionAndRebasableInfo *client.ImageInfo + remoteInfo *client.ImageInfo + remoteWithExtensionInfo *client.ImageInfo + remoteInfoNoRebasable *client.ImageInfo - localInfo *client.ImageInfo - localInfoWithRebasable *client.ImageInfo - localWithExtensionInfo *client.ImageInfo - localWithExtensionAndRebasableInfo *client.ImageInfo + localInfo *client.ImageInfo + localWithExtensionInfo *client.ImageInfo + localInfoNoRebasable *client.ImageInfo expectedRemoteOutput = `REMOTE: Stack: test.stack.id.remote -Base Image: - Reference: some-remote-run-image-reference - Top Layer: some-remote-top-layer - -Run Images: - user-configured-mirror-for-remote (user-configured) - some-remote-run-image - some-remote-mirror - other-remote-mirror - -Buildpacks: - ID VERSION HOMEPAGE - test.bp.one.remote 1.0.0 https://some-homepage-one - test.bp.two.remote 2.0.0 https://some-homepage-two - test.bp.three.remote 3.0.0 - - -Processes: - TYPE SHELL COMMAND ARGS WORK DIR - some-remote-type (default) bash /some/remote command some remote args /some-test-work-dir - other-remote-type /other/remote/command other remote args /other-test-work-dir` - - expectedRemoteOutputWithRebasable = `REMOTE: - -Stack: test.stack.id.remote - Base Image: Reference: some-remote-run-image-reference Top Layer: some-remote-top-layer @@ -93,8 +66,7 @@ Processes: TYPE SHELL COMMAND ARGS WORK DIR some-remote-type (default) bash /some/remote command some remote args /some-test-work-dir other-remote-type /other/remote/command other remote args /other-test-work-dir` - - expectedRemoteWithExtensionOutput = `REMOTE: + expectedRemoteNoRebasableOutput = `REMOTE: Stack: test.stack.id.remote @@ -108,25 +80,20 @@ Run Images: some-remote-mirror other-remote-mirror -Buildpacks: - ID VERSION HOMEPAGE - test.bp.one.remote 1.0.0 https://some-homepage-one - test.bp.two.remote 2.0.0 https://some-homepage-two - test.bp.three.remote 3.0.0 - +Rebasable: false -Extensions: +Buildpacks: ID VERSION HOMEPAGE test.bp.one.remote 1.0.0 https://some-homepage-one test.bp.two.remote 2.0.0 https://some-homepage-two test.bp.three.remote 3.0.0 - - Processes: TYPE SHELL COMMAND ARGS WORK DIR some-remote-type (default) bash /some/remote command some remote args /some-test-work-dir other-remote-type /other/remote/command other remote args /other-test-work-dir` - expectedRemoteWithExtensionAndRebasableOutput = `REMOTE: + expectedRemoteWithExtensionOutput = `REMOTE: Stack: test.stack.id.remote @@ -154,7 +121,6 @@ Extensions: test.bp.two.remote 2.0.0 https://some-homepage-two test.bp.three.remote 3.0.0 - - Processes: TYPE SHELL COMMAND ARGS WORK DIR some-remote-type (default) bash /some/remote command some remote args /some-test-work-dir @@ -164,31 +130,6 @@ Processes: Stack: test.stack.id.local -Base Image: - Reference: some-local-run-image-reference - Top Layer: some-local-top-layer - -Run Images: - user-configured-mirror-for-local (user-configured) - some-local-run-image - some-local-mirror - other-local-mirror - -Buildpacks: - ID VERSION HOMEPAGE - test.bp.one.local 1.0.0 https://some-homepage-one - test.bp.two.local 2.0.0 https://some-homepage-two - test.bp.three.local 3.0.0 - - -Processes: - TYPE SHELL COMMAND ARGS WORK DIR - some-local-type (default) bash /some/local command some local args /some-test-work-dir - other-local-type /other/local/command other local args /other-test-work-dir` - - expectedLocalOutputWithRebasable = `LOCAL: - -Stack: test.stack.id.local - Base Image: Reference: some-local-run-image-reference Top Layer: some-local-top-layer @@ -211,8 +152,7 @@ Processes: TYPE SHELL COMMAND ARGS WORK DIR some-local-type (default) bash /some/local command some local args /some-test-work-dir other-local-type /other/local/command other local args /other-test-work-dir` - - expectedLocalWithExtensionOutput = `LOCAL: + expectedLocalNoRebasableOutput = `LOCAL: Stack: test.stack.id.local @@ -226,25 +166,20 @@ Run Images: some-local-mirror other-local-mirror -Buildpacks: - ID VERSION HOMEPAGE - test.bp.one.local 1.0.0 https://some-homepage-one - test.bp.two.local 2.0.0 https://some-homepage-two - test.bp.three.local 3.0.0 - +Rebasable: false -Extensions: +Buildpacks: ID VERSION HOMEPAGE test.bp.one.local 1.0.0 https://some-homepage-one test.bp.two.local 2.0.0 https://some-homepage-two test.bp.three.local 3.0.0 - - Processes: TYPE SHELL COMMAND ARGS WORK DIR some-local-type (default) bash /some/local command some local args /some-test-work-dir other-local-type /other/local/command other local args /other-test-work-dir` - expectedLocalWithExtensionAndRebasableOutput = `LOCAL: + expectedLocalWithExtensionOutput = `LOCAL: Stack: test.stack.id.local @@ -272,7 +207,6 @@ Extensions: test.bp.two.local 2.0.0 https://some-homepage-two test.bp.three.local 3.0.0 - - Processes: TYPE SHELL COMMAND ARGS WORK DIR some-local-type (default) bash /some/local command some local args /some-test-work-dir @@ -281,15 +215,13 @@ Processes: when("Print", func() { it.Before(func() { - remoteInfo = getRemoteBasicImageInfo() - remoteInfoWithRebasable = getRemoteImageInfoWithRebasable() - remoteWithExtensionInfo = getRemoteImageInfoWithExtension() - remoteWithExtensionAndRebasableInfo = getRemoteImageInfoWithExtensionAndRebasable() + remoteInfo = getRemoteBasicImageInfo(t) + remoteWithExtensionInfo = getRemoteImageInfoWithExtension(t) + remoteInfoNoRebasable = getRemoteImageInfoNoRebasable(t) - localInfo = getBasicLocalImageInfo() - localInfoWithRebasable = getLocalImageInfoWithRebasable() - localWithExtensionInfo = getLocalImageInfoWithExtension() - localWithExtensionAndRebasableInfo = getLocalImageInfoWithExtensionAndRebasable() + localInfo = getBasicLocalImageInfo(t) + localWithExtensionInfo = getLocalImageInfoWithExtension(t) + localInfoNoRebasable = getLocalImageInfoNoRebasable(t) outBuf = bytes.Buffer{} }) @@ -385,7 +317,7 @@ Processes: assert.Contains(outBuf.String(), expectedLocalOutput) assert.NotContains(outBuf.String(), expectedRemoteOutput) }) - it("prints local rebasable image info in a human readable format", func() { + it("prints local no rebasable image info in a human readable format", func() { runImageMirrors := []config.RunImage{ { Image: "un-used-run-image", @@ -407,10 +339,10 @@ Processes: humanReadableWriter := writer.NewHumanReadable() logger := logging.NewLogWithWriters(&outBuf, &outBuf) - err := humanReadableWriter.Print(logger, sharedImageInfo, localInfoWithRebasable, nil, nil, nil) + err := humanReadableWriter.Print(logger, sharedImageInfo, localInfoNoRebasable, nil, nil, nil) assert.Nil(err) - assert.Contains(outBuf.String(), expectedLocalOutputWithRebasable) + assert.Contains(outBuf.String(), expectedLocalNoRebasableOutput) assert.NotContains(outBuf.String(), expectedRemoteOutput) }) }) @@ -444,34 +376,6 @@ Processes: assert.Contains(outBuf.String(), expectedLocalWithExtensionOutput) assert.NotContains(outBuf.String(), expectedRemoteWithExtensionOutput) }) - it("prints localWithExtension and localWithRebasable image info in a human readable format", func() { - runImageMirrors := []config.RunImage{ - { - Image: "un-used-run-image", - Mirrors: []string{"un-used"}, - }, - { - Image: "some-local-run-image", - Mirrors: []string{"user-configured-mirror-for-local"}, - }, - { - Image: "some-remote-run-image", - Mirrors: []string{"user-configured-mirror-for-remote"}, - }, - } - sharedImageInfo := inspectimage.GeneralInfo{ - Name: "test-image", - RunImageMirrors: runImageMirrors, - } - humanReadableWriter := writer.NewHumanReadable() - - logger := logging.NewLogWithWriters(&outBuf, &outBuf) - err := humanReadableWriter.Print(logger, sharedImageInfo, localWithExtensionAndRebasableInfo, nil, nil, nil) - assert.Nil(err) - - assert.Contains(outBuf.String(), expectedLocalWithExtensionAndRebasableOutput) - assert.NotContains(outBuf.String(), expectedRemoteWithExtensionOutput) - }) }) when("only remote image exists", func() { @@ -503,7 +407,7 @@ Processes: assert.NotContains(outBuf.String(), expectedLocalOutput) assert.Contains(outBuf.String(), expectedRemoteOutput) }) - it("prints remote rebasable image info in a human readable format", func() { + it("prints remote no rebasable image info in a human readable format", func() { runImageMirrors := []config.RunImage{ { Image: "un-used-run-image", @@ -525,11 +429,11 @@ Processes: humanReadableWriter := writer.NewHumanReadable() logger := logging.NewLogWithWriters(&outBuf, &outBuf) - err := humanReadableWriter.Print(logger, sharedImageInfo, nil, remoteInfoWithRebasable, nil, nil) + err := humanReadableWriter.Print(logger, sharedImageInfo, nil, remoteInfoNoRebasable, nil, nil) assert.Nil(err) - assert.Contains(outBuf.String(), expectedRemoteOutputWithRebasable) assert.NotContains(outBuf.String(), expectedLocalOutput) + assert.Contains(outBuf.String(), expectedRemoteNoRebasableOutput) }) when("buildpack metadata is missing", func() { @@ -602,34 +506,6 @@ Processes: assert.NotContains(outBuf.String(), expectedLocalWithExtensionOutput) assert.Contains(outBuf.String(), expectedRemoteWithExtensionOutput) }) - it("prints remoteWithExtension and remoteWithRebasable image info in a human readable format", func() { - runImageMirrors := []config.RunImage{ - { - Image: "un-used-run-image", - Mirrors: []string{"un-used"}, - }, - { - Image: "some-local-run-image", - Mirrors: []string{"user-configured-mirror-for-local"}, - }, - { - Image: "some-remote-run-image", - Mirrors: []string{"user-configured-mirror-for-remote"}, - }, - } - sharedImageInfo := inspectimage.GeneralInfo{ - Name: "test-image", - RunImageMirrors: runImageMirrors, - } - humanReadableWriter := writer.NewHumanReadable() - - logger := logging.NewLogWithWriters(&outBuf, &outBuf) - err := humanReadableWriter.Print(logger, sharedImageInfo, nil, remoteWithExtensionAndRebasableInfo, nil, nil) - assert.Nil(err) - - assert.NotContains(outBuf.String(), expectedLocalOutput) - assert.Contains(outBuf.String(), expectedRemoteWithExtensionAndRebasableOutput) - }) when("buildpack metadata is missing", func() { it.Before(func() { @@ -830,22 +706,23 @@ Processes: }) } -func getRemoteBasicImageInfo() *client.ImageInfo { - return getRemoteImageInfo(false, false) +func getRemoteBasicImageInfo(t testing.TB) *client.ImageInfo { + t.Helper() + return getRemoteImageInfo(t, false, true) } -func getRemoteImageInfoWithExtension() *client.ImageInfo { - return getRemoteImageInfo(true, false) +func getRemoteImageInfoWithExtension(t testing.TB) *client.ImageInfo { + t.Helper() + return getRemoteImageInfo(t, true, true) } -func getRemoteImageInfoWithRebasable() *client.ImageInfo { - return getRemoteImageInfo(false, true) +func getRemoteImageInfoNoRebasable(t testing.TB) *client.ImageInfo { + t.Helper() + return getRemoteImageInfo(t, false, false) } -func getRemoteImageInfoWithExtensionAndRebasable() *client.ImageInfo { - return getRemoteImageInfo(true, true) -} +func getRemoteImageInfo(t testing.TB, extension bool, rebasable bool) *client.ImageInfo { + t.Helper() -func getRemoteImageInfo(extension bool, rebasable bool) *client.ImageInfo { mockedStackID := "test.stack.id.remote" mockedBuildpacks := []buildpack.GroupElement{ @@ -927,36 +804,34 @@ func getRemoteImageInfo(extension bool, rebasable bool) *client.ImageInfo { Stack: mockedStack, BOM: mockedBOM, Processes: mockedProcesses, + Rebasable: rebasable, } if extension { imageInfo.Extensions = mockedExtension } - if rebasable { - imageInfo.Rebasable = true - } - return imageInfo } -func getBasicLocalImageInfo() *client.ImageInfo { - return getLocalImageInfo(false, false) +func getBasicLocalImageInfo(t testing.TB) *client.ImageInfo { + t.Helper() + return getLocalImageInfo(t, false, true) } -func getLocalImageInfoWithExtension() *client.ImageInfo { - return getLocalImageInfo(true, false) +func getLocalImageInfoWithExtension(t testing.TB) *client.ImageInfo { + t.Helper() + return getLocalImageInfo(t, true, true) } -func getLocalImageInfoWithRebasable() *client.ImageInfo { - return getLocalImageInfo(false, true) +func getLocalImageInfoNoRebasable(t testing.TB) *client.ImageInfo { + t.Helper() + return getLocalImageInfo(t, false, false) } -func getLocalImageInfoWithExtensionAndRebasable() *client.ImageInfo { - return getLocalImageInfo(true, true) -} +func getLocalImageInfo(t testing.TB, extension bool, rebasable bool) *client.ImageInfo { + t.Helper() -func getLocalImageInfo(extension bool, rebasable bool) *client.ImageInfo { mockedStackID := "test.stack.id.local" mockedBuildpacks := []buildpack.GroupElement{ @@ -1033,15 +908,12 @@ func getLocalImageInfo(extension bool, rebasable bool) *client.ImageInfo { Stack: mockedPlatform, BOM: mockedBOM, Processes: mockedProcesses, + Rebasable: rebasable, } if extension { imageInfo.Extensions = mockedExtension } - if rebasable { - imageInfo.Rebasable = true - } - return imageInfo } diff --git a/internal/inspectimage/writer/json_test.go b/internal/inspectimage/writer/json_test.go index 519a8609c..fa61c3f18 100644 --- a/internal/inspectimage/writer/json_test.go +++ b/internal/inspectimage/writer/json_test.go @@ -30,15 +30,15 @@ func testJSON(t *testing.T, when spec.G, it spec.S) { assert = h.NewAssertionManager(t) outBuf bytes.Buffer - remoteInfo *client.ImageInfo - remoteInfoWithRebasable *client.ImageInfo - localInfo *client.ImageInfo - localInfoWithRebasable *client.ImageInfo + remoteInfo *client.ImageInfo + remoteInfoNoRebasable *client.ImageInfo + localInfo *client.ImageInfo + localInfoNoRebasable *client.ImageInfo expectedLocalOutput = `{ "local_info": { "stack": "test.stack.id.local", - "rebasable": false, + "rebasable": true, "base_image": { "top_layer": "some-local-top-layer", "reference": "some-local-run-image-reference" @@ -99,10 +99,10 @@ func testJSON(t *testing.T, when spec.G, it spec.S) { ] } }` - expectedLocalOutputWithRebasable = `{ + expectedLocalNoRebasableOutput = `{ "local_info": { "stack": "test.stack.id.local", - "rebasable": true, + "rebasable": false, "base_image": { "top_layer": "some-local-top-layer", "reference": "some-local-run-image-reference" @@ -166,7 +166,7 @@ func testJSON(t *testing.T, when spec.G, it spec.S) { expectedRemoteOutput = `{ "remote_info": { "stack": "test.stack.id.remote", - "rebasable": false, + "rebasable": true, "base_image": { "top_layer": "some-remote-top-layer", "reference": "some-remote-run-image-reference" @@ -227,10 +227,10 @@ func testJSON(t *testing.T, when spec.G, it spec.S) { ] } }` - expectedRemoteOutputWithRebasable = `{ + expectedRemoteNoRebasableOutput = `{ "remote_info": { "stack": "test.stack.id.remote", - "rebasable": true, + "rebasable": false, "base_image": { "top_layer": "some-remote-top-layer", "reference": "some-remote-run-image-reference" @@ -357,20 +357,20 @@ func testJSON(t *testing.T, when spec.G, it spec.S) { }, }, }, + Rebasable: true, } - - remoteInfoWithRebasable = &client.ImageInfo{ + remoteInfoNoRebasable = &client.ImageInfo{ StackID: "test.stack.id.remote", Buildpacks: []buildpack.GroupElement{ {ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, {ID: "test.bp.two.remote", Version: "2.0.0", Homepage: "https://some-homepage-two"}, }, - Base: platform.RunImageForRebase{ + Base: files.RunImageForRebase{ TopLayer: "some-remote-top-layer", Reference: "some-remote-run-image-reference", }, - Stack: platform.StackMetadata{ - RunImage: platform.RunImageForExport{ + Stack: files.Stack{ + RunImage: files.RunImageForExport{ Image: "some-remote-run-image", Mirrors: []string{"some-remote-mirror", "other-remote-mirror"}, }, @@ -412,7 +412,7 @@ func testJSON(t *testing.T, when spec.G, it spec.S) { }, }, }, - Rebasable: true, + Rebasable: false, } localInfo = &client.ImageInfo{ @@ -462,20 +462,20 @@ func testJSON(t *testing.T, when spec.G, it spec.S) { }, }, }, + Rebasable: true, } - - localInfoWithRebasable = &client.ImageInfo{ + localInfoNoRebasable = &client.ImageInfo{ StackID: "test.stack.id.local", Buildpacks: []buildpack.GroupElement{ {ID: "test.bp.one.local", Version: "1.0.0", Homepage: "https://some-homepage-one"}, {ID: "test.bp.two.local", Version: "2.0.0", Homepage: "https://some-homepage-two"}, }, - Base: platform.RunImageForRebase{ + Base: files.RunImageForRebase{ TopLayer: "some-local-top-layer", Reference: "some-local-run-image-reference", }, - Stack: platform.StackMetadata{ - RunImage: platform.RunImageForExport{ + Stack: files.Stack{ + RunImage: files.RunImageForExport{ Image: "some-local-run-image", Mirrors: []string{"some-local-mirror", "other-local-mirror"}, }, @@ -511,7 +511,7 @@ func testJSON(t *testing.T, when spec.G, it spec.S) { }, }, }, - Rebasable: true, + Rebasable: false, } outBuf = bytes.Buffer{} @@ -547,10 +547,7 @@ func testJSON(t *testing.T, when spec.G, it spec.S) { assert.ContainsJSON(outBuf.String(), expectedLocalOutput) assert.ContainsJSON(outBuf.String(), expectedRemoteOutput) }) - }) - - when("only local image exists", func() { - it("prints local image info in JSON format", func() { + it("prints both local and remote no rebasable images info in a JSON format", func() { runImageMirrors := []config.RunImage{ { Image: "un-used-run-image", @@ -572,16 +569,17 @@ func testJSON(t *testing.T, when spec.G, it spec.S) { jsonWriter := writer.NewJSON() logger := logging.NewLogWithWriters(&outBuf, &outBuf) - err := jsonWriter.Print(logger, sharedImageInfo, localInfo, nil, nil, nil) + err := jsonWriter.Print(logger, sharedImageInfo, localInfoNoRebasable, remoteInfoNoRebasable, nil, nil) assert.Nil(err) assert.ContainsJSON(outBuf.String(), `{ "image_name": "test-image" }`) - assert.ContainsJSON(outBuf.String(), expectedLocalOutput) - - assert.NotContains(outBuf.String(), "test.stack.id.remote") - assert.ContainsJSON(outBuf.String(), expectedLocalOutput) + assert.ContainsJSON(outBuf.String(), expectedLocalNoRebasableOutput) + assert.ContainsJSON(outBuf.String(), expectedRemoteNoRebasableOutput) }) - it("prints local rebasable image info in JSON format", func() { + }) + + when("only local image exists", func() { + it("prints local image info in JSON format", func() { runImageMirrors := []config.RunImage{ { Image: "un-used-run-image", @@ -603,12 +601,14 @@ func testJSON(t *testing.T, when spec.G, it spec.S) { jsonWriter := writer.NewJSON() logger := logging.NewLogWithWriters(&outBuf, &outBuf) - err := jsonWriter.Print(logger, sharedImageInfo, localInfoWithRebasable, nil, nil, nil) + err := jsonWriter.Print(logger, sharedImageInfo, localInfo, nil, nil, nil) assert.Nil(err) assert.ContainsJSON(outBuf.String(), `{ "image_name": "test-image" }`) - assert.ContainsJSON(outBuf.String(), expectedLocalOutputWithRebasable) + assert.ContainsJSON(outBuf.String(), expectedLocalOutput) + assert.NotContains(outBuf.String(), "test.stack.id.remote") + assert.ContainsJSON(outBuf.String(), expectedLocalOutput) }) }) @@ -642,35 +642,6 @@ func testJSON(t *testing.T, when spec.G, it spec.S) { assert.NotContains(outBuf.String(), "test.stack.id.local") assert.ContainsJSON(outBuf.String(), expectedRemoteOutput) }) - it("prints remote rebasable image info in JSON format", func() { - runImageMirrors := []config.RunImage{ - { - Image: "un-used-run-image", - Mirrors: []string{"un-used"}, - }, - { - Image: "some-local-run-image", - Mirrors: []string{"user-configured-mirror-for-local"}, - }, - { - Image: "some-remote-run-image", - Mirrors: []string{"user-configured-mirror-for-remote"}, - }, - } - sharedImageInfo := inspectimage.GeneralInfo{ - Name: "test-image", - RunImageMirrors: runImageMirrors, - } - jsonWriter := writer.NewJSON() - - logger := logging.NewLogWithWriters(&outBuf, &outBuf) - err := jsonWriter.Print(logger, sharedImageInfo, nil, remoteInfoWithRebasable, nil, nil) - assert.Nil(err) - - assert.ContainsJSON(outBuf.String(), `{ "image_name": "test-image" }`) - assert.NotContains(outBuf.String(), "test.stack.id.local") - assert.ContainsJSON(outBuf.String(), expectedRemoteOutputWithRebasable) - }) }) }) } diff --git a/internal/inspectimage/writer/toml_test.go b/internal/inspectimage/writer/toml_test.go index bae26d643..27f92f4de 100644 --- a/internal/inspectimage/writer/toml_test.go +++ b/internal/inspectimage/writer/toml_test.go @@ -30,14 +30,14 @@ func testTOML(t *testing.T, when spec.G, it spec.S) { assert = h.NewAssertionManager(t) outBuf bytes.Buffer - remoteInfo *client.ImageInfo - remoteInfoWithRebasable *client.ImageInfo - localInfo *client.ImageInfo - localInfoWithRebasable *client.ImageInfo + remoteInfo *client.ImageInfo + remoteInfoNoRebasable *client.ImageInfo + localInfo *client.ImageInfo + localInfoNoRebasable *client.ImageInfo expectedLocalOutput = `[local_info] stack = 'test.stack.id.local' -rebasable = false +rebasable = true [local_info.base_image] top_layer = 'some-local-top-layer' @@ -90,10 +90,9 @@ args = [ ] working-dir = "/other-test-work-dir" ` - - expectedLocalOutputWithRebasable = `[local_info] + expectedLocalNoRebasableOutput = `[local_info] stack = 'test.stack.id.local' -rebasable = true +rebasable = false [local_info.base_image] top_layer = 'some-local-top-layer' @@ -150,7 +149,7 @@ working-dir = "/other-test-work-dir" expectedRemoteOutput = ` [remote_info] stack = 'test.stack.id.remote' -rebasable = false +rebasable = true [remote_info.base_image] top_layer = 'some-remote-top-layer' @@ -203,11 +202,10 @@ args = [ ] working-dir = "/other-test-work-dir" ` - - expectedRemoteOutputWithRebasable = ` + expectedRemoteNoRebasableOutput = ` [remote_info] stack = 'test.stack.id.remote' -rebasable = true +rebasable = false [remote_info.base_image] top_layer = 'some-remote-top-layer' @@ -326,19 +324,20 @@ working-dir = "/other-test-work-dir" }, }, }, + Rebasable: true, } - remoteInfoWithRebasable = &client.ImageInfo{ + remoteInfoNoRebasable = &client.ImageInfo{ StackID: "test.stack.id.remote", Buildpacks: []buildpack.GroupElement{ {ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, {ID: "test.bp.two.remote", Version: "2.0.0", Homepage: "https://some-homepage-two"}, }, - Base: platform.RunImageForRebase{ + Base: files.RunImageForRebase{ TopLayer: "some-remote-top-layer", Reference: "some-remote-run-image-reference", }, - Stack: platform.StackMetadata{ - RunImage: platform.RunImageForExport{ + Stack: files.Stack{ + RunImage: files.RunImageForExport{ Image: "some-remote-run-image", Mirrors: []string{"some-remote-mirror", "other-remote-mirror"}, }, @@ -380,7 +379,7 @@ working-dir = "/other-test-work-dir" }, }, }, - Rebasable: true, + Rebasable: false, } localInfo = &client.ImageInfo{ @@ -430,20 +429,20 @@ working-dir = "/other-test-work-dir" }, }, }, + Rebasable: true, } - - localInfoWithRebasable = &client.ImageInfo{ + localInfoNoRebasable = &client.ImageInfo{ StackID: "test.stack.id.local", Buildpacks: []buildpack.GroupElement{ {ID: "test.bp.one.local", Version: "1.0.0", Homepage: "https://some-homepage-one"}, {ID: "test.bp.two.local", Version: "2.0.0", Homepage: "https://some-homepage-two"}, }, - Base: platform.RunImageForRebase{ + Base: files.RunImageForRebase{ TopLayer: "some-local-top-layer", Reference: "some-local-run-image-reference", }, - Stack: platform.StackMetadata{ - RunImage: platform.RunImageForExport{ + Stack: files.Stack{ + RunImage: files.RunImageForExport{ Image: "some-local-run-image", Mirrors: []string{"some-local-mirror", "other-local-mirror"}, }, @@ -479,7 +478,7 @@ working-dir = "/other-test-work-dir" }, }, }, - Rebasable: true, + Rebasable: false, } outBuf = bytes.Buffer{} @@ -515,10 +514,7 @@ working-dir = "/other-test-work-dir" assert.ContainsTOML(outBuf.String(), expectedLocalOutput) assert.ContainsTOML(outBuf.String(), expectedRemoteOutput) }) - }) - - when("only local image exists", func() { - it("prints local image info in TOML format", func() { + it("prints both local and remote no rebasable images info in a TOML format", func() { runImageMirrors := []config.RunImage{ { Image: "un-used-run-image", @@ -540,14 +536,17 @@ working-dir = "/other-test-work-dir" tomlWriter := writer.NewTOML() logger := logging.NewLogWithWriters(&outBuf, &outBuf) - err := tomlWriter.Print(logger, sharedImageInfo, localInfo, nil, nil, nil) + err := tomlWriter.Print(logger, sharedImageInfo, localInfoNoRebasable, remoteInfoNoRebasable, nil, nil) assert.Nil(err) assert.ContainsTOML(outBuf.String(), `image_name = "test-image"`) - assert.NotContains(outBuf.String(), "test.stack.id.remote") - assert.ContainsTOML(outBuf.String(), expectedLocalOutput) + assert.ContainsTOML(outBuf.String(), expectedLocalNoRebasableOutput) + assert.ContainsTOML(outBuf.String(), expectedRemoteNoRebasableOutput) }) - it("prints local rebasable image info in TOML format", func() { + }) + + when("only local image exists", func() { + it("prints local image info in TOML format", func() { runImageMirrors := []config.RunImage{ { Image: "un-used-run-image", @@ -569,12 +568,12 @@ working-dir = "/other-test-work-dir" tomlWriter := writer.NewTOML() logger := logging.NewLogWithWriters(&outBuf, &outBuf) - err := tomlWriter.Print(logger, sharedImageInfo, localInfoWithRebasable, nil, nil, nil) + err := tomlWriter.Print(logger, sharedImageInfo, localInfo, nil, nil, nil) assert.Nil(err) assert.ContainsTOML(outBuf.String(), `image_name = "test-image"`) assert.NotContains(outBuf.String(), "test.stack.id.remote") - assert.ContainsTOML(outBuf.String(), expectedLocalOutputWithRebasable) + assert.ContainsTOML(outBuf.String(), expectedLocalOutput) }) }) @@ -608,35 +607,6 @@ working-dir = "/other-test-work-dir" assert.NotContains(outBuf.String(), "test.stack.id.local") assert.ContainsTOML(outBuf.String(), expectedRemoteOutput) }) - it("prints remote rebasable image info in TOML format", func() { - runImageMirrors := []config.RunImage{ - { - Image: "un-used-run-image", - Mirrors: []string{"un-used"}, - }, - { - Image: "some-local-run-image", - Mirrors: []string{"user-configured-mirror-for-local"}, - }, - { - Image: "some-remote-run-image", - Mirrors: []string{"user-configured-mirror-for-remote"}, - }, - } - sharedImageInfo := inspectimage.GeneralInfo{ - Name: "test-image", - RunImageMirrors: runImageMirrors, - } - tomlWriter := writer.NewTOML() - - logger := logging.NewLogWithWriters(&outBuf, &outBuf) - err := tomlWriter.Print(logger, sharedImageInfo, nil, remoteInfoWithRebasable, nil, nil) - assert.Nil(err) - - assert.ContainsTOML(outBuf.String(), `image_name = "test-image"`) - assert.NotContains(outBuf.String(), "test.stack.id.local") - assert.ContainsTOML(outBuf.String(), expectedRemoteOutputWithRebasable) - }) }) }) } diff --git a/internal/inspectimage/writer/yaml_test.go b/internal/inspectimage/writer/yaml_test.go index 13d676c96..ee97ec7a0 100644 --- a/internal/inspectimage/writer/yaml_test.go +++ b/internal/inspectimage/writer/yaml_test.go @@ -30,15 +30,15 @@ func testYAML(t *testing.T, when spec.G, it spec.S) { assert = h.NewAssertionManager(t) outBuf bytes.Buffer - remoteInfo *client.ImageInfo - remoteInfoWithRebasable *client.ImageInfo - localInfo *client.ImageInfo - localInfoWithRebasable *client.ImageInfo + remoteInfo *client.ImageInfo + remoteInfoNoRebasable *client.ImageInfo + localInfo *client.ImageInfo + localInfoNoRebasable *client.ImageInfo expectedLocalOutput = `--- local_info: stack: test.stack.id.local - rebasable: false + rebasable: true base_image: top_layer: some-local-top-layer reference: some-local-run-image-reference @@ -76,10 +76,10 @@ local_info: - args working-dir: /other-test-work-dir ` - expectedLocalOutputWithRebasable = `--- + expectedLocalNoRebasableOutput = `--- local_info: stack: test.stack.id.local - rebasable: true + rebasable: false base_image: top_layer: some-local-top-layer reference: some-local-run-image-reference @@ -120,7 +120,7 @@ local_info: expectedRemoteOutput = `--- remote_info: stack: test.stack.id.remote - rebasable: false + rebasable: true base_image: top_layer: some-remote-top-layer reference: some-remote-run-image-reference @@ -158,10 +158,10 @@ remote_info: - args working-dir: /other-test-work-dir ` - expectedRemoteOutputWithRebasable = `--- + expectedRemoteNoRebasableOutput = `--- remote_info: stack: test.stack.id.remote - rebasable: true + rebasable: false base_image: top_layer: some-remote-top-layer reference: some-remote-run-image-reference @@ -265,20 +265,20 @@ remote_info: }, }, }, + Rebasable: true, } - - remoteInfoWithRebasable = &client.ImageInfo{ + remoteInfoNoRebasable = &client.ImageInfo{ StackID: "test.stack.id.remote", Buildpacks: []buildpack.GroupElement{ {ID: "test.bp.one.remote", Version: "1.0.0", Homepage: "https://some-homepage-one"}, {ID: "test.bp.two.remote", Version: "2.0.0", Homepage: "https://some-homepage-two"}, }, - Base: platform.RunImageForRebase{ + Base: files.RunImageForRebase{ TopLayer: "some-remote-top-layer", Reference: "some-remote-run-image-reference", }, - Stack: platform.StackMetadata{ - RunImage: platform.RunImageForExport{ + Stack: files.Stack{ + RunImage: files.RunImageForExport{ Image: "some-remote-run-image", Mirrors: []string{"some-remote-mirror", "other-remote-mirror"}, }, @@ -320,7 +320,7 @@ remote_info: }, }, }, - Rebasable: true, + Rebasable: false, } localInfo = &client.ImageInfo{ @@ -370,20 +370,20 @@ remote_info: }, }, }, + Rebasable: true, } - - localInfoWithRebasable = &client.ImageInfo{ + localInfoNoRebasable = &client.ImageInfo{ StackID: "test.stack.id.local", Buildpacks: []buildpack.GroupElement{ {ID: "test.bp.one.local", Version: "1.0.0", Homepage: "https://some-homepage-one"}, {ID: "test.bp.two.local", Version: "2.0.0", Homepage: "https://some-homepage-two"}, }, - Base: platform.RunImageForRebase{ + Base: files.RunImageForRebase{ TopLayer: "some-local-top-layer", Reference: "some-local-run-image-reference", }, - Stack: platform.StackMetadata{ - RunImage: platform.RunImageForExport{ + Stack: files.Stack{ + RunImage: files.RunImageForExport{ Image: "some-local-run-image", Mirrors: []string{"some-local-mirror", "other-local-mirror"}, }, @@ -419,7 +419,7 @@ remote_info: }, }, }, - Rebasable: true, + Rebasable: false, } outBuf = bytes.Buffer{} @@ -455,10 +455,7 @@ remote_info: assert.ContainsYAML(outBuf.String(), expectedLocalOutput) assert.ContainsYAML(outBuf.String(), expectedRemoteOutput) }) - }) - - when("only local image exists", func() { - it("prints local image info in YAML format", func() { + it("prints both local and remote no rebasable images info in a YAML format", func() { runImageMirrors := []config.RunImage{ { Image: "un-used-run-image", @@ -480,14 +477,17 @@ remote_info: yamlWriter := writer.NewYAML() logger := logging.NewLogWithWriters(&outBuf, &outBuf) - err := yamlWriter.Print(logger, sharedImageInfo, localInfo, nil, nil, nil) + err := yamlWriter.Print(logger, sharedImageInfo, localInfoNoRebasable, remoteInfoNoRebasable, nil, nil) assert.Nil(err) assert.ContainsYAML(outBuf.String(), `"image_name": "test-image"`) - assert.ContainsYAML(outBuf.String(), expectedLocalOutput) - assert.NotContains(outBuf.String(), "test.stack.id.remote") + assert.ContainsYAML(outBuf.String(), expectedLocalNoRebasableOutput) + assert.ContainsYAML(outBuf.String(), expectedRemoteNoRebasableOutput) }) - it("prints local rebasable image info in YAML format", func() { + }) + + when("only local image exists", func() { + it("prints local image info in YAML format", func() { runImageMirrors := []config.RunImage{ { Image: "un-used-run-image", @@ -509,11 +509,11 @@ remote_info: yamlWriter := writer.NewYAML() logger := logging.NewLogWithWriters(&outBuf, &outBuf) - err := yamlWriter.Print(logger, sharedImageInfo, localInfoWithRebasable, nil, nil, nil) + err := yamlWriter.Print(logger, sharedImageInfo, localInfo, nil, nil, nil) assert.Nil(err) assert.ContainsYAML(outBuf.String(), `"image_name": "test-image"`) - assert.ContainsYAML(outBuf.String(), expectedLocalOutputWithRebasable) + assert.ContainsYAML(outBuf.String(), expectedLocalOutput) assert.NotContains(outBuf.String(), "test.stack.id.remote") }) }) @@ -548,35 +548,6 @@ remote_info: assert.NotContains(outBuf.String(), "test.stack.id.local") assert.ContainsYAML(outBuf.String(), expectedRemoteOutput) }) - it("prints remote rebasable image info in YAML format", func() { - runImageMirrors := []config.RunImage{ - { - Image: "un-used-run-image", - Mirrors: []string{"un-used"}, - }, - { - Image: "some-local-run-image", - Mirrors: []string{"user-configured-mirror-for-local"}, - }, - { - Image: "some-remote-run-image", - Mirrors: []string{"user-configured-mirror-for-remote"}, - }, - } - sharedImageInfo := inspectimage.GeneralInfo{ - Name: "test-image", - RunImageMirrors: runImageMirrors, - } - yamlWriter := writer.NewYAML() - - logger := logging.NewLogWithWriters(&outBuf, &outBuf) - err := yamlWriter.Print(logger, sharedImageInfo, nil, remoteInfoWithRebasable, nil, nil) - assert.Nil(err) - - assert.ContainsYAML(outBuf.String(), `"image_name": "test-image"`) - assert.ContainsYAML(outBuf.String(), expectedRemoteOutputWithRebasable) - assert.NotContains(outBuf.String(), "test.stack.id.local") - }) }) }) } diff --git a/pkg/client/inspect_image.go b/pkg/client/inspect_image.go index dbb227f34..ee5e5a6a8 100644 --- a/pkg/client/inspect_image.go +++ b/pkg/client/inspect_image.go @@ -124,7 +124,7 @@ func (c *Client) InspectImage(name string, daemon bool) (*ImageInfo, error) { } var rebasable bool - if _, err := dist.GetLabel(img, platform.RebaseableLabel, &rebasable); err != nil { + if _, err := dist.GetLabel(img, platform.RebasableLabel, &rebasable); err != nil { return nil, err } diff --git a/pkg/client/inspect_image_test.go b/pkg/client/inspect_image_test.go index ee786043a..124c25902 100644 --- a/pkg/client/inspect_image_test.go +++ b/pkg/client/inspect_image_test.go @@ -37,15 +37,14 @@ var ignorePlatformAPI = []cmp.Option{ func testInspectImage(t *testing.T, when spec.G, it spec.S) { var ( - subject *Client - mockImageFetcher *testmocks.MockImageFetcher - mockDockerClient *testmocks.MockCommonAPIClient - mockController *gomock.Controller - mockImage *testmocks.MockImage - mockRebasableImage *testmocks.MockImage - mockImageWithExtension *testmocks.MockImage - mockRebasableImageWithExtension *testmocks.MockImage - out bytes.Buffer + subject *Client + mockImageFetcher *testmocks.MockImageFetcher + mockDockerClient *testmocks.MockCommonAPIClient + mockController *gomock.Controller + mockImage *testmocks.MockImage + mockImageNoRebasable *testmocks.MockImage + mockImageWithExtension *testmocks.MockImage + out bytes.Buffer ) it.Before(func() { @@ -60,6 +59,7 @@ func testInspectImage(t *testing.T, when spec.G, it spec.S) { mockImage = testmocks.NewImage("some/image", "", nil) h.AssertNil(t, mockImage.SetWorkingDir("/test-workdir")) h.AssertNil(t, mockImage.SetLabel("io.buildpacks.stack.id", "test.stack.id")) + h.AssertNil(t, mockImage.SetLabel("io.buildpacks.rebasable", "true")) h.AssertNil(t, mockImage.SetLabel( "io.buildpacks.lifecycle.metadata", `{ @@ -116,15 +116,16 @@ func testInspectImage(t *testing.T, when spec.G, it spec.S) { }`, )) - mockRebasableImage = testmocks.NewImage("some/rebasableImage", "", nil) - h.AssertNil(t, mockRebasableImage.SetWorkingDir("/test-workdir")) - h.AssertNil(t, mockRebasableImage.SetLabel("io.buildpacks.stack.id", "test.stack.id")) - h.AssertNil(t, mockRebasableImage.SetLabel( + mockImageNoRebasable = testmocks.NewImage("some/imageNoRebasable", "", nil) + h.AssertNil(t, mockImageNoRebasable.SetWorkingDir("/test-workdir")) + h.AssertNil(t, mockImageNoRebasable.SetLabel("io.buildpacks.stack.id", "test.stack.id")) + h.AssertNil(t, mockImageNoRebasable.SetLabel("io.buildpacks.rebasable", "false")) + h.AssertNil(t, mockImageNoRebasable.SetLabel( "io.buildpacks.lifecycle.metadata", `{ "stack": { "runImage": { - "image": "some-run-image", + "image": "some-run-image-no-rebasable", "mirrors": [ "some-mirror", "other-mirror" @@ -137,7 +138,7 @@ func testInspectImage(t *testing.T, when spec.G, it spec.S) { } }`, )) - h.AssertNil(t, mockRebasableImage.SetLabel( + h.AssertNil(t, mockImage.SetLabel( "io.buildpacks.build.metadata", `{ "bom": [ @@ -174,11 +175,11 @@ func testInspectImage(t *testing.T, when spec.G, it spec.S) { } }`, )) - h.AssertNil(t, mockRebasableImage.SetLabel("io.buildpacks.rebasable", "true")) mockImageWithExtension = testmocks.NewImage("some/imageWithExtension", "", nil) h.AssertNil(t, mockImageWithExtension.SetWorkingDir("/test-workdir")) h.AssertNil(t, mockImageWithExtension.SetLabel("io.buildpacks.stack.id", "test.stack.id")) + h.AssertNil(t, mockImageWithExtension.SetLabel("io.buildpacks.rebasable", "true")) h.AssertNil(t, mockImageWithExtension.SetLabel( "io.buildpacks.lifecycle.metadata", `{ @@ -244,76 +245,6 @@ func testInspectImage(t *testing.T, when spec.G, it spec.S) { } }`, )) - - mockRebasableImageWithExtension = testmocks.NewImage("some/rebasableImageWithExtension", "", nil) - h.AssertNil(t, mockRebasableImageWithExtension.SetWorkingDir("/test-workdir")) - h.AssertNil(t, mockRebasableImageWithExtension.SetLabel("io.buildpacks.stack.id", "test.stack.id")) - h.AssertNil(t, mockRebasableImageWithExtension.SetLabel( - "io.buildpacks.lifecycle.metadata", - `{ - "stack": { - "runImage": { - "image": "some-run-image", - "mirrors": [ - "some-mirror", - "other-mirror" - ] - } - }, - "runImage": { - "topLayer": "some-top-layer", - "reference": "some-run-image-reference" - } -}`, - )) - h.AssertNil(t, mockRebasableImageWithExtension.SetLabel( - "io.buildpacks.build.metadata", - `{ - "bom": [ - { - "name": "some-bom-element" - } - ], - "buildpacks": [ - { - "id": "some-buildpack", - "version": "some-version" - }, - { - "id": "other-buildpack", - "version": "other-version" - } - ], - "extensions": [ - { - "id": "some-extension", - "version": "some-version" - }, - { - "id": "other-extension", - "version": "other-version" - } - ], - "processes": [ - { - "type": "other-process", - "command": "/other/process", - "args": ["opt", "1"], - "direct": true - }, - { - "type": "web", - "command": "/start/web-process", - "args": ["-p", "1234"], - "direct": false - } - ], - "launcher": { - "version": "0.5.0" - } -}`, - )) - h.AssertNil(t, mockRebasableImageWithExtension.SetLabel("io.buildpacks.rebasable", "true")) }) it.After(func() { @@ -327,14 +258,12 @@ func testInspectImage(t *testing.T, when spec.G, it spec.S) { it.Before(func() { if useDaemon { mockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/image", image.FetchOptions{Daemon: true, PullPolicy: image.PullNever}).Return(mockImage, nil).AnyTimes() - mockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/rebasableImage", image.FetchOptions{Daemon: true, PullPolicy: image.PullNever}).Return(mockRebasableImage, nil).AnyTimes() + mockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/imageNoRebasable", image.FetchOptions{Daemon: true, PullPolicy: image.PullNever}).Return(mockImageNoRebasable, nil).AnyTimes() mockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/imageWithExtension", image.FetchOptions{Daemon: true, PullPolicy: image.PullNever}).Return(mockImageWithExtension, nil).AnyTimes() - mockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/rebasableImageWithExtension", image.FetchOptions{Daemon: true, PullPolicy: image.PullNever}).Return(mockRebasableImageWithExtension, nil).AnyTimes() } else { mockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/image", image.FetchOptions{Daemon: false, PullPolicy: image.PullNever}).Return(mockImage, nil).AnyTimes() - mockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/rebasableImage", image.FetchOptions{Daemon: false, PullPolicy: image.PullNever}).Return(mockRebasableImage, nil).AnyTimes() + mockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/imageNoRebasable", image.FetchOptions{Daemon: false, PullPolicy: image.PullNever}).Return(mockImageNoRebasable, nil).AnyTimes() mockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/imageWithExtension", image.FetchOptions{Daemon: false, PullPolicy: image.PullNever}).Return(mockImageWithExtension, nil).AnyTimes() - mockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/rebasableImageWithExtension", image.FetchOptions{Daemon: false, PullPolicy: image.PullNever}).Return(mockRebasableImageWithExtension, nil).AnyTimes() } }) @@ -422,13 +351,19 @@ func testInspectImage(t *testing.T, when spec.G, it spec.S) { }) it("returns the rebasable image", func() { - info, err := subject.InspectImage("some/rebasableImage", useDaemon) + info, err := subject.InspectImage("some/image", useDaemon) h.AssertNil(t, err) h.AssertEq(t, info.Rebasable, true) }) + it("returns the no rebasable image", func() { + info, err := subject.InspectImage("some/imageNoRebasable", useDaemon) + h.AssertNil(t, err) + h.AssertEq(t, info.Rebasable, false) + }) + it("returns the rebasable image with Extension", func() { - infoRebasableWithExtension, err := subject.InspectImage("some/rebasableImageWithExtension", useDaemon) + infoRebasableWithExtension, err := subject.InspectImage("some/imageWithExtension", useDaemon) h.AssertNil(t, err) h.AssertEq(t, infoRebasableWithExtension.Rebasable, true) })