proxy: Add an API to fetch the config upconverted to OCI

While the caller could fetch this today as a blob, it'd be in
either docker or oci schema.  In keeping with the model of having
this proxy only expose OCI, add an API which uses the c/image logic
to do the conversion.

This is necessary for callers to get the diffIDs, and in general
to implement something like an external `skopeo copy`.

Signed-off-by: Colin Walters <walters@verbum.org>
This commit is contained in:
Colin Walters
2021-11-06 09:15:16 -04:00
parent 1e01e38459
commit e7b7be5734

View File

@@ -83,9 +83,11 @@ import (
// protocolVersion is semantic version of the protocol used by this proxy.
// The first version of the protocol has major version 0.2 to signify a
// departure from the original code which used HTTP. The minor version is 1
// instead of 0 to help exercise semver parsers.
const protocolVersion = "0.2.1"
// departure from the original code which used HTTP.
//
// 0.2.1: Initial version
// 0.2.2: Added support for fetching image configuration as OCI
const protocolVersion = "0.2.2"
// maxMsgSize is the current limit on a packet size.
// Note that all non-metadata (i.e. payload data) is sent over a pipe.
@@ -380,6 +382,53 @@ func (h *proxyHandler) GetManifest(args []interface{}) (replyBuf, error) {
return ret, nil
}
// GetConfig returns a copy of the image configuration, converted to OCI format.
func (h *proxyHandler) GetConfig(args []interface{}) (replyBuf, error) {
h.lock.Lock()
defer h.lock.Unlock()
var ret replyBuf
if h.sysctx == nil {
return ret, fmt.Errorf("Must invoke Initialize")
}
if len(args) != 1 {
return ret, fmt.Errorf("invalid request, expecting: [imgid]")
}
imgref, err := h.parseImageFromID(args[0])
if err != nil {
return ret, err
}
ctx := context.TODO()
config, err := imgref.img.OCIConfig(ctx)
if err != nil {
return ret, err
}
serialized, err := json.Marshal(&config.Config)
if err != nil {
return ret, err
}
piper, f, err := h.allocPipe()
if err != nil {
return ret, err
}
go func() {
// Signal completion when we return
defer f.wg.Done()
_, err = io.Copy(f.w, bytes.NewReader(serialized))
if err != nil {
f.err = err
}
}()
ret.fd = piper
ret.pipeid = uint32(f.w.Fd())
return ret, nil
}
// GetBlob fetches a blob, performing digest verification.
func (h *proxyHandler) GetBlob(args []interface{}) (replyBuf, error) {
h.lock.Lock()
@@ -551,6 +600,8 @@ func (h *proxyHandler) processRequest(req request) (rb replyBuf, terminate bool,
rb, err = h.CloseImage(req.Args)
case "GetManifest":
rb, err = h.GetManifest(req.Args)
case "GetConfig":
rb, err = h.GetConfig(req.Args)
case "GetBlob":
rb, err = h.GetBlob(req.Args)
case "FinishPipe":