Stores complete OCI descriptor instead of digest and platform
fields. This includes the size which was getting lost by not
storing the original manifest bytes.
Attempt to support existing cached files, if not output
the filename with the incorrect content.
Signed-off-by: Derek McGowan <derek@mcgstyle.net>
(cherry picked from commit 1fd2d66df8)
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
147 lines
4.3 KiB
Go
147 lines
4.3 KiB
Go
package manifest
|
|
|
|
import (
|
|
"context"
|
|
"io/ioutil"
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/docker/cli/cli/manifest/store"
|
|
"github.com/docker/cli/cli/manifest/types"
|
|
manifesttypes "github.com/docker/cli/cli/manifest/types"
|
|
"github.com/docker/cli/internal/test"
|
|
"github.com/docker/distribution"
|
|
"github.com/docker/distribution/manifest/schema2"
|
|
"github.com/docker/distribution/reference"
|
|
digest "github.com/opencontainers/go-digest"
|
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
|
"github.com/pkg/errors"
|
|
"gotest.tools/assert"
|
|
is "gotest.tools/assert/cmp"
|
|
"gotest.tools/golden"
|
|
)
|
|
|
|
func newTempManifestStore(t *testing.T) (store.Store, func()) {
|
|
tmpdir, err := ioutil.TempDir("", "test-manifest-storage")
|
|
assert.NilError(t, err)
|
|
|
|
return store.NewStore(tmpdir), func() { os.RemoveAll(tmpdir) }
|
|
}
|
|
|
|
func ref(t *testing.T, name string) reference.Named {
|
|
named, err := reference.ParseNamed("example.com/" + name)
|
|
assert.NilError(t, err)
|
|
return named
|
|
}
|
|
|
|
func fullImageManifest(t *testing.T, ref reference.Named) types.ImageManifest {
|
|
man, err := schema2.FromStruct(schema2.Manifest{
|
|
Versioned: schema2.SchemaVersion,
|
|
Config: distribution.Descriptor{
|
|
Digest: "sha256:7328f6f8b41890597575cbaadc884e7386ae0acc53b747401ebce5cf0d624560",
|
|
Size: 1520,
|
|
MediaType: schema2.MediaTypeImageConfig,
|
|
},
|
|
Layers: []distribution.Descriptor{
|
|
{
|
|
MediaType: schema2.MediaTypeLayer,
|
|
Size: 1990402,
|
|
Digest: "sha256:88286f41530e93dffd4b964e1db22ce4939fffa4a4c665dab8591fbab03d4926",
|
|
},
|
|
},
|
|
})
|
|
assert.NilError(t, err)
|
|
|
|
// TODO: include image data for verbose inspect
|
|
mt, raw, err := man.Payload()
|
|
assert.NilError(t, err)
|
|
|
|
desc := ocispec.Descriptor{
|
|
Digest: digest.FromBytes(raw),
|
|
Size: int64(len(raw)),
|
|
MediaType: mt,
|
|
Platform: &ocispec.Platform{
|
|
Architecture: "amd64",
|
|
OS: "linux",
|
|
},
|
|
}
|
|
|
|
return types.NewImageManifest(ref, desc, man)
|
|
}
|
|
|
|
func TestInspectCommandLocalManifestNotFound(t *testing.T) {
|
|
store, cleanup := newTempManifestStore(t)
|
|
defer cleanup()
|
|
|
|
cli := test.NewFakeCli(nil)
|
|
cli.SetManifestStore(store)
|
|
|
|
cmd := newInspectCommand(cli)
|
|
cmd.SetOutput(ioutil.Discard)
|
|
cmd.SetArgs([]string{"example.com/list:v1", "example.com/alpine:3.0"})
|
|
err := cmd.Execute()
|
|
assert.Error(t, err, "No such manifest: example.com/alpine:3.0")
|
|
}
|
|
|
|
func TestInspectCommandNotFound(t *testing.T) {
|
|
store, cleanup := newTempManifestStore(t)
|
|
defer cleanup()
|
|
|
|
cli := test.NewFakeCli(nil)
|
|
cli.SetManifestStore(store)
|
|
cli.SetRegistryClient(&fakeRegistryClient{
|
|
getManifestFunc: func(_ context.Context, _ reference.Named) (manifesttypes.ImageManifest, error) {
|
|
return manifesttypes.ImageManifest{}, errors.New("missing")
|
|
},
|
|
getManifestListFunc: func(ctx context.Context, ref reference.Named) ([]manifesttypes.ImageManifest, error) {
|
|
return nil, errors.Errorf("No such manifest: %s", ref)
|
|
},
|
|
})
|
|
|
|
cmd := newInspectCommand(cli)
|
|
cmd.SetOutput(ioutil.Discard)
|
|
cmd.SetArgs([]string{"example.com/alpine:3.0"})
|
|
err := cmd.Execute()
|
|
assert.Error(t, err, "No such manifest: example.com/alpine:3.0")
|
|
}
|
|
|
|
func TestInspectCommandLocalManifest(t *testing.T) {
|
|
store, cleanup := newTempManifestStore(t)
|
|
defer cleanup()
|
|
|
|
cli := test.NewFakeCli(nil)
|
|
cli.SetManifestStore(store)
|
|
namedRef := ref(t, "alpine:3.0")
|
|
imageManifest := fullImageManifest(t, namedRef)
|
|
err := store.Save(ref(t, "list:v1"), namedRef, imageManifest)
|
|
assert.NilError(t, err)
|
|
|
|
cmd := newInspectCommand(cli)
|
|
cmd.SetArgs([]string{"example.com/list:v1", "example.com/alpine:3.0"})
|
|
assert.NilError(t, cmd.Execute())
|
|
actual := cli.OutBuffer()
|
|
expected := golden.Get(t, "inspect-manifest.golden")
|
|
assert.Check(t, is.Equal(string(expected), actual.String()))
|
|
}
|
|
|
|
func TestInspectcommandRemoteManifest(t *testing.T) {
|
|
store, cleanup := newTempManifestStore(t)
|
|
defer cleanup()
|
|
|
|
cli := test.NewFakeCli(nil)
|
|
cli.SetManifestStore(store)
|
|
cli.SetRegistryClient(&fakeRegistryClient{
|
|
getManifestFunc: func(_ context.Context, ref reference.Named) (manifesttypes.ImageManifest, error) {
|
|
return fullImageManifest(t, ref), nil
|
|
},
|
|
})
|
|
|
|
cmd := newInspectCommand(cli)
|
|
cmd.SetOutput(ioutil.Discard)
|
|
cmd.SetArgs([]string{"example.com/alpine:3.0"})
|
|
assert.NilError(t, cmd.Execute())
|
|
actual := cli.OutBuffer()
|
|
expected := golden.Get(t, "inspect-manifest.golden")
|
|
assert.Check(t, is.Equal(string(expected), actual.String()))
|
|
}
|