diff --git a/README.md b/README.md index 6e76bfd5..63efd470 100644 --- a/README.md +++ b/README.md @@ -117,9 +117,7 @@ TODO - update README with `layers` command - list all images on registry? - registry v2 search? -- make skopeo docker registry v2 only - download layers in parallel and support docker load tar(s) -- get rid of docker/docker code (?) - show repo tags via flag or when reference isn't tagged or digested - add tests (integration with deployed registries in container - Docker-like) - support rkt/appc image spec diff --git a/cmd/skopeo/inspect.go b/cmd/skopeo/inspect.go index 6cf426f6..203ed481 100644 --- a/cmd/skopeo/inspect.go +++ b/cmd/skopeo/inspect.go @@ -23,12 +23,11 @@ var inspectCmd = cli.Command{ }, }, Action: func(c *cli.Context) { + img, err := skopeo.ParseImage(c.Args().First()) + if err != nil { + logrus.Fatal(err) + } if c.Bool("raw") { - img, err := skopeo.ParseImage(c.Args().First()) - if err != nil { - logrus.Fatal(err) - } - // TODO(runcom): this is not falling back to v1 // TODO(runcom): hardcoded schema 2 version 1 b, err := img.RawManifest("2-1") if err != nil { @@ -37,12 +36,11 @@ var inspectCmd = cli.Command{ fmt.Println(string(b)) return } - // get the Image interface before inspecting...utils.go parseImage - imgInspect, err := inspect(c) + imgInspect, err := img.Manifest() if err != nil { logrus.Fatal(err) } - out, err := json.Marshal(imgInspect) + out, err := json.MarshalIndent(imgInspect, "", " ") if err != nil { logrus.Fatal(err) } diff --git a/docker.go b/docker.go index 297afaf3..7ee829dd 100644 --- a/docker.go +++ b/docker.go @@ -53,11 +53,36 @@ func (i *dockerImage) RawManifest(version string) ([]byte, error) { return i.rawManifest, nil } -func (i *dockerImage) Manifest(version string) (types.ImageManifest, error) { - // TODO(runcom): port docker/docker implementation under docker/ to just - // use this!!! and do not rely on docker upstream code - will need to support - // v1 fall back also... - return nil, nil +func (i *dockerImage) Manifest() (types.ImageManifest, error) { + // TODO(runcom): unused version param for now, default to docker v2-1 + m, err := i.getSchema1Manifest() + if err != nil { + return nil, err + } + ms1, ok := m.(*manifestSchema1) + if !ok { + return nil, fmt.Errorf("error retrivieng manifest schema1") + } + + // TODO(runcom): get all tags, last argument, and digest + return makeImageManifest(ms1, "", nil), nil +} + +func makeImageManifest(m *manifestSchema1, dgst string, tagList []string) types.ImageManifest { + return &types.DockerImageManifest{ + Tag: m.Tag, + Digest: dgst, + RepoTags: tagList, + Comment: "", + Created: "", + ContainerConfig: nil, + DockerVersion: "", + Author: "", + Config: nil, + Architecture: "", + Os: "", + Layers: nil, + } } func (i *dockerImage) DockerTar() ([]byte, error) { @@ -273,6 +298,13 @@ func (i *dockerImage) getSchema1Manifest() (manifest, error) { if err := fixManifestLayers(mschema1); err != nil { return nil, err } + // TODO(runcom): verify manifest schema 1, 2 etc + //if len(m.FSLayers) != len(m.History) { + //return nil, fmt.Errorf("length of history not equal to number of layers for %q", ref.String()) + //} + //if len(m.FSLayers) == 0 { + //return nil, fmt.Errorf("no FSLayers in manifest for %q", ref.String()) + //} return mschema1, nil } diff --git a/types/types.go b/types/types.go index 0e9000ee..ac56ea0e 100644 --- a/types/types.go +++ b/types/types.go @@ -22,7 +22,7 @@ type Repository interface { type Image interface { // ref to repository? Layers(layers ...string) error // configure download directory? Call it DownloadLayers? - Manifest(version string) (ImageManifest, error) + Manifest() (ImageManifest, error) RawManifest(version string) ([]byte, error) DockerTar() ([]byte, error) // ??? also, configure output directory } @@ -48,5 +48,8 @@ type DockerImageManifest struct { } func (m *DockerImageManifest) Labels() map[string]string { + if m.Config == nil { + return nil + } return m.Config.Labels }