mirror of
https://github.com/containers/skopeo.git
synced 2025-06-28 15:47:34 +00:00
Merge pull request #187 from mtrmac/api-changes
Update for mtrmac/image:api-changes
This commit is contained in:
commit
4421e7ea2f
@ -39,6 +39,8 @@ var inspectCmd = cli.Command{
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer img.Close()
|
||||
|
||||
rawManifest, _, err := img.Manifest()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -26,6 +26,8 @@ var layersCmd = cli.Command{
|
||||
return err
|
||||
}
|
||||
src := image.FromSource(rawSource)
|
||||
defer src.Close()
|
||||
|
||||
blobDigests := c.Args().Tail()
|
||||
if len(blobDigests) == 0 {
|
||||
b, err := src.BlobDigests()
|
||||
@ -46,6 +48,23 @@ var layersCmd = cli.Command{
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer dest.Close()
|
||||
|
||||
for _, digest := range blobDigests {
|
||||
if !strings.HasPrefix(digest, "sha256:") {
|
||||
digest = "sha256:" + digest
|
||||
}
|
||||
r, blobSize, err := rawSource.GetBlob(digest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := dest.PutBlob(digest, blobSize, r); err != nil {
|
||||
r.Close()
|
||||
return err
|
||||
}
|
||||
r.Close()
|
||||
}
|
||||
|
||||
manifest, _, err := src.Manifest()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -53,20 +72,11 @@ var layersCmd = cli.Command{
|
||||
if err := dest.PutManifest(manifest); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, digest := range blobDigests {
|
||||
if !strings.HasPrefix(digest, "sha256:") {
|
||||
digest = "sha256:" + digest
|
||||
}
|
||||
r, _, err := rawSource.GetBlob(digest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := dest.PutBlob(digest, r); err != nil {
|
||||
r.Close()
|
||||
return err
|
||||
}
|
||||
r.Close()
|
||||
|
||||
if err := dest.Commit(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ func contextFromGlobalOptions(c *cli.Context) *types.SystemContext {
|
||||
}
|
||||
|
||||
// ParseImage converts image URL-like string to an initialized handler for that image.
|
||||
// The caller must call .Close() on the returned Image.
|
||||
func parseImage(c *cli.Context) (types.Image, error) {
|
||||
imgName := c.Args().First()
|
||||
ref, err := transports.ParseImageName(imgName)
|
||||
@ -28,6 +29,7 @@ func parseImage(c *cli.Context) (types.Image, error) {
|
||||
|
||||
// parseImageSource converts image URL-like string to an ImageSource.
|
||||
// requestedManifestMIMETypes is as in types.ImageReference.NewImageSource.
|
||||
// The caller must call .Close() on the returned ImageSource.
|
||||
func parseImageSource(c *cli.Context, name string, requestedManifestMIMETypes []string) (types.ImageSource, error) {
|
||||
ref, err := transports.ParseImageName(name)
|
||||
if err != nil {
|
||||
|
14
vendor/github.com/containers/image/copy/copy.go
generated
vendored
14
vendor/github.com/containers/image/copy/copy.go
generated
vendored
@ -86,11 +86,14 @@ func Image(ctx *types.SystemContext, policyContext *signature.PolicyContext, des
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error initializing destination %s: %v", transports.ImageName(destRef), err)
|
||||
}
|
||||
defer dest.Close()
|
||||
|
||||
rawSource, err := srcRef.NewImageSource(ctx, dest.SupportedManifestMIMETypes())
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error initializing source %s: %v", transports.ImageName(srcRef), err)
|
||||
}
|
||||
src := image.FromSource(rawSource)
|
||||
defer src.Close()
|
||||
|
||||
// Please keep this policy check BEFORE reading any other information about the image.
|
||||
if allowed, err := policyContext.IsRunningImageAllowed(src); !allowed || err != nil { // Be paranoid and fail if either return value indicates so.
|
||||
@ -119,8 +122,7 @@ func Image(ctx *types.SystemContext, policyContext *signature.PolicyContext, des
|
||||
return fmt.Errorf("Error parsing manifest: %v", err)
|
||||
}
|
||||
for _, digest := range blobDigests {
|
||||
// TODO(mitr): do not ignore the size param returned here
|
||||
stream, _, err := rawSource.GetBlob(digest)
|
||||
stream, blobSize, err := rawSource.GetBlob(digest)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error reading blob %s: %v", digest, err)
|
||||
}
|
||||
@ -135,7 +137,7 @@ func Image(ctx *types.SystemContext, policyContext *signature.PolicyContext, des
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error preparing to verify blob %s: %v", digest, err)
|
||||
}
|
||||
if err := dest.PutBlob(digest, digestingReader); err != nil {
|
||||
if err := dest.PutBlob(digest, blobSize, digestingReader); err != nil {
|
||||
return fmt.Errorf("Error writing blob: %v", err)
|
||||
}
|
||||
if digestingReader.validationFailed { // Coverage: This should never happen.
|
||||
@ -160,7 +162,6 @@ func Image(ctx *types.SystemContext, policyContext *signature.PolicyContext, des
|
||||
sigs = append(sigs, newSig)
|
||||
}
|
||||
|
||||
// FIXME: We need to call PutManifest after PutBlob and before PutSignatures. This seems ugly; move to a "set properties" + "commit" model?
|
||||
if err := dest.PutManifest(manifest); err != nil {
|
||||
return fmt.Errorf("Error writing manifest: %v", err)
|
||||
}
|
||||
@ -168,5 +169,10 @@ func Image(ctx *types.SystemContext, policyContext *signature.PolicyContext, des
|
||||
if err := dest.PutSignatures(sigs); err != nil {
|
||||
return fmt.Errorf("Error writing signatures: %v", err)
|
||||
}
|
||||
|
||||
if err := dest.Commit(); err != nil {
|
||||
return fmt.Errorf("Error committing the finished image: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
31
vendor/github.com/containers/image/directory/directory_dest.go
generated
vendored
31
vendor/github.com/containers/image/directory/directory_dest.go
generated
vendored
@ -1,6 +1,7 @@
|
||||
package directory
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@ -24,20 +25,20 @@ func (d *dirImageDestination) Reference() types.ImageReference {
|
||||
return d.ref
|
||||
}
|
||||
|
||||
// Close removes resources associated with an initialized ImageDestination, if any.
|
||||
func (d *dirImageDestination) Close() {
|
||||
}
|
||||
|
||||
func (d *dirImageDestination) SupportedManifestMIMETypes() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *dirImageDestination) PutManifest(manifest []byte) error {
|
||||
return ioutil.WriteFile(d.ref.manifestPath(), manifest, 0644)
|
||||
}
|
||||
|
||||
// PutBlob writes contents of stream as a blob identified by digest.
|
||||
// The length of stream is expected to be expectedSize; if expectedSize == -1, it is not known.
|
||||
// WARNING: The contents of stream are being verified on the fly. Until stream.Read() returns io.EOF, the contents of the data SHOULD NOT be available
|
||||
// to any other readers for download using the supplied digest.
|
||||
// If stream.Read() at any time, ESPECIALLY at end of input, returns an error, PutBlob MUST 1) fail, and 2) delete any data stored so far.
|
||||
// Note: Calling PutBlob() and other methods may have ordering dependencies WRT other methods of this type. FIXME: Figure out and document.
|
||||
func (d *dirImageDestination) PutBlob(digest string, stream io.Reader) error {
|
||||
func (d *dirImageDestination) PutBlob(digest string, expectedSize int64, stream io.Reader) error {
|
||||
blobPath := d.ref.layerPath(digest)
|
||||
blobFile, err := ioutil.TempFile(filepath.Dir(blobPath), filepath.Base(blobPath))
|
||||
if err != nil {
|
||||
@ -51,9 +52,13 @@ func (d *dirImageDestination) PutBlob(digest string, stream io.Reader) error {
|
||||
}
|
||||
}()
|
||||
|
||||
if _, err := io.Copy(blobFile, stream); err != nil {
|
||||
size, err := io.Copy(blobFile, stream)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if expectedSize != -1 && size != expectedSize {
|
||||
return fmt.Errorf("Size mismatch when copying %s, expected %d, got %d", digest, expectedSize, size)
|
||||
}
|
||||
if err := blobFile.Sync(); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -67,6 +72,10 @@ func (d *dirImageDestination) PutBlob(digest string, stream io.Reader) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *dirImageDestination) PutManifest(manifest []byte) error {
|
||||
return ioutil.WriteFile(d.ref.manifestPath(), manifest, 0644)
|
||||
}
|
||||
|
||||
func (d *dirImageDestination) PutSignatures(signatures [][]byte) error {
|
||||
for i, sig := range signatures {
|
||||
if err := ioutil.WriteFile(d.ref.signaturePath(i), sig, 0644); err != nil {
|
||||
@ -75,3 +84,11 @@ func (d *dirImageDestination) PutSignatures(signatures [][]byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Commit marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before Commit() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *dirImageDestination) Commit() error {
|
||||
return nil
|
||||
}
|
||||
|
6
vendor/github.com/containers/image/directory/directory_src.go
generated
vendored
6
vendor/github.com/containers/image/directory/directory_src.go
generated
vendored
@ -13,6 +13,7 @@ type dirImageSource struct {
|
||||
}
|
||||
|
||||
// newImageSource returns an ImageSource reading from an existing directory.
|
||||
// The caller must call .Close() on the returned ImageSource.
|
||||
func newImageSource(ref dirReference) types.ImageSource {
|
||||
return &dirImageSource{ref}
|
||||
}
|
||||
@ -23,6 +24,10 @@ func (s *dirImageSource) Reference() types.ImageReference {
|
||||
return s.ref
|
||||
}
|
||||
|
||||
// Close removes resources associated with an initialized ImageSource, if any.
|
||||
func (s *dirImageSource) Close() {
|
||||
}
|
||||
|
||||
// it's up to the caller to determine the MIME type of the returned manifest's bytes
|
||||
func (s *dirImageSource) GetManifest() ([]byte, string, error) {
|
||||
m, err := ioutil.ReadFile(s.ref.manifestPath())
|
||||
@ -32,6 +37,7 @@ func (s *dirImageSource) GetManifest() ([]byte, string, error) {
|
||||
return m, "", err
|
||||
}
|
||||
|
||||
// GetBlob returns a stream for the specified blob, and the blob’s size (or -1 if unknown).
|
||||
func (s *dirImageSource) GetBlob(digest string) (io.ReadCloser, int64, error) {
|
||||
r, err := os.Open(s.ref.layerPath(digest))
|
||||
if err != nil {
|
||||
|
5
vendor/github.com/containers/image/directory/directory_transport.go
generated
vendored
5
vendor/github.com/containers/image/directory/directory_transport.go
generated
vendored
@ -128,19 +128,22 @@ func (ref dirReference) PolicyConfigurationNamespaces() []string {
|
||||
}
|
||||
|
||||
// NewImage returns a types.Image for this reference.
|
||||
// The caller must call .Close() on the returned Image.
|
||||
func (ref dirReference) NewImage(ctx *types.SystemContext) (types.Image, error) {
|
||||
src := newImageSource(ref)
|
||||
return image.FromSource(src), nil
|
||||
}
|
||||
|
||||
// NewImageSource returns a types.ImageSource for this reference,
|
||||
// asking the backend to use a manifest from requestedManifestMIMETypes if possible
|
||||
// asking the backend to use a manifest from requestedManifestMIMETypes if possible.
|
||||
// nil requestedManifestMIMETypes means manifest.DefaultRequestedManifestMIMETypes.
|
||||
// The caller must call .Close() on the returned ImageSource.
|
||||
func (ref dirReference) NewImageSource(ctx *types.SystemContext, requestedManifestMIMETypes []string) (types.ImageSource, error) {
|
||||
return newImageSource(ref), nil
|
||||
}
|
||||
|
||||
// NewImageDestination returns a types.ImageDestination for this reference.
|
||||
// The caller must call .Close() on the returned ImageDestination.
|
||||
func (ref dirReference) NewImageDestination(ctx *types.SystemContext) (types.ImageDestination, error) {
|
||||
return newImageDestination(ref), nil
|
||||
}
|
||||
|
8
vendor/github.com/containers/image/docker/docker_client.go
generated
vendored
8
vendor/github.com/containers/image/docker/docker_client.go
generated
vendored
@ -99,16 +99,20 @@ func (c *dockerClient) makeRequest(method, url string, headers map[string][]stri
|
||||
}
|
||||
|
||||
url = fmt.Sprintf(baseURL, c.scheme, c.registry) + url
|
||||
return c.makeRequestToResolvedURL(method, url, headers, stream)
|
||||
return c.makeRequestToResolvedURL(method, url, headers, stream, -1)
|
||||
}
|
||||
|
||||
// makeRequestToResolvedURL creates and executes a http.Request with the specified parameters, adding authentication and TLS options for the Docker client.
|
||||
// streamLen, if not -1, specifies the length of the data expected on stream.
|
||||
// makeRequest should generally be preferred.
|
||||
func (c *dockerClient) makeRequestToResolvedURL(method, url string, headers map[string][]string, stream io.Reader) (*http.Response, error) {
|
||||
func (c *dockerClient) makeRequestToResolvedURL(method, url string, headers map[string][]string, stream io.Reader, streamLen int64) (*http.Response, error) {
|
||||
req, err := http.NewRequest(method, url, stream)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if streamLen != -1 { // Do not blindly overwrite if streamLen == -1, http.NewRequest above can figure out the length of bytes.Reader and similar objects without us having to compute it.
|
||||
req.ContentLength = streamLen
|
||||
}
|
||||
req.Header.Set("Docker-Distribution-API-Version", "registry/2.0")
|
||||
for n, h := range headers {
|
||||
for _, hh := range h {
|
||||
|
1
vendor/github.com/containers/image/docker/docker_image.go
generated
vendored
1
vendor/github.com/containers/image/docker/docker_image.go
generated
vendored
@ -18,6 +18,7 @@ type Image struct {
|
||||
|
||||
// newImage returns a new Image interface type after setting up
|
||||
// a client to the registry hosting the given image.
|
||||
// The caller must call .Close() on the returned Image.
|
||||
func newImage(ctx *types.SystemContext, ref dockerReference) (types.Image, error) {
|
||||
s, err := newImageSource(ctx, ref, nil)
|
||||
if err != nil {
|
||||
|
78
vendor/github.com/containers/image/docker/docker_image_dest.go
generated
vendored
78
vendor/github.com/containers/image/docker/docker_image_dest.go
generated
vendored
@ -35,6 +35,10 @@ func (d *dockerImageDestination) Reference() types.ImageReference {
|
||||
return d.ref
|
||||
}
|
||||
|
||||
// Close removes resources associated with an initialized ImageDestination, if any.
|
||||
func (d *dockerImageDestination) Close() {
|
||||
}
|
||||
|
||||
func (d *dockerImageDestination) SupportedManifestMIMETypes() []string {
|
||||
return []string{
|
||||
// TODO(runcom): we'll add OCI as part of another PR here
|
||||
@ -44,42 +48,12 @@ func (d *dockerImageDestination) SupportedManifestMIMETypes() []string {
|
||||
}
|
||||
}
|
||||
|
||||
func (d *dockerImageDestination) PutManifest(m []byte) error {
|
||||
// FIXME: This only allows upload by digest, not creating a tag. See the
|
||||
// corresponding comment in openshift.NewImageDestination.
|
||||
digest, err := manifest.Digest(m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
url := fmt.Sprintf(manifestURL, d.ref.ref.RemoteName(), digest)
|
||||
|
||||
headers := map[string][]string{}
|
||||
mimeType := manifest.GuessMIMEType(m)
|
||||
if mimeType != "" {
|
||||
headers["Content-Type"] = []string{mimeType}
|
||||
}
|
||||
res, err := d.c.makeRequest("PUT", url, headers, bytes.NewReader(m))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusCreated {
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
if err == nil {
|
||||
logrus.Debugf("Error body %s", string(body))
|
||||
}
|
||||
logrus.Debugf("Error uploading manifest, status %d, %#v", res.StatusCode, res)
|
||||
return fmt.Errorf("Error uploading manifest to %s, status %d", url, res.StatusCode)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// PutBlob writes contents of stream as a blob identified by digest.
|
||||
// The length of stream is expected to be expectedSize; if expectedSize == -1, it is not known.
|
||||
// WARNING: The contents of stream are being verified on the fly. Until stream.Read() returns io.EOF, the contents of the data SHOULD NOT be available
|
||||
// to any other readers for download using the supplied digest.
|
||||
// If stream.Read() at any time, ESPECIALLY at end of input, returns an error, PutBlob MUST 1) fail, and 2) delete any data stored so far.
|
||||
// Note: Calling PutBlob() and other methods may have ordering dependencies WRT other methods of this type. FIXME: Figure out and document.
|
||||
func (d *dockerImageDestination) PutBlob(digest string, stream io.Reader) error {
|
||||
func (d *dockerImageDestination) PutBlob(digest string, expectedSize int64, stream io.Reader) error {
|
||||
checkURL := fmt.Sprintf(blobsURL, d.ref.ref.RemoteName(), digest)
|
||||
|
||||
logrus.Debugf("Checking %s", checkURL)
|
||||
@ -116,7 +90,7 @@ func (d *dockerImageDestination) PutBlob(digest string, stream io.Reader) error
|
||||
locationQuery := uploadLocation.Query()
|
||||
locationQuery.Set("digest", digest)
|
||||
uploadLocation.RawQuery = locationQuery.Encode()
|
||||
res, err = d.c.makeRequestToResolvedURL("PUT", uploadLocation.String(), map[string][]string{"Content-Type": {"application/octet-stream"}}, stream)
|
||||
res, err = d.c.makeRequestToResolvedURL("PUT", uploadLocation.String(), map[string][]string{"Content-Type": {"application/octet-stream"}}, stream, expectedSize)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -130,9 +104,47 @@ func (d *dockerImageDestination) PutBlob(digest string, stream io.Reader) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *dockerImageDestination) PutManifest(m []byte) error {
|
||||
// FIXME: This only allows upload by digest, not creating a tag. See the
|
||||
// corresponding comment in openshift.NewImageDestination.
|
||||
digest, err := manifest.Digest(m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
url := fmt.Sprintf(manifestURL, d.ref.ref.RemoteName(), digest)
|
||||
|
||||
headers := map[string][]string{}
|
||||
mimeType := manifest.GuessMIMEType(m)
|
||||
if mimeType != "" {
|
||||
headers["Content-Type"] = []string{mimeType}
|
||||
}
|
||||
res, err := d.c.makeRequest("PUT", url, headers, bytes.NewReader(m))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusCreated {
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
if err == nil {
|
||||
logrus.Debugf("Error body %s", string(body))
|
||||
}
|
||||
logrus.Debugf("Error uploading manifest, status %d, %#v", res.StatusCode, res)
|
||||
return fmt.Errorf("Error uploading manifest to %s, status %d", url, res.StatusCode)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *dockerImageDestination) PutSignatures(signatures [][]byte) error {
|
||||
if len(signatures) != 0 {
|
||||
return fmt.Errorf("Pushing signatures to a Docker Registry is not supported")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Commit marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before Commit() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *dockerImageDestination) Commit() error {
|
||||
return nil
|
||||
}
|
||||
|
10
vendor/github.com/containers/image/docker/docker_image_src.go
generated
vendored
10
vendor/github.com/containers/image/docker/docker_image_src.go
generated
vendored
@ -29,8 +29,9 @@ type dockerImageSource struct {
|
||||
}
|
||||
|
||||
// newImageSource creates a new ImageSource for the specified image reference,
|
||||
// asking the backend to use a manifest from requestedManifestMIMETypes if possible
|
||||
// asking the backend to use a manifest from requestedManifestMIMETypes if possible.
|
||||
// nil requestedManifestMIMETypes means manifest.DefaultRequestedManifestMIMETypes.
|
||||
// The caller must call .Close() on the returned ImageSource.
|
||||
func newImageSource(ctx *types.SystemContext, ref dockerReference, requestedManifestMIMETypes []string) (*dockerImageSource, error) {
|
||||
c, err := newDockerClient(ctx, ref.ref.Hostname())
|
||||
if err != nil {
|
||||
@ -52,6 +53,10 @@ func (s *dockerImageSource) Reference() types.ImageReference {
|
||||
return s.ref
|
||||
}
|
||||
|
||||
// Close removes resources associated with an initialized ImageSource, if any.
|
||||
func (s *dockerImageSource) Close() {
|
||||
}
|
||||
|
||||
// simplifyContentType drops parameters from a HTTP media type (see https://tools.ietf.org/html/rfc7231#section-3.1.1.1)
|
||||
// Alternatively, an empty string is returned unchanged, and invalid values are "simplified" to an empty string.
|
||||
func simplifyContentType(contentType string) string {
|
||||
@ -91,6 +96,7 @@ func (s *dockerImageSource) GetManifest() ([]byte, string, error) {
|
||||
return manblob, simplifyContentType(res.Header.Get("Content-Type")), nil
|
||||
}
|
||||
|
||||
// GetBlob returns a stream for the specified blob, and the blob’s size (or -1 if unknown).
|
||||
func (s *dockerImageSource) GetBlob(digest string) (io.ReadCloser, int64, error) {
|
||||
url := fmt.Sprintf(blobsURL, s.ref.ref.RemoteName(), digest)
|
||||
logrus.Debugf("Downloading %s", url)
|
||||
@ -104,7 +110,7 @@ func (s *dockerImageSource) GetBlob(digest string) (io.ReadCloser, int64, error)
|
||||
}
|
||||
size, err := strconv.ParseInt(res.Header.Get("Content-Length"), 10, 64)
|
||||
if err != nil {
|
||||
size = 0
|
||||
size = -1
|
||||
}
|
||||
return res.Body, size, nil
|
||||
}
|
||||
|
5
vendor/github.com/containers/image/docker/docker_transport.go
generated
vendored
5
vendor/github.com/containers/image/docker/docker_transport.go
generated
vendored
@ -116,18 +116,21 @@ func (ref dockerReference) PolicyConfigurationNamespaces() []string {
|
||||
}
|
||||
|
||||
// NewImage returns a types.Image for this reference.
|
||||
// The caller must call .Close() on the returned Image.
|
||||
func (ref dockerReference) NewImage(ctx *types.SystemContext) (types.Image, error) {
|
||||
return newImage(ctx, ref)
|
||||
}
|
||||
|
||||
// NewImageSource returns a types.ImageSource for this reference,
|
||||
// asking the backend to use a manifest from requestedManifestMIMETypes if possible
|
||||
// asking the backend to use a manifest from requestedManifestMIMETypes if possible.
|
||||
// nil requestedManifestMIMETypes means manifest.DefaultRequestedManifestMIMETypes.
|
||||
// The caller must call .Close() on the returned ImageSource.
|
||||
func (ref dockerReference) NewImageSource(ctx *types.SystemContext, requestedManifestMIMETypes []string) (types.ImageSource, error) {
|
||||
return newImageSource(ctx, ref, requestedManifestMIMETypes)
|
||||
}
|
||||
|
||||
// NewImageDestination returns a types.ImageDestination for this reference.
|
||||
// The caller must call .Close() on the returned ImageDestination.
|
||||
func (ref dockerReference) NewImageDestination(ctx *types.SystemContext) (types.ImageDestination, error) {
|
||||
return newImageDestination(ctx, ref)
|
||||
}
|
||||
|
11
vendor/github.com/containers/image/image/image.go
generated
vendored
11
vendor/github.com/containers/image/image/image.go
generated
vendored
@ -37,6 +37,12 @@ type genericImage struct {
|
||||
}
|
||||
|
||||
// FromSource returns a types.Image implementation for source.
|
||||
// The caller must call .Close() on the returned Image.
|
||||
//
|
||||
// FromSource “takes ownership” of the input ImageSource and will call src.Close()
|
||||
// when the image is closed. (This does not prevent callers from using both the
|
||||
// Image and ImageSource objects simultaneously, but it means that they only need to
|
||||
// the Image.)
|
||||
func FromSource(src types.ImageSource) types.Image {
|
||||
return &genericImage{src: src}
|
||||
}
|
||||
@ -47,6 +53,11 @@ func (i *genericImage) Reference() types.ImageReference {
|
||||
return i.src.Reference()
|
||||
}
|
||||
|
||||
// Close removes resources associated with an initialized Image, if any.
|
||||
func (i *genericImage) Close() {
|
||||
i.src.Close()
|
||||
}
|
||||
|
||||
// Manifest is like ImageSource.GetManifest, but the result is cached; it is OK to call this however often you need.
|
||||
// NOTE: It is essential for signature verification that Manifest returns the manifest from which BlobDigests is computed.
|
||||
func (i *genericImage) Manifest() ([]byte, string, error) {
|
||||
|
4
vendor/github.com/containers/image/manifest/manifest.go
generated
vendored
4
vendor/github.com/containers/image/manifest/manifest.go
generated
vendored
@ -28,9 +28,9 @@ const (
|
||||
// OCIV1ImageManifestListMIMEType specifies the mediaType for an image manifest list.
|
||||
OCIV1ImageManifestListMIMEType = "application/vnd.oci.image.manifest.list.v1+json"
|
||||
// OCIV1ImageSerializationMIMEType is the mediaType used for layers referenced by the manifest.
|
||||
OCIV1ImageSerializationMIMEType = "application/vnd.oci.image.serialization.rootfs.tar.gzip"
|
||||
OCIV1ImageSerializationMIMEType = "application/vnd.oci.image.layer.tar+gzip"
|
||||
// OCIV1ImageSerializationConfigMIMEType specifies the mediaType for the image configuration.
|
||||
OCIV1ImageSerializationConfigMIMEType = "application/vnd.oci.image.serialization.config.v1+json"
|
||||
OCIV1ImageSerializationConfigMIMEType = "application/vnd.oci.image.config.v1+json"
|
||||
)
|
||||
|
||||
// DefaultRequestedManifestMIMETypes is a list of MIME types a types.ImageSource
|
||||
|
98
vendor/github.com/containers/image/oci/oci_dest.go
generated
vendored
98
vendor/github.com/containers/image/oci/oci_dest.go
generated
vendored
@ -41,6 +41,55 @@ func (d *ociImageDestination) Reference() types.ImageReference {
|
||||
return d.ref
|
||||
}
|
||||
|
||||
// Close removes resources associated with an initialized ImageDestination, if any.
|
||||
func (d *ociImageDestination) Close() {
|
||||
}
|
||||
|
||||
// PutBlob writes contents of stream as a blob identified by digest.
|
||||
// The length of stream is expected to be expectedSize; if expectedSize == -1, it is not known.
|
||||
// WARNING: The contents of stream are being verified on the fly. Until stream.Read() returns io.EOF, the contents of the data SHOULD NOT be available
|
||||
// to any other readers for download using the supplied digest.
|
||||
// If stream.Read() at any time, ESPECIALLY at end of input, returns an error, PutBlob MUST 1) fail, and 2) delete any data stored so far.
|
||||
func (d *ociImageDestination) PutBlob(digest string, expectedSize int64, stream io.Reader) error {
|
||||
blobPath, err := d.ref.blobPath(digest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ensureParentDirectoryExists(blobPath); err != nil {
|
||||
return err
|
||||
}
|
||||
blobFile, err := ioutil.TempFile(filepath.Dir(blobPath), filepath.Base(blobPath))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
succeeded := false
|
||||
defer func() {
|
||||
blobFile.Close()
|
||||
if !succeeded {
|
||||
os.Remove(blobFile.Name())
|
||||
}
|
||||
}()
|
||||
|
||||
size, err := io.Copy(blobFile, stream)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if expectedSize != -1 && size != expectedSize {
|
||||
return fmt.Errorf("Size mismatch when copying %s, expected %d, got %d", digest, expectedSize, size)
|
||||
}
|
||||
if err := blobFile.Sync(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := blobFile.Chmod(0644); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.Rename(blobFile.Name(), blobPath); err != nil {
|
||||
return nil
|
||||
}
|
||||
succeeded = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func createManifest(m []byte) ([]byte, string, error) {
|
||||
om := ociManifest{}
|
||||
mt := manifest.GuessMIMEType(m)
|
||||
@ -114,47 +163,6 @@ func (d *ociImageDestination) PutManifest(m []byte) error {
|
||||
return ioutil.WriteFile(descriptorPath, data, 0644)
|
||||
}
|
||||
|
||||
// PutBlob writes contents of stream as a blob identified by digest.
|
||||
// WARNING: The contents of stream are being verified on the fly. Until stream.Read() returns io.EOF, the contents of the data SHOULD NOT be available
|
||||
// to any other readers for download using the supplied digest.
|
||||
// If stream.Read() at any time, ESPECIALLY at end of input, returns an error, PutBlob MUST 1) fail, and 2) delete any data stored so far.
|
||||
// Note: Calling PutBlob() and other methods may have ordering dependencies WRT other methods of this type. FIXME: Figure out and document.
|
||||
func (d *ociImageDestination) PutBlob(digest string, stream io.Reader) error {
|
||||
blobPath, err := d.ref.blobPath(digest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ensureParentDirectoryExists(blobPath); err != nil {
|
||||
return err
|
||||
}
|
||||
blobFile, err := ioutil.TempFile(filepath.Dir(blobPath), filepath.Base(blobPath))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
succeeded := false
|
||||
defer func() {
|
||||
blobFile.Close()
|
||||
if !succeeded {
|
||||
os.Remove(blobFile.Name())
|
||||
}
|
||||
}()
|
||||
|
||||
if _, err := io.Copy(blobFile, stream); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := blobFile.Sync(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := blobFile.Chmod(0644); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.Rename(blobFile.Name(), blobPath); err != nil {
|
||||
return nil
|
||||
}
|
||||
succeeded = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// ensureParentDirectoryExists ensures the parent of the supplied path exists.
|
||||
func ensureParentDirectoryExists(path string) error {
|
||||
parent := filepath.Dir(path)
|
||||
@ -179,3 +187,11 @@ func (d *ociImageDestination) PutSignatures(signatures [][]byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Commit marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before Commit() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *ociImageDestination) Commit() error {
|
||||
return nil
|
||||
}
|
||||
|
5
vendor/github.com/containers/image/oci/oci_transport.go
generated
vendored
5
vendor/github.com/containers/image/oci/oci_transport.go
generated
vendored
@ -165,18 +165,21 @@ func (ref ociReference) PolicyConfigurationNamespaces() []string {
|
||||
}
|
||||
|
||||
// NewImage returns a types.Image for this reference.
|
||||
// The caller must call .Close() on the returned Image.
|
||||
func (ref ociReference) NewImage(ctx *types.SystemContext) (types.Image, error) {
|
||||
return nil, errors.New("Full Image support not implemented for oci: image names")
|
||||
}
|
||||
|
||||
// NewImageSource returns a types.ImageSource for this reference,
|
||||
// asking the backend to use a manifest from requestedManifestMIMETypes if possible
|
||||
// asking the backend to use a manifest from requestedManifestMIMETypes if possible.
|
||||
// nil requestedManifestMIMETypes means manifest.DefaultRequestedManifestMIMETypes.
|
||||
// The caller must call .Close() on the returned ImageSource.
|
||||
func (ref ociReference) NewImageSource(ctx *types.SystemContext, requestedManifestMIMETypes []string) (types.ImageSource, error) {
|
||||
return nil, errors.New("Reading images not implemented for oci: image names")
|
||||
}
|
||||
|
||||
// NewImageDestination returns a types.ImageDestination for this reference.
|
||||
// The caller must call .Close() on the returned ImageDestination.
|
||||
func (ref ociReference) NewImageDestination(ctx *types.SystemContext) (types.ImageDestination, error) {
|
||||
return newImageDestination(ref), nil
|
||||
}
|
||||
|
46
vendor/github.com/containers/image/openshift/openshift.go
generated
vendored
46
vendor/github.com/containers/image/openshift/openshift.go
generated
vendored
@ -179,8 +179,9 @@ type openshiftImageSource struct {
|
||||
}
|
||||
|
||||
// newImageSource creates a new ImageSource for the specified reference,
|
||||
// asking the backend to use a manifest from requestedManifestMIMETypes if possible
|
||||
// asking the backend to use a manifest from requestedManifestMIMETypes if possible.
|
||||
// nil requestedManifestMIMETypes means manifest.DefaultRequestedManifestMIMETypes.
|
||||
// The caller must call .Close() on the returned ImageSource.
|
||||
func newImageSource(ctx *types.SystemContext, ref openshiftReference, requestedManifestMIMETypes []string) (types.ImageSource, error) {
|
||||
client, err := newOpenshiftClient(ref)
|
||||
if err != nil {
|
||||
@ -200,6 +201,14 @@ func (s *openshiftImageSource) Reference() types.ImageReference {
|
||||
return s.client.ref
|
||||
}
|
||||
|
||||
// Close removes resources associated with an initialized ImageSource, if any.
|
||||
func (s *openshiftImageSource) Close() {
|
||||
if s.docker != nil {
|
||||
s.docker.Close()
|
||||
s.docker = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (s *openshiftImageSource) GetManifest() ([]byte, string, error) {
|
||||
if err := s.ensureImageIsResolved(); err != nil {
|
||||
return nil, "", err
|
||||
@ -207,6 +216,7 @@ func (s *openshiftImageSource) GetManifest() ([]byte, string, error) {
|
||||
return s.docker.GetManifest()
|
||||
}
|
||||
|
||||
// GetBlob returns a stream for the specified blob, and the blob’s size (or -1 if unknown).
|
||||
func (s *openshiftImageSource) GetBlob(digest string) (io.ReadCloser, int64, error) {
|
||||
if err := s.ensureImageIsResolved(); err != nil {
|
||||
return nil, 0, err
|
||||
@ -320,6 +330,11 @@ func (d *openshiftImageDestination) Reference() types.ImageReference {
|
||||
return d.client.ref
|
||||
}
|
||||
|
||||
// Close removes resources associated with an initialized ImageDestination, if any.
|
||||
func (d *openshiftImageDestination) Close() {
|
||||
d.docker.Close()
|
||||
}
|
||||
|
||||
func (d *openshiftImageDestination) SupportedManifestMIMETypes() []string {
|
||||
return []string{
|
||||
manifest.DockerV2Schema1SignedMIMEType,
|
||||
@ -327,6 +342,15 @@ func (d *openshiftImageDestination) SupportedManifestMIMETypes() []string {
|
||||
}
|
||||
}
|
||||
|
||||
// PutBlob writes contents of stream as a blob identified by digest.
|
||||
// The length of stream is expected to be expectedSize; if expectedSize == -1, it is not known.
|
||||
// WARNING: The contents of stream are being verified on the fly. Until stream.Read() returns io.EOF, the contents of the data SHOULD NOT be available
|
||||
// to any other readers for download using the supplied digest.
|
||||
// If stream.Read() at any time, ESPECIALLY at end of input, returns an error, PutBlob MUST 1) fail, and 2) delete any data stored so far.
|
||||
func (d *openshiftImageDestination) PutBlob(digest string, expectedSize int64, stream io.Reader) error {
|
||||
return d.docker.PutBlob(digest, expectedSize, stream)
|
||||
}
|
||||
|
||||
func (d *openshiftImageDestination) PutManifest(m []byte) error {
|
||||
// FIXME? Can this eventually just call d.docker.PutManifest()?
|
||||
// Right now we need this as a skeleton to attach signatures to, and
|
||||
@ -373,19 +397,9 @@ func (d *openshiftImageDestination) PutManifest(m []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// PutBlob writes contents of stream as a blob identified by digest.
|
||||
// WARNING: The contents of stream are being verified on the fly. Until stream.Read() returns io.EOF, the contents of the data SHOULD NOT be available
|
||||
// to any other readers for download using the supplied digest.
|
||||
// If stream.Read() at any time, ESPECIALLY at end of input, returns an error, PutBlob MUST 1) fail, and 2) delete any data stored so far.
|
||||
// Note: Calling PutBlob() and other methods may have ordering dependencies WRT other methods of this type. FIXME: Figure out and document.
|
||||
func (d *openshiftImageDestination) PutBlob(digest string, stream io.Reader) error {
|
||||
return d.docker.PutBlob(digest, stream)
|
||||
}
|
||||
|
||||
func (d *openshiftImageDestination) PutSignatures(signatures [][]byte) error {
|
||||
// FIXME: This assumption that signatures are stored after the manifest rather breaks the model.
|
||||
if d.imageStreamImageName == "" {
|
||||
return fmt.Errorf("Unknown manifest digest, can't add signatures")
|
||||
return fmt.Errorf("Internal error: Unknown manifest digest, can't add signatures")
|
||||
}
|
||||
// Because image signatures are a shared resource in Atomic Registry, the default upload
|
||||
// always adds signatures. Eventually we should also allow removing signatures.
|
||||
@ -444,6 +458,14 @@ sigExists:
|
||||
return nil
|
||||
}
|
||||
|
||||
// Commit marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before Commit() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *openshiftImageDestination) Commit() error {
|
||||
return d.docker.Commit()
|
||||
}
|
||||
|
||||
// These structs are subsets of github.com/openshift/origin/pkg/image/api/v1 and its dependencies.
|
||||
type imageStream struct {
|
||||
Status imageStreamStatus `json:"status,omitempty"`
|
||||
|
5
vendor/github.com/containers/image/openshift/openshift_transport.go
generated
vendored
5
vendor/github.com/containers/image/openshift/openshift_transport.go
generated
vendored
@ -154,18 +154,21 @@ func (ref openshiftReference) PolicyConfigurationNamespaces() []string {
|
||||
}
|
||||
|
||||
// NewImage returns a types.Image for this reference.
|
||||
// The caller must call .Close() on the returned Image.
|
||||
func (ref openshiftReference) NewImage(ctx *types.SystemContext) (types.Image, error) {
|
||||
return nil, errors.New("Full Image support not implemented for atomic: image names")
|
||||
}
|
||||
|
||||
// NewImageSource returns a types.ImageSource for this reference,
|
||||
// asking the backend to use a manifest from requestedManifestMIMETypes if possible
|
||||
// asking the backend to use a manifest from requestedManifestMIMETypes if possible.
|
||||
// nil requestedManifestMIMETypes means manifest.DefaultRequestedManifestMIMETypes.
|
||||
// The caller must call .Close() on the returned ImageSource.
|
||||
func (ref openshiftReference) NewImageSource(ctx *types.SystemContext, requestedManifestMIMETypes []string) (types.ImageSource, error) {
|
||||
return newImageSource(ctx, ref, requestedManifestMIMETypes)
|
||||
}
|
||||
|
||||
// NewImageDestination returns a types.ImageDestination for this reference.
|
||||
// The caller must call .Close() on the returned ImageDestination.
|
||||
func (ref openshiftReference) NewImageDestination(ctx *types.SystemContext) (types.ImageDestination, error) {
|
||||
return newImageDestination(ctx, ref)
|
||||
}
|
||||
|
36
vendor/github.com/containers/image/types/types.go
generated
vendored
36
vendor/github.com/containers/image/types/types.go
generated
vendored
@ -71,12 +71,15 @@ type ImageReference interface {
|
||||
PolicyConfigurationNamespaces() []string
|
||||
|
||||
// NewImage returns a types.Image for this reference.
|
||||
// The caller must call .Close() on the returned Image.
|
||||
NewImage(ctx *SystemContext) (Image, error)
|
||||
// NewImageSource returns a types.ImageSource for this reference,
|
||||
// asking the backend to use a manifest from requestedManifestMIMETypes if possible
|
||||
// asking the backend to use a manifest from requestedManifestMIMETypes if possible.
|
||||
// nil requestedManifestMIMETypes means manifest.DefaultRequestedManifestMIMETypes.
|
||||
// The caller must call .Close() on the returned ImageSource.
|
||||
NewImageSource(ctx *SystemContext, requestedManifestMIMETypes []string) (ImageSource, error)
|
||||
// NewImageDestination returns a types.ImageDestination for this reference.
|
||||
// The caller must call .Close() on the returned ImageDestination.
|
||||
NewImageDestination(ctx *SystemContext) (ImageDestination, error)
|
||||
|
||||
// DeleteImage deletes the named image from the registry, if supported.
|
||||
@ -86,44 +89,63 @@ type ImageReference interface {
|
||||
// ImageSource is a service, possibly remote (= slow), to download components of a single image.
|
||||
// This is primarily useful for copying images around; for examining their properties, Image (below)
|
||||
// is usually more useful.
|
||||
// Each ImageSource should eventually be closed by calling Close().
|
||||
type ImageSource interface {
|
||||
// Reference returns the reference used to set up this source, _as specified by the user_
|
||||
// (not as the image itself, or its underlying storage, claims). This can be used e.g. to determine which public keys are trusted for this image.
|
||||
Reference() ImageReference
|
||||
// Close removes resources associated with an initialized ImageSource, if any.
|
||||
Close()
|
||||
// GetManifest returns the image's manifest along with its MIME type. The empty string is returned if the MIME type is unknown.
|
||||
// It may use a remote (= slow) service.
|
||||
GetManifest() ([]byte, string, error)
|
||||
// Note: Calling GetBlob() may have ordering dependencies WRT other methods of this type. FIXME: How does this work with (docker save) on stdin?
|
||||
// the second return value is the size of the blob. If not known 0 is returned
|
||||
// GetBlob returns a stream for the specified blob, and the blob’s size (or -1 if unknown).
|
||||
GetBlob(digest string) (io.ReadCloser, int64, error)
|
||||
// GetSignatures returns the image's signatures. It may use a remote (= slow) service.
|
||||
GetSignatures() ([][]byte, error)
|
||||
}
|
||||
|
||||
// ImageDestination is a service, possibly remote (= slow), to store components of a single image.
|
||||
//
|
||||
// There is a specific required order for some of the calls:
|
||||
// PutBlob on the various blobs, if any, MUST be called before PutManifest (manifest references blobs, which may be created or compressed only at push time)
|
||||
// PutSignatures, if called, MUST be called after PutManifest (signatures reference manifest contents)
|
||||
// Finally, Commit MUST be called if the caller wants the image, as formed by the components saved above, to persist.
|
||||
//
|
||||
// Each ImageDestination should eventually be closed by calling Close().
|
||||
type ImageDestination interface {
|
||||
// Reference returns the reference used to set up this destination. Note that this should directly correspond to user's intent,
|
||||
// e.g. it should use the public hostname instead of the result of resolving CNAMEs or following redirects.
|
||||
Reference() ImageReference
|
||||
// FIXME? This should also receive a MIME type if known, to differentiate between schema versions.
|
||||
PutManifest([]byte) error
|
||||
// Close removes resources associated with an initialized ImageDestination, if any.
|
||||
Close()
|
||||
// PutBlob writes contents of stream as a blob identified by digest.
|
||||
// The length of stream is expected to be expectedSize; if expectedSize == -1, it is not known.
|
||||
// WARNING: The contents of stream are being verified on the fly. Until stream.Read() returns io.EOF, the contents of the data SHOULD NOT be available
|
||||
// to any other readers for download using the supplied digest.
|
||||
// If stream.Read() at any time, ESPECIALLY at end of input, returns an error, PutBlob MUST 1) fail, and 2) delete any data stored so far.
|
||||
// Note: Calling PutBlob() and other methods may have ordering dependencies WRT other methods of this type. FIXME: Figure out and document.
|
||||
PutBlob(digest string, stream io.Reader) error
|
||||
PutBlob(digest string, expectedSize int64, stream io.Reader) error
|
||||
// FIXME? This should also receive a MIME type if known, to differentiate between schema versions.
|
||||
PutManifest([]byte) error
|
||||
PutSignatures(signatures [][]byte) error
|
||||
// Commit marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before Commit() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
|
||||
Commit() error
|
||||
// SupportedManifestMIMETypes tells which manifest mime types the destination supports
|
||||
// If an empty slice or nil it's returned, then any mime type can be tried to upload
|
||||
SupportedManifestMIMETypes() []string
|
||||
}
|
||||
|
||||
// Image is the primary API for inspecting properties of images.
|
||||
// Each Image should eventually be closed by calling Close().
|
||||
type Image interface {
|
||||
// Reference returns the reference used to set up this source, _as specified by the user_
|
||||
// (not as the image itself, or its underlying storage, claims). This can be used e.g. to determine which public keys are trusted for this image.
|
||||
Reference() ImageReference
|
||||
// Close removes resources associated with an initialized Image, if any.
|
||||
Close()
|
||||
// ref to repository?
|
||||
// Manifest is like ImageSource.GetManifest, but the result is cached; it is OK to call this however often you need.
|
||||
// NOTE: It is essential for signature verification that Manifest returns the manifest from which BlobDigests is computed.
|
||||
|
Loading…
Reference in New Issue
Block a user