mirror of https://github.com/docker/cli.git
Merge pull request #476 from dnephin/small-cleanup-to-two-formatters
Reduce complexity of image formatter
This commit is contained in:
commit
6780c29d6e
|
@ -1,9 +1,10 @@
|
||||||
package formatter
|
package formatter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func compareMultipleValues(t *testing.T, value, expected string) {
|
func compareMultipleValues(t *testing.T, value, expected string) {
|
||||||
|
@ -22,7 +23,5 @@ func compareMultipleValues(t *testing.T, value, expected string) {
|
||||||
keyval := strings.Split(expected, "=")
|
keyval := strings.Split(expected, "=")
|
||||||
expMap[keyval[0]] = keyval[1]
|
expMap[keyval[0]] = keyval[1]
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(expMap, entriesMap) {
|
assert.Equal(t, expMap, entriesMap)
|
||||||
t.Fatalf("Expected entries: %v, got: %v", expected, value)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,9 +86,9 @@ func needDigest(ctx ImageContext) bool {
|
||||||
|
|
||||||
func imageFormat(ctx ImageContext, images []types.ImageSummary, format func(subContext subContext) error) error {
|
func imageFormat(ctx ImageContext, images []types.ImageSummary, format func(subContext subContext) error) error {
|
||||||
for _, image := range images {
|
for _, image := range images {
|
||||||
images := []*imageContext{}
|
formatted := []*imageContext{}
|
||||||
if isDangling(image) {
|
if isDangling(image) {
|
||||||
images = append(images, &imageContext{
|
formatted = append(formatted, &imageContext{
|
||||||
trunc: ctx.Trunc,
|
trunc: ctx.Trunc,
|
||||||
i: image,
|
i: image,
|
||||||
repo: "<none>",
|
repo: "<none>",
|
||||||
|
@ -96,90 +96,9 @@ func imageFormat(ctx ImageContext, images []types.ImageSummary, format func(subC
|
||||||
digest: "<none>",
|
digest: "<none>",
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
repoTags := map[string][]string{}
|
formatted = imageFormatTaggedAndDigest(ctx, image)
|
||||||
repoDigests := map[string][]string{}
|
|
||||||
|
|
||||||
for _, refString := range image.RepoTags {
|
|
||||||
ref, err := reference.ParseNormalizedNamed(refString)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if nt, ok := ref.(reference.NamedTagged); ok {
|
|
||||||
familiarRef := reference.FamiliarName(ref)
|
|
||||||
repoTags[familiarRef] = append(repoTags[familiarRef], nt.Tag())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, refString := range image.RepoDigests {
|
|
||||||
ref, err := reference.ParseNormalizedNamed(refString)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if c, ok := ref.(reference.Canonical); ok {
|
|
||||||
familiarRef := reference.FamiliarName(ref)
|
|
||||||
repoDigests[familiarRef] = append(repoDigests[familiarRef], c.Digest().String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for repo, tags := range repoTags {
|
|
||||||
digests := repoDigests[repo]
|
|
||||||
|
|
||||||
// Do not display digests as their own row
|
|
||||||
delete(repoDigests, repo)
|
|
||||||
|
|
||||||
if !needDigest(ctx) {
|
|
||||||
// Ignore digest references, just show tag once
|
|
||||||
digests = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tag := range tags {
|
|
||||||
if len(digests) == 0 {
|
|
||||||
images = append(images, &imageContext{
|
|
||||||
trunc: ctx.Trunc,
|
|
||||||
i: image,
|
|
||||||
repo: repo,
|
|
||||||
tag: tag,
|
|
||||||
digest: "<none>",
|
|
||||||
})
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Display the digests for each tag
|
|
||||||
for _, dgst := range digests {
|
|
||||||
images = append(images, &imageContext{
|
|
||||||
trunc: ctx.Trunc,
|
|
||||||
i: image,
|
|
||||||
repo: repo,
|
|
||||||
tag: tag,
|
|
||||||
digest: dgst,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show rows for remaining digest only references
|
|
||||||
for repo, digests := range repoDigests {
|
|
||||||
// If digests are displayed, show row per digest
|
|
||||||
if ctx.Digest {
|
|
||||||
for _, dgst := range digests {
|
|
||||||
images = append(images, &imageContext{
|
|
||||||
trunc: ctx.Trunc,
|
|
||||||
i: image,
|
|
||||||
repo: repo,
|
|
||||||
tag: "<none>",
|
|
||||||
digest: dgst,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
images = append(images, &imageContext{
|
|
||||||
trunc: ctx.Trunc,
|
|
||||||
i: image,
|
|
||||||
repo: repo,
|
|
||||||
tag: "<none>",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for _, imageCtx := range images {
|
for _, imageCtx := range formatted {
|
||||||
if err := format(imageCtx); err != nil {
|
if err := format(imageCtx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -188,6 +107,82 @@ func imageFormat(ctx ImageContext, images []types.ImageSummary, format func(subC
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func imageFormatTaggedAndDigest(ctx ImageContext, image types.ImageSummary) []*imageContext {
|
||||||
|
repoTags := map[string][]string{}
|
||||||
|
repoDigests := map[string][]string{}
|
||||||
|
images := []*imageContext{}
|
||||||
|
|
||||||
|
for _, refString := range image.RepoTags {
|
||||||
|
ref, err := reference.ParseNormalizedNamed(refString)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if nt, ok := ref.(reference.NamedTagged); ok {
|
||||||
|
familiarRef := reference.FamiliarName(ref)
|
||||||
|
repoTags[familiarRef] = append(repoTags[familiarRef], nt.Tag())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, refString := range image.RepoDigests {
|
||||||
|
ref, err := reference.ParseNormalizedNamed(refString)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if c, ok := ref.(reference.Canonical); ok {
|
||||||
|
familiarRef := reference.FamiliarName(ref)
|
||||||
|
repoDigests[familiarRef] = append(repoDigests[familiarRef], c.Digest().String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addImage := func(repo, tag, digest string) {
|
||||||
|
image := &imageContext{
|
||||||
|
trunc: ctx.Trunc,
|
||||||
|
i: image,
|
||||||
|
repo: repo,
|
||||||
|
tag: tag,
|
||||||
|
digest: digest,
|
||||||
|
}
|
||||||
|
images = append(images, image)
|
||||||
|
}
|
||||||
|
|
||||||
|
for repo, tags := range repoTags {
|
||||||
|
digests := repoDigests[repo]
|
||||||
|
|
||||||
|
// Do not display digests as their own row
|
||||||
|
delete(repoDigests, repo)
|
||||||
|
|
||||||
|
if !needDigest(ctx) {
|
||||||
|
// Ignore digest references, just show tag once
|
||||||
|
digests = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tag := range tags {
|
||||||
|
if len(digests) == 0 {
|
||||||
|
addImage(repo, tag, "<none>")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Display the digests for each tag
|
||||||
|
for _, dgst := range digests {
|
||||||
|
addImage(repo, tag, dgst)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show rows for remaining digest only references
|
||||||
|
for repo, digests := range repoDigests {
|
||||||
|
// If digests are displayed, show row per digest
|
||||||
|
if ctx.Digest {
|
||||||
|
for _, dgst := range digests {
|
||||||
|
addImage(repo, "<none>", dgst)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
addImage(repo, "<none>", "")
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return images
|
||||||
|
}
|
||||||
|
|
||||||
type imageContext struct {
|
type imageContext struct {
|
||||||
HeaderContext
|
HeaderContext
|
||||||
trunc bool
|
trunc bool
|
||||||
|
|
|
@ -55,6 +55,26 @@ func TestImageContext(t *testing.T) {
|
||||||
i: types.ImageSummary{},
|
i: types.ImageSummary{},
|
||||||
digest: "sha256:d149ab53f8718e987c3a3024bb8aa0e2caadf6c0328f1d9d850b2a2a67f2819a",
|
digest: "sha256:d149ab53f8718e987c3a3024bb8aa0e2caadf6c0328f1d9d850b2a2a67f2819a",
|
||||||
}, "sha256:d149ab53f8718e987c3a3024bb8aa0e2caadf6c0328f1d9d850b2a2a67f2819a", ctx.Digest},
|
}, "sha256:d149ab53f8718e987c3a3024bb8aa0e2caadf6c0328f1d9d850b2a2a67f2819a", ctx.Digest},
|
||||||
|
{
|
||||||
|
imageContext{
|
||||||
|
i: types.ImageSummary{Containers: 10},
|
||||||
|
}, "10", ctx.Containers,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
imageContext{
|
||||||
|
i: types.ImageSummary{VirtualSize: 10000},
|
||||||
|
}, "10kB", ctx.VirtualSize,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
imageContext{
|
||||||
|
i: types.ImageSummary{SharedSize: 10000},
|
||||||
|
}, "10kB", ctx.SharedSize,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
imageContext{
|
||||||
|
i: types.ImageSummary{SharedSize: 5000, VirtualSize: 20000},
|
||||||
|
}, "15kB", ctx.UniqueSize,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
|
@ -62,8 +82,8 @@ func TestImageContext(t *testing.T) {
|
||||||
v := c.call()
|
v := c.call()
|
||||||
if strings.Contains(v, ",") {
|
if strings.Contains(v, ",") {
|
||||||
compareMultipleValues(t, v, c.expValue)
|
compareMultipleValues(t, v, c.expValue)
|
||||||
} else if v != c.expValue {
|
} else {
|
||||||
t.Fatalf("Expected %s, was %s\n", c.expValue, v)
|
assert.Equal(t, c.expValue, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,11 +93,7 @@ func Load(configDetails types.ConfigDetails) (*types.Config, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.Configs, err = LoadConfigObjs(config["configs"], configDetails.WorkingDir)
|
cfg.Configs, err = LoadConfigObjs(config["configs"], configDetails.WorkingDir)
|
||||||
if err != nil {
|
return &cfg, err
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &cfg, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func interpolateConfig(configDict map[string]interface{}, lookupEnv template.Mapping) (map[string]map[string]interface{}, error) {
|
func interpolateConfig(configDict map[string]interface{}, lookupEnv template.Mapping) (map[string]map[string]interface{}, error) {
|
||||||
|
|
Loading…
Reference in New Issue