2016-06-28 15:24:25 +08:00
|
|
|
|
package directory
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2017-07-29 04:47:24 +08:00
|
|
|
|
"context"
|
2016-06-28 15:24:25 +08:00
|
|
|
|
"io"
|
|
|
|
|
|
"io/ioutil"
|
|
|
|
|
|
"os"
|
|
|
|
|
|
|
2016-10-29 00:07:29 +08:00
|
|
|
|
"github.com/containers/image/manifest"
|
2016-06-28 15:24:25 +08:00
|
|
|
|
"github.com/containers/image/types"
|
2017-01-09 18:10:30 +08:00
|
|
|
|
"github.com/opencontainers/go-digest"
|
2016-12-19 22:13:01 +08:00
|
|
|
|
"github.com/pkg/errors"
|
2016-06-28 15:24:25 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
type dirImageSource struct {
|
2016-07-14 09:37:11 +08:00
|
|
|
|
ref dirReference
|
2016-06-28 15:24:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-07-14 09:37:11 +08:00
|
|
|
|
// newImageSource returns an ImageSource reading from an existing directory.
|
2016-08-27 05:24:39 +08:00
|
|
|
|
// The caller must call .Close() on the returned ImageSource.
|
2016-07-14 09:37:11 +08:00
|
|
|
|
func newImageSource(ref dirReference) types.ImageSource {
|
|
|
|
|
|
return &dirImageSource{ref}
|
2016-06-28 15:24:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-07-14 03:50:04 +08:00
|
|
|
|
// 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.
|
|
|
|
|
|
func (s *dirImageSource) Reference() types.ImageReference {
|
|
|
|
|
|
return s.ref
|
2016-06-28 15:24:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-08-27 05:24:39 +08:00
|
|
|
|
// Close removes resources associated with an initialized ImageSource, if any.
|
2017-02-06 15:13:00 +08:00
|
|
|
|
func (s *dirImageSource) Close() error {
|
|
|
|
|
|
return nil
|
2016-08-27 05:24:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-11-02 01:20:36 +08:00
|
|
|
|
// GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available).
|
|
|
|
|
|
// It may use a remote (= slow) service.
|
2017-09-16 05:42:07 +08:00
|
|
|
|
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list);
|
|
|
|
|
|
// this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists).
|
2018-02-23 17:45:56 +08:00
|
|
|
|
func (s *dirImageSource) GetManifest(ctx context.Context, instanceDigest *digest.Digest) ([]byte, string, error) {
|
2017-09-16 05:42:07 +08:00
|
|
|
|
if instanceDigest != nil {
|
|
|
|
|
|
return nil, "", errors.Errorf(`Getting target manifest not supported by "dir:"`)
|
|
|
|
|
|
}
|
2016-07-09 11:24:41 +08:00
|
|
|
|
m, err := ioutil.ReadFile(s.ref.manifestPath())
|
2016-06-28 15:24:25 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, "", err
|
|
|
|
|
|
}
|
2016-10-29 00:07:29 +08:00
|
|
|
|
return m, manifest.GuessMIMEType(m), err
|
2016-06-28 15:24:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-08-27 09:13:00 +08:00
|
|
|
|
// GetBlob returns a stream for the specified blob, and the blob’s size (or -1 if unknown).
|
2018-02-23 17:45:56 +08:00
|
|
|
|
func (s *dirImageSource) GetBlob(ctx context.Context, info types.BlobInfo) (io.ReadCloser, int64, error) {
|
2016-11-02 17:20:10 +08:00
|
|
|
|
r, err := os.Open(s.ref.layerPath(info.Digest))
|
2016-06-28 15:24:25 +08:00
|
|
|
|
if err != nil {
|
2018-02-20 01:06:10 +08:00
|
|
|
|
return nil, -1, err
|
2016-06-28 15:24:25 +08:00
|
|
|
|
}
|
2016-07-14 00:59:27 +08:00
|
|
|
|
fi, err := r.Stat()
|
2016-06-28 15:24:25 +08:00
|
|
|
|
if err != nil {
|
2018-02-20 01:06:10 +08:00
|
|
|
|
return nil, -1, err
|
2016-06-28 15:24:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
return r, fi.Size(), nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-09-16 06:43:30 +08:00
|
|
|
|
// GetSignatures returns the image's signatures. It may use a remote (= slow) service.
|
|
|
|
|
|
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve signatures for
|
|
|
|
|
|
// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list
|
|
|
|
|
|
// (e.g. if the source never returns manifest lists).
|
|
|
|
|
|
func (s *dirImageSource) GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) {
|
|
|
|
|
|
if instanceDigest != nil {
|
|
|
|
|
|
return nil, errors.Errorf(`Manifests lists are not supported by "dir:"`)
|
|
|
|
|
|
}
|
2016-06-28 15:24:25 +08:00
|
|
|
|
signatures := [][]byte{}
|
|
|
|
|
|
for i := 0; ; i++ {
|
2016-07-09 11:24:41 +08:00
|
|
|
|
signature, err := ioutil.ReadFile(s.ref.signaturePath(i))
|
2016-06-28 15:24:25 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
|
|
break
|
|
|
|
|
|
}
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
}
|
|
|
|
|
|
signatures = append(signatures, signature)
|
|
|
|
|
|
}
|
|
|
|
|
|
return signatures, nil
|
|
|
|
|
|
}
|
2017-10-24 03:10:23 +08:00
|
|
|
|
|
|
|
|
|
|
// LayerInfosForCopy() returns updated layer info that should be used when copying, in preference to values in the manifest, if specified.
|
2018-02-23 17:45:56 +08:00
|
|
|
|
func (s *dirImageSource) LayerInfosForCopy(ctx context.Context) ([]types.BlobInfo, error) {
|
2018-01-22 23:56:54 +08:00
|
|
|
|
return nil, nil
|
2017-10-24 03:10:23 +08:00
|
|
|
|
}
|