Skip to content

Commit f2dc0e2

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). I'd prefer casLayout and refsLayout for the imported packages, but Stephen doesn't want camelCase for package names [1]. [1]: #159 (comment) Signed-off-by: W. Trevor King <[email protected]>
1 parent 2d55583 commit f2dc0e2

12 files changed

+157
-367
lines changed

cmd/oci-image-tool/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)

cmd/oci-image-tool/create_runtime_bundle.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-spec/image"
2424
"github.com/spf13/cobra"
25+
"golang.org/x/net/context"
2526
)
2627

2728
// supported bundle types
2829
var bundleTypes = []string{
29-
typeImageLayout,
3030
typeImage,
3131
}
3232

@@ -82,6 +82,8 @@ func (v *bundleCmd) Run(cmd *cobra.Command, args []string) {
8282
os.Exit(1)
8383
}
8484

85+
ctx := context.Background()
86+
8587
if _, err := os.Stat(args[1]); os.IsNotExist(err) {
8688
v.stderr.Printf("destination path %s does not exist", args[1])
8789
os.Exit(1)
@@ -98,11 +100,8 @@ func (v *bundleCmd) Run(cmd *cobra.Command, args []string) {
98100

99101
var err error
100102
switch v.typ {
101-
case typeImageLayout:
102-
err = image.CreateRuntimeBundleLayout(args[0], args[1], v.ref, v.root)
103-
104103
case typeImage:
105-
err = image.CreateRuntimeBundle(args[0], args[1], v.ref, v.root)
104+
err = image.CreateRuntimeBundle(ctx, args[0], args[1], v.ref, v.root)
106105
}
107106

108107
if err != nil {

cmd/oci-image-tool/man/oci-image-tool-create-runtime-bundle.1.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ oci-image-tool-create-runtime-bundle \- Create an OCI image runtime bundle
2222
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")
2323

2424
**--type**
25-
Type of the file to unpack. If unset, oci-image-tool will try to auto-detect the type. One of "imageLayout,image"
25+
Type of the file to unpack. If unset, oci-image-tool will try to auto-detect the type. One of "image"
2626

2727
# EXAMPLES
2828
```

cmd/oci-image-tool/man/oci-image-tool-unpack.1.md

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

2121
**--type**
22-
Type of the file to unpack. If unset, oci-image-tool will try to auto-detect the type. One of "imageLayout,image"
22+
Type of the file to unpack. If unset, oci-image-tool will try to auto-detect the type. One of "image"
2323

2424
# EXAMPLES
2525
```

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@ oci-image-tool-validate \- Validate one or more image files
1616
Print usage statement
1717

1818
**--ref**
19-
The ref pointing to the manifest to be validated. This must be present in the "refs" subdirectory of the image. Only applicable if type is image or imageLayout. (default "v1.0")
19+
The ref pointing to the manifest to be validated. This must be present in the "refs" subdirectory of the image. Only applicable if type is image. (default "v1.0")
2020

2121
**--type**
22-
Type of the file to validate. If unset, oci-image-tool will try to auto-detect the type. One of "imageLayout,image,manifest,manifestList,config"
22+
Type of the file to validate. If unset, oci-image-tool will try to auto-detect the type. One of "image,manifest,manifestList,config"
2323

2424
# EXAMPLES
2525
```
2626
$ skopeo copy docker://busybox oci:busybox-oci
27-
$ oci-image-tool validate --type imageLayout --ref latest busybox-oci
27+
$ oci-image-tool validate --type image --ref latest busybox-oci
2828
busybox-oci: OK
2929
```
3030

cmd/oci-image-tool/unpack.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-spec/image"
2424
"github.com/spf13/cobra"
25+
"golang.org/x/net/context"
2526
)
2627

2728
// supported unpack types
2829
var unpackTypes = []string{
29-
typeImageLayout,
3030
typeImage,
3131
}
3232

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

4646
cmd := &cobra.Command{
4747
Use: "unpack [src] [dest]",
48-
Short: "Unpack an image or image source layout",
49-
Long: `Unpack the OCI image .tar file or OCI image layout directory present at [src] to the destination directory [dest].`,
48+
Short: "Unpack an image",
49+
Long: `Unpack the OCI image present at [src] to the destination directory [dest].`,
5050
Run: v.Run,
5151
}
5252

@@ -75,6 +75,8 @@ func (v *unpackCmd) Run(cmd *cobra.Command, args []string) {
7575
os.Exit(1)
7676
}
7777

78+
ctx := context.Background()
79+
7880
if v.typ == "" {
7981
typ, err := autodetect(args[0])
8082
if err != nil {
@@ -86,11 +88,8 @@ func (v *unpackCmd) Run(cmd *cobra.Command, args []string) {
8688

8789
var err error
8890
switch v.typ {
89-
case typeImageLayout:
90-
err = image.UnpackLayout(args[0], args[1], v.ref)
91-
9291
case typeImage:
93-
err = image.Unpack(args[0], args[1], v.ref)
92+
err = image.Unpack(ctx, args[0], args[1], v.ref)
9493
}
9594

9695
if err != nil {

cmd/oci-image-tool/validate.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-spec/schema"
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-
typeImageLayout,
3232
typeImage,
3333
typeManifest,
3434
typeManifestList,
@@ -64,7 +64,7 @@ func newValidateCmd(stdout, stderr *log.Logger) *cobra.Command {
6464

6565
cmd.Flags().StringVar(
6666
&v.ref, "ref", "v1.0",
67-
`The ref pointing to the manifest to be validated. This must be present in the "refs" subdirectory of the image. Only applicable if type is image or imageLayout.`,
67+
`The ref pointing to the manifest to be validated. This must be present in the "refs" subdirectory of the image. Only applicable if type is image.`,
6868
)
6969

7070
return cmd
@@ -79,9 +79,11 @@ func (v *validateCmd) Run(cmd *cobra.Command, args []string) {
7979
os.Exit(1)
8080
}
8181

82+
ctx := context.Background()
83+
8284
var exitcode int
8385
for _, arg := range args {
84-
err := v.validatePath(arg)
86+
err := v.validatePath(ctx, arg)
8587

8688
if err == nil {
8789
v.stdout.Printf("%s: OK", arg)
@@ -111,7 +113,7 @@ func (v *validateCmd) Run(cmd *cobra.Command, args []string) {
111113
os.Exit(exitcode)
112114
}
113115

114-
func (v *validateCmd) validatePath(name string) error {
116+
func (v *validateCmd) validatePath(ctx context.Context, name string) error {
115117
var err error
116118
typ := v.typ
117119

@@ -122,10 +124,8 @@ func (v *validateCmd) validatePath(name string) error {
122124
}
123125

124126
switch typ {
125-
case typeImageLayout:
126-
return image.ValidateLayout(name, v.ref)
127127
case typeImage:
128-
return image.Validate(name, v.ref)
128+
return image.Validate(ctx, name, v.ref)
129129
}
130130

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

image/config.go

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

25+
"github.com/opencontainers/image-spec/image/cas"
2826
"github.com/opencontainers/image-spec/schema"
29-
"github.com/opencontainers/runtime-spec/specs-go"
27+
imageSpecs "github.com/opencontainers/image-spec/specs-go"
28+
runtimeSpecs "github.com/opencontainers/runtime-spec/specs-go"
3029
"github.com/pkg/errors"
30+
"golang.org/x/net/context"
3131
)
3232

3333
type cfg struct {
@@ -49,43 +49,35 @@ type config struct {
4949
Config cfg `json:"config"`
5050
}
5151

52-
func findConfig(w walker, d *descriptor) (*config, error) {
53-
var c config
54-
cpath := filepath.Join("blobs", d.algo(), d.hash())
52+
func findConfig(ctx context.Context, engine cas.Engine, descriptor *imageSpecs.Descriptor) (*config, error) {
53+
reader, err := engine.Get(ctx, descriptor.Digest)
54+
if err != nil {
55+
return nil, err
56+
}
5557

56-
switch err := w.walk(func(path string, info os.FileInfo, r io.Reader) error {
57-
if info.IsDir() || filepath.Clean(path) != cpath {
58-
return nil
59-
}
60-
buf, err := ioutil.ReadAll(r)
61-
if err != nil {
62-
return errors.Wrapf(err, "%s: error reading config", path)
63-
}
58+
buf, err := ioutil.ReadAll(reader)
59+
if err != nil {
60+
return nil, errors.Wrapf(err, "%s: error reading manifest", descriptor.Digest)
61+
}
6462

65-
if err := schema.MediaTypeImageConfig.Validate(bytes.NewReader(buf)); err != nil {
66-
return errors.Wrapf(err, "%s: config validation failed", path)
67-
}
63+
if err := schema.MediaTypeImageConfig.Validate(bytes.NewReader(buf)); err != nil {
64+
return nil, errors.Wrapf(err, "%s: config validation failed", descriptor.Digest)
65+
}
6866

69-
if err := json.Unmarshal(buf, &c); err != nil {
70-
return err
71-
}
72-
return errEOW
73-
}); err {
74-
case nil:
75-
return nil, fmt.Errorf("%s: config not found", cpath)
76-
case errEOW:
77-
return &c, nil
78-
default:
67+
var c config
68+
if err := json.Unmarshal(buf, &c); err != nil {
7969
return nil, err
8070
}
71+
72+
return &c, nil
8173
}
8274

83-
func (c *config) runtimeSpec(rootfs string) (*specs.Spec, error) {
75+
func (c *config) runtimeSpec(rootfs string) (*runtimeSpecs.Spec, error) {
8476
if c.OS != "linux" {
8577
return nil, fmt.Errorf("%s: unsupported OS", c.OS)
8678
}
8779

88-
var s specs.Spec
80+
var s runtimeSpecs.Spec
8981
s.Version = "0.5.0"
9082
// we should at least apply the default spec, otherwise this is totally useless
9183
s.Process.Terminal = true
@@ -128,12 +120,12 @@ func (c *config) runtimeSpec(rootfs string) (*specs.Spec, error) {
128120
swap := uint64(c.Config.MemorySwap)
129121
shares := uint64(c.Config.CPUShares)
130122

131-
s.Linux.Resources = &specs.Resources{
132-
CPU: &specs.CPU{
123+
s.Linux.Resources = &runtimeSpecs.Resources{
124+
CPU: &runtimeSpecs.CPU{
133125
Shares: &shares,
134126
},
135127

136-
Memory: &specs.Memory{
128+
Memory: &runtimeSpecs.Memory{
137129
Limit: &mem,
138130
Reservation: &mem,
139131
Swap: &swap,
@@ -143,7 +135,7 @@ func (c *config) runtimeSpec(rootfs string) (*specs.Spec, error) {
143135
for vol := range c.Config.Volumes {
144136
s.Mounts = append(
145137
s.Mounts,
146-
specs.Mount{
138+
runtimeSpecs.Mount{
147139
Destination: vol,
148140
Type: "bind",
149141
Options: []string{"rbind"},

0 commit comments

Comments
 (0)