Skip to content

Commit

Permalink
proxy: Add optional flags to OpenImage
Browse files Browse the repository at this point in the history
See #1829 (comment)

This is prep for adding another option like `require-signatures`.

Signed-off-by: Colin Walters <[email protected]>
  • Loading branch information
cgwalters committed Jan 10, 2023
1 parent 4517ea0 commit 1c93bd2
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 7 deletions.
55 changes: 49 additions & 6 deletions cmd/skopeo/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ import (
// 0.2.3: Added GetFullConfig
// 0.2.4: Added OpenImageOptional
// 0.2.5: Added LayerInfoJSON
const protocolVersion = "0.2.5"
// 0.2.6: OpenImage now accepts a second argument with an array of options
const protocolVersion = "0.2.6"

// maxMsgSize is the current limit on a packet size.
// Note that all non-metadata (i.e. payload data) is sent over a pipe.
Expand Down Expand Up @@ -214,8 +215,18 @@ func (h *proxyHandler) Initialize(args []interface{}) (replyBuf, error) {

// OpenImage accepts a string image reference i.e. TRANSPORT:REF - like `skopeo copy`.
// The return value is an opaque integer handle.
//
// A second argument may be present; if so, it is an array of string-valued flags.
//
// - optional: Do not error if the image is not present; instead return a zero imageid. Since: 0.2.6
func (h *proxyHandler) OpenImage(args []interface{}) (replyBuf, error) {
return h.openImageImpl(args, false)
opts := openOptions{}
if len(args) > 1 {
if err := opts.parse(args[1]); err != nil {
return replyBuf{}, err
}
}
return h.openImageImpl(args, opts)
}

// isDockerManifestUnknownError is a copy of code from containers/image,
Expand All @@ -237,15 +248,45 @@ func isNotFoundImageError(err error) bool {
errors.Is(err, ocilayout.ImageNotFoundError{})
}

func (h *proxyHandler) openImageImpl(args []interface{}, allowNotFound bool) (replyBuf, error) {
type openOptions struct {
optional bool
}

func (o *openOptions) parse(argsval interface{}) error {
args, ok := argsval.([]interface{})
if !ok {
return fmt.Errorf("expecting array for options, not %T", argsval)
}
for _, argv := range args {
arg, ok := argv.(string)
if !ok {
return fmt.Errorf("expecting string option, not %T", arg)
}
switch arg {
case "optional":
o.optional = true
default:
return fmt.Errorf("unknown option %s", arg)
}
}

return nil
}

func (h *proxyHandler) openImageImpl(args []interface{}, opts openOptions) (replyBuf, error) {
h.lock.Lock()
defer h.lock.Unlock()
var ret replyBuf

if h.sysctx == nil {
return ret, fmt.Errorf("client error: must invoke Initialize")
}
if len(args) != 1 {
switch len(args) {
case 1:
// This is is the default
case 2:
// The second argument, if present should have been parsed by the caller
default:
return ret, fmt.Errorf("invalid request, expecting one argument")
}
imageref, ok := args[0].(string)
Expand All @@ -259,7 +300,7 @@ func (h *proxyHandler) openImageImpl(args []interface{}, allowNotFound bool) (re
}
imgsrc, err := imgRef.NewImageSource(context.Background(), h.sysctx)
if err != nil {
if allowNotFound && isNotFoundImageError(err) {
if opts.optional && isNotFoundImageError(err) {
ret.value = sentinelImageID
return ret, nil
}
Expand All @@ -283,7 +324,9 @@ func (h *proxyHandler) openImageImpl(args []interface{}, allowNotFound bool) (re
// The return value is an opaque integer handle. If the image does not exist, zero
// is returned.
func (h *proxyHandler) OpenImageOptional(args []interface{}) (replyBuf, error) {
return h.openImageImpl(args, true)
return h.openImageImpl(args, openOptions{
optional: true,
})
}

func (h *proxyHandler) CloseImage(args []interface{}) (replyBuf, error) {
Expand Down
2 changes: 1 addition & 1 deletion hack/make/test-integration
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ bundle_test_integration() {

# subshell so that we can export PATH without breaking other things
(
make PREFIX=/usr install
#make PREFIX=/usr install
bundle_test_integration
) 2>&1
17 changes: 17 additions & 0 deletions integration/proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,23 @@ func runTestOpenImageOptionalNotFound(p *proxy, img string) error {
if imgid != 0 {
return fmt.Errorf("Unexpected optional image id %v", imgid)
}

// Also verify the optional options
opts := []string{"optional"}
v, err = p.callNoFd("OpenImage", []interface{}{img, opts})
if err != nil {
return fmt.Errorf("calling OpenImage with flag optional: %w ", err)
}

imgidv, ok = v.(float64)
if !ok {
return fmt.Errorf("OpenImage return value is %T", v)
}
imgid = uint32(imgidv)
if imgid != 0 {
return fmt.Errorf("Unexpected optional image id %v", imgid)
}

return nil
}

Expand Down

0 comments on commit 1c93bd2

Please sign in to comment.