Skip to content

Commit ea85928

Browse files
committed
image: Refactor to use cas/ref engines instead of walkers
The validation/unpacking code doesn't really care what the reference and CAS implemenations are. And the new generic interfaces in image/refs and image/cas will scale better as we add new backends than the walker interface. The old tar/directory distinction between image and imageLayout is gone. The new CAS/refs engines don't support directory backends yet (I plan on adding them once the engine framework lands), but the new framework will handle tar/directory/... detection inside layout.NewEngine (and possibly inside a new (cas|refs).NewEngine when we grow engine types that aren't based on image-layout). Also replace the old methods like: func (d *descriptor) validateContent(r io.Reader) error with functions like: validateContent(ctx context.Context, descriptor *specs.Descriptor, r io.Reader) error to avoid local types that duplicate the image-spec types. This saves an extra instantiation for folks who want to validate (or whatever) a specs.Descriptor they have obtained elsewhere. I'd prefer casLayout and refsLayout for the imported packages, but Stephen doesn't want camelCase for package names [1]. [1]: opencontainers/image-spec#159 (comment) Signed-off-by: W. Trevor King <[email protected]>
1 parent 91d6bb3 commit ea85928

File tree

13 files changed

+263
-454
lines changed

13 files changed

+263
-454
lines changed

cmd/oci-create-runtime-bundle/main.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ import (
2222

2323
"github.com/opencontainers/image-tools/image"
2424
"github.com/spf13/cobra"
25+
"golang.org/x/net/context"
2526
)
2627

2728
// supported bundle types
2829
var bundleTypes = []string{
29-
image.TypeImageLayout,
3030
image.TypeImage,
3131
}
3232

@@ -93,6 +93,8 @@ func (v *bundleCmd) Run(cmd *cobra.Command, args []string) {
9393
os.Exit(1)
9494
}
9595

96+
ctx := context.Background()
97+
9698
if _, err := os.Stat(args[1]); os.IsNotExist(err) {
9799
v.stderr.Printf("destination path %s does not exist", args[1])
98100
os.Exit(1)
@@ -109,11 +111,8 @@ func (v *bundleCmd) Run(cmd *cobra.Command, args []string) {
109111

110112
var err error
111113
switch v.typ {
112-
case image.TypeImageLayout:
113-
err = image.CreateRuntimeBundleLayout(args[0], args[1], v.ref, v.root)
114-
115114
case image.TypeImage:
116-
err = image.CreateRuntimeBundle(args[0], args[1], v.ref, v.root)
115+
err = image.CreateRuntimeBundle(ctx, args[0], args[1], v.ref, v.root)
117116
}
118117

119118
if err != nil {

cmd/oci-create-runtime-bundle/oci-create-runtime-bundle.1.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ runtime-spec-compatible `dest/config.json`.
2424
A directory representing the root filesystem of the container in the OCI runtime bundle. It is strongly recommended to keep the default value. (default "rootfs")
2525

2626
**--type**
27-
Type of the file to unpack. If unset, oci-create-runtime-bundle will try to auto-detect the type. One of "imageLayout,image"
27+
Type of the file to unpack. If unset, oci-create-runtime-bundle will try to auto-detect the type. One of "image"
2828

2929
# EXAMPLES
3030
```

cmd/oci-image-validate/main.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ import (
2424
"github.com/opencontainers/image-tools/image"
2525
"github.com/pkg/errors"
2626
"github.com/spf13/cobra"
27+
"golang.org/x/net/context"
2728
)
2829

2930
// supported validation types
3031
var validateTypes = []string{
31-
image.TypeImageLayout,
3232
image.TypeImage,
3333
image.TypeManifest,
3434
image.TypeManifestList,
@@ -75,7 +75,7 @@ func newValidateCmd(stdout, stderr *log.Logger) *cobra.Command {
7575

7676
cmd.Flags().StringSliceVar(
7777
&v.refs, "ref", nil,
78-
`A set of refs pointing to the manifests to be validated. Each reference must be present in the "refs" subdirectory of the image. Only applicable if type is image or imageLayout.`,
78+
`A set of refs pointing to the manifests to be validated. Each reference must be present in the "refs" subdirectory of the image. Only applicable if type is image.`,
7979
)
8080

8181
return cmd
@@ -90,9 +90,11 @@ func (v *validateCmd) Run(cmd *cobra.Command, args []string) {
9090
os.Exit(1)
9191
}
9292

93+
ctx := context.Background()
94+
9395
var exitcode int
9496
for _, arg := range args {
95-
err := v.validatePath(arg)
97+
err := v.validatePath(ctx, arg)
9698

9799
if err == nil {
98100
v.stdout.Printf("%s: OK", arg)
@@ -122,7 +124,7 @@ func (v *validateCmd) Run(cmd *cobra.Command, args []string) {
122124
os.Exit(exitcode)
123125
}
124126

125-
func (v *validateCmd) validatePath(name string) error {
127+
func (v *validateCmd) validatePath(ctx context.Context, name string) error {
126128
var (
127129
err error
128130
typ = v.typ
@@ -135,10 +137,8 @@ func (v *validateCmd) validatePath(name string) error {
135137
}
136138

137139
switch typ {
138-
case image.TypeImageLayout:
139-
return image.ValidateLayout(name, v.refs, v.stdout)
140140
case image.TypeImage:
141-
return image.Validate(name, v.refs, v.stdout)
141+
return image.Validate(ctx, name, v.refs, v.stdout)
142142
}
143143

144144
f, err := os.Open(name)

cmd/oci-image-validate/oci-image-validate.1.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@ oci-image-validate \- Validate one or more image files
2020
Can be specified multiple times to validate multiple references.
2121
`NAME` must be present in the `refs` subdirectory of the image.
2222
Defaults to `v1.0`.
23-
Only applicable if type is image or imageLayout.
23+
Only applicable if type is image.
2424

2525
**--type**
26-
Type of the file to validate. If unset, oci-image-validate will try to auto-detect the type. One of "imageLayout,image,manifest,manifestList,config"
26+
Type of the file to validate. If unset, oci-image-validate will try to auto-detect the type. One of "image,manifest,manifestList,config"
2727

2828
# EXAMPLES
2929
```
3030
$ skopeo copy docker://busybox oci:busybox-oci
31-
$ oci-image-validate --type imageLayout --ref latest busybox-oci
31+
$ oci-image-validate --type image --ref latest busybox-oci
3232
busybox-oci: OK
3333
```
3434

cmd/oci-unpack/main.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ import (
2222

2323
"github.com/opencontainers/image-tools/image"
2424
"github.com/spf13/cobra"
25+
"golang.org/x/net/context"
2526
)
2627

2728
// supported unpack types
2829
var unpackTypes = []string{
29-
image.TypeImageLayout,
3030
image.TypeImage,
3131
}
3232

@@ -56,8 +56,8 @@ func newUnpackCmd(stdout, stderr *log.Logger) *cobra.Command {
5656

5757
cmd := &cobra.Command{
5858
Use: "unpack [src] [dest]",
59-
Short: "Unpack an image or image source layout",
60-
Long: `Unpack the OCI image .tar file or OCI image layout directory present at [src] to the destination directory [dest].`,
59+
Short: "Unpack an image",
60+
Long: `Unpack the OCI image present at [src] to the destination directory [dest].`,
6161
Run: v.Run,
6262
}
6363

@@ -86,6 +86,8 @@ func (v *unpackCmd) Run(cmd *cobra.Command, args []string) {
8686
os.Exit(1)
8787
}
8888

89+
ctx := context.Background()
90+
8991
if v.typ == "" {
9092
typ, err := image.Autodetect(args[0])
9193
if err != nil {
@@ -97,11 +99,8 @@ func (v *unpackCmd) Run(cmd *cobra.Command, args []string) {
9799

98100
var err error
99101
switch v.typ {
100-
case image.TypeImageLayout:
101-
err = image.UnpackLayout(args[0], args[1], v.ref)
102-
103102
case image.TypeImage:
104-
err = image.Unpack(args[0], args[1], v.ref)
103+
err = image.Unpack(ctx, args[0], args[1], v.ref)
105104
}
106105

107106
if err != nil {

cmd/oci-unpack/oci-unpack.1.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ oci-unpack \- Unpack an image or image source layout
1818
The ref pointing to the manifest to be unpacked. This must be present in the "refs" subdirectory of the image. (default "v1.0")
1919

2020
**--type**
21-
Type of the file to unpack. If unset, oci-unpack will try to auto-detect the type. One of "imageLayout,image"
21+
Type of the file to unpack. If unset, oci-unpack will try to auto-detect the type. One of "image"
2222

2323
# EXAMPLES
2424
```

image/autodetect.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import (
2727

2828
// supported autodetection types
2929
const (
30-
TypeImageLayout = "imageLayout"
3130
TypeImage = "image"
3231
TypeManifest = "manifest"
3332
TypeManifestList = "manifestList"
@@ -43,7 +42,7 @@ func Autodetect(path string) (string, error) {
4342
}
4443

4544
if fi.IsDir() {
46-
return TypeImageLayout, nil
45+
return TypeImage, nil
4746
}
4847

4948
f, err := os.Open(path)

image/config.go

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,58 +18,57 @@ import (
1818
"bytes"
1919
"encoding/json"
2020
"fmt"
21-
"io"
2221
"io/ioutil"
23-
"os"
24-
"path/filepath"
2522
"strconv"
2623
"strings"
2724

2825
"github.com/opencontainers/image-spec/schema"
26+
imagespecs "github.com/opencontainers/image-spec/specs-go"
2927
"github.com/opencontainers/image-spec/specs-go/v1"
30-
"github.com/opencontainers/runtime-spec/specs-go"
28+
"github.com/opencontainers/image-tools/image/cas"
29+
runtimespecs "github.com/opencontainers/runtime-spec/specs-go"
3130
"github.com/pkg/errors"
31+
"golang.org/x/net/context"
3232
)
3333

34-
type config v1.Image
34+
func findConfig(ctx context.Context, engine cas.Engine, descriptor *imagespecs.Descriptor) (config *v1.Image, err error) {
35+
err = validateMediaType(descriptor.MediaType, []string{v1.MediaTypeImageConfig})
36+
if err != nil {
37+
return nil, errors.Wrap(err, "invalid config media type")
38+
}
3539

36-
func findConfig(w walker, d *descriptor) (*config, error) {
37-
var c config
38-
cpath := filepath.Join("blobs", d.algo(), d.hash())
40+
if err := validateDescriptor(ctx, engine, descriptor); err != nil {
41+
return nil, errors.Wrap(err, "invalid config descriptor")
42+
}
3943

40-
switch err := w.walk(func(path string, info os.FileInfo, r io.Reader) error {
41-
if info.IsDir() || filepath.Clean(path) != cpath {
42-
return nil
43-
}
44-
buf, err := ioutil.ReadAll(r)
45-
if err != nil {
46-
return errors.Wrapf(err, "%s: error reading config", path)
47-
}
44+
reader, err := engine.Get(ctx, descriptor.Digest)
45+
if err != nil {
46+
return nil, errors.Wrapf(err, "failed to fetch %s", descriptor.Digest)
47+
}
4848

49-
if err := schema.MediaTypeImageConfig.Validate(bytes.NewReader(buf)); err != nil {
50-
return errors.Wrapf(err, "%s: config validation failed", path)
51-
}
49+
buf, err := ioutil.ReadAll(reader)
50+
if err != nil {
51+
return nil, errors.Wrapf(err, "%s: error reading manifest", descriptor.Digest)
52+
}
5253

53-
if err := json.Unmarshal(buf, &c); err != nil {
54-
return err
55-
}
56-
return errEOW
57-
}); err {
58-
case nil:
59-
return nil, fmt.Errorf("%s: config not found", cpath)
60-
case errEOW:
61-
return &c, nil
62-
default:
54+
if err := schema.MediaTypeImageConfig.Validate(bytes.NewReader(buf)); err != nil {
55+
return nil, errors.Wrapf(err, "%s: config validation failed", descriptor.Digest)
56+
}
57+
58+
var c v1.Image
59+
if err := json.Unmarshal(buf, &c); err != nil {
6360
return nil, err
6461
}
62+
63+
return &c, nil
6564
}
6665

67-
func (c *config) runtimeSpec(rootfs string) (*specs.Spec, error) {
66+
func runtimeSpec(c *v1.Image, rootfs string) (*runtimespecs.Spec, error) {
6867
if c.OS != "linux" {
6968
return nil, fmt.Errorf("%s: unsupported OS", c.OS)
7069
}
7170

72-
var s specs.Spec
71+
var s runtimespecs.Spec
7372
s.Version = "0.5.0"
7473
// we should at least apply the default spec, otherwise this is totally useless
7574
s.Process.Terminal = true
@@ -112,12 +111,12 @@ func (c *config) runtimeSpec(rootfs string) (*specs.Spec, error) {
112111
swap := uint64(c.Config.MemorySwap)
113112
shares := uint64(c.Config.CPUShares)
114113

115-
s.Linux.Resources = &specs.Resources{
116-
CPU: &specs.CPU{
114+
s.Linux.Resources = &runtimespecs.Resources{
115+
CPU: &runtimespecs.CPU{
117116
Shares: &shares,
118117
},
119118

120-
Memory: &specs.Memory{
119+
Memory: &runtimespecs.Memory{
121120
Limit: &mem,
122121
Reservation: &mem,
123122
Swap: &swap,
@@ -127,7 +126,7 @@ func (c *config) runtimeSpec(rootfs string) (*specs.Spec, error) {
127126
for vol := range c.Config.Volumes {
128127
s.Mounts = append(
129128
s.Mounts,
130-
specs.Mount{
129+
runtimespecs.Mount{
131130
Destination: vol,
132131
Type: "bind",
133132
Options: []string{"rbind"},

0 commit comments

Comments
 (0)