2017-02-11 00:48:15 +08:00
|
|
|
package buildah
|
2017-01-27 00:58:00 +08:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2017-01-27 22:38:32 +08:00
|
|
|
"time"
|
2017-01-27 00:58:00 +08:00
|
|
|
|
|
|
|
"github.com/Sirupsen/logrus"
|
|
|
|
"github.com/containers/image/docker/reference"
|
|
|
|
"github.com/containers/image/image"
|
|
|
|
is "github.com/containers/image/storage"
|
|
|
|
"github.com/containers/image/types"
|
2017-05-17 23:53:28 +08:00
|
|
|
"github.com/containers/storage"
|
2017-01-27 00:58:00 +08:00
|
|
|
"github.com/containers/storage/pkg/archive"
|
|
|
|
"github.com/containers/storage/pkg/ioutils"
|
|
|
|
digest "github.com/opencontainers/go-digest"
|
|
|
|
specs "github.com/opencontainers/image-spec/specs-go"
|
|
|
|
"github.com/opencontainers/image-spec/specs-go/v1"
|
2017-06-02 03:23:02 +08:00
|
|
|
"github.com/pkg/errors"
|
2017-05-18 05:01:06 +08:00
|
|
|
"github.com/projectatomic/buildah/docker"
|
2017-01-27 00:58:00 +08:00
|
|
|
)
|
|
|
|
|
2017-05-18 05:02:40 +08:00
|
|
|
const (
|
|
|
|
// OCIv1ImageManifest is the MIME type of an OCIv1 image manifest,
|
|
|
|
// suitable for specifying as a value of the PreferredManifestType
|
|
|
|
// member of a CommitOptions structure. It is also the default.
|
|
|
|
OCIv1ImageManifest = v1.MediaTypeImageManifest
|
|
|
|
// Dockerv2ImageManifest is the MIME type of a Docker v2s2 image
|
|
|
|
// manifest, suitable for specifying as a value of the
|
|
|
|
// PreferredManifestType member of a CommitOptions structure.
|
|
|
|
Dockerv2ImageManifest = docker.V2S2MediaTypeManifest
|
|
|
|
)
|
|
|
|
|
2017-01-27 00:58:00 +08:00
|
|
|
type containerImageRef struct {
|
2017-05-18 05:02:40 +08:00
|
|
|
store storage.Store
|
|
|
|
container *storage.Container
|
|
|
|
compression archive.Compression
|
|
|
|
name reference.Named
|
|
|
|
oconfig []byte
|
|
|
|
dconfig []byte
|
|
|
|
createdBy string
|
|
|
|
annotations map[string]string
|
|
|
|
preferredManifestType string
|
2017-01-27 00:58:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
type containerImageSource struct {
|
|
|
|
path string
|
|
|
|
ref *containerImageRef
|
|
|
|
store storage.Store
|
|
|
|
container *storage.Container
|
2017-01-28 15:18:02 +08:00
|
|
|
compression archive.Compression
|
2017-01-27 00:58:00 +08:00
|
|
|
config []byte
|
|
|
|
configDigest digest.Digest
|
|
|
|
manifest []byte
|
2017-05-18 05:01:06 +08:00
|
|
|
manifestType string
|
2017-01-27 00:58:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (i *containerImageRef) NewImage(sc *types.SystemContext) (types.Image, error) {
|
|
|
|
src, err := i.NewImageSource(sc, nil)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return image.FromSource(src)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i *containerImageRef) NewImageSource(sc *types.SystemContext, manifestTypes []string) (src types.ImageSource, err error) {
|
2017-05-18 05:01:06 +08:00
|
|
|
manifestType := ""
|
2017-05-18 05:02:40 +08:00
|
|
|
// If we have a preferred format, and it's in the acceptable list, select that one.
|
2017-05-18 05:01:06 +08:00
|
|
|
for _, mt := range manifestTypes {
|
2017-05-18 05:02:40 +08:00
|
|
|
if mt == i.preferredManifestType {
|
2017-05-18 05:01:06 +08:00
|
|
|
manifestType = mt
|
|
|
|
break
|
2017-01-27 00:58:00 +08:00
|
|
|
}
|
2017-05-18 05:02:40 +08:00
|
|
|
}
|
|
|
|
// Look for a supported format in the acceptable list.
|
|
|
|
if manifestType == "" {
|
|
|
|
for _, mt := range manifestTypes {
|
|
|
|
if mt == v1.MediaTypeImageManifest || mt == docker.V2S2MediaTypeManifest {
|
|
|
|
manifestType = mt
|
|
|
|
break
|
|
|
|
}
|
2017-01-27 00:58:00 +08:00
|
|
|
}
|
|
|
|
}
|
2017-05-18 05:02:40 +08:00
|
|
|
// If we don't support any of the passed-in formats, try to select our preferred one.
|
|
|
|
if manifestType == "" {
|
|
|
|
manifestType = i.preferredManifestType
|
|
|
|
}
|
2017-05-18 05:01:06 +08:00
|
|
|
// If it's not a format we support, return an error.
|
|
|
|
if manifestType != v1.MediaTypeImageManifest && manifestType != docker.V2S2MediaTypeManifest {
|
2017-06-03 00:17:27 +08:00
|
|
|
return nil, errors.Errorf("no supported manifest types (attempted to use %q, only know %q and %q)",
|
2017-05-18 05:01:06 +08:00
|
|
|
manifestType, v1.MediaTypeImageManifest, docker.V2S2MediaTypeManifest)
|
|
|
|
}
|
2017-01-27 00:58:00 +08:00
|
|
|
layers := []string{}
|
|
|
|
layerID := i.container.LayerID
|
2017-05-17 23:53:28 +08:00
|
|
|
layer, err := i.store.Layer(layerID)
|
2017-01-27 00:58:00 +08:00
|
|
|
if err != nil {
|
2017-06-02 03:23:02 +08:00
|
|
|
return nil, errors.Wrapf(err, "unable to read layer %q", layerID)
|
2017-01-27 00:58:00 +08:00
|
|
|
}
|
|
|
|
for layer != nil {
|
|
|
|
layers = append(append([]string{}, layerID), layers...)
|
|
|
|
layerID = layer.Parent
|
|
|
|
if layerID == "" {
|
|
|
|
err = nil
|
|
|
|
break
|
|
|
|
}
|
2017-05-17 23:53:28 +08:00
|
|
|
layer, err = i.store.Layer(layerID)
|
2017-01-27 00:58:00 +08:00
|
|
|
if err != nil {
|
2017-06-02 03:23:02 +08:00
|
|
|
return nil, errors.Wrapf(err, "unable to read layer %q", layerID)
|
2017-01-27 00:58:00 +08:00
|
|
|
}
|
|
|
|
}
|
2017-01-27 22:38:32 +08:00
|
|
|
logrus.Debugf("layer list: %q", layers)
|
|
|
|
|
2017-02-14 00:44:47 +08:00
|
|
|
created := time.Now().UTC()
|
2017-01-27 00:58:00 +08:00
|
|
|
|
2017-01-27 19:28:12 +08:00
|
|
|
path, err := ioutil.TempDir(os.TempDir(), Package)
|
2017-01-27 00:58:00 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-01-28 15:18:02 +08:00
|
|
|
logrus.Debugf("using %q to hold temporary data", path)
|
2017-01-27 00:58:00 +08:00
|
|
|
defer func() {
|
|
|
|
if src == nil {
|
|
|
|
err2 := os.RemoveAll(path)
|
|
|
|
if err2 != nil {
|
|
|
|
logrus.Errorf("error removing %q: %v", path, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2017-05-18 05:01:06 +08:00
|
|
|
oimage := v1.Image{}
|
|
|
|
err = json.Unmarshal(i.oconfig, &oimage)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
dimage := docker.V2Image{}
|
|
|
|
err = json.Unmarshal(i.dconfig, &dimage)
|
2017-01-27 22:38:32 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-05-18 05:01:06 +08:00
|
|
|
omanifest := v1.Manifest{
|
2017-01-27 00:58:00 +08:00
|
|
|
Versioned: specs.Versioned{
|
|
|
|
SchemaVersion: 2,
|
|
|
|
},
|
|
|
|
Config: v1.Descriptor{
|
|
|
|
MediaType: v1.MediaTypeImageConfig,
|
|
|
|
},
|
2017-02-11 00:48:15 +08:00
|
|
|
Layers: []v1.Descriptor{},
|
|
|
|
Annotations: i.annotations,
|
2017-01-27 00:58:00 +08:00
|
|
|
}
|
2017-05-18 05:01:06 +08:00
|
|
|
dmanifest := docker.V2S2Manifest{
|
|
|
|
V2Versioned: docker.V2Versioned{
|
|
|
|
SchemaVersion: 2,
|
|
|
|
MediaType: docker.V2S2MediaTypeManifest,
|
|
|
|
},
|
|
|
|
Config: docker.V2S2Descriptor{
|
|
|
|
MediaType: docker.V2S2MediaTypeImageConfig,
|
|
|
|
},
|
|
|
|
Layers: []docker.V2S2Descriptor{},
|
|
|
|
}
|
2017-01-27 00:58:00 +08:00
|
|
|
|
2017-05-18 05:01:06 +08:00
|
|
|
oimage.RootFS.Type = docker.TypeLayers
|
|
|
|
oimage.RootFS.DiffIDs = []string{}
|
|
|
|
dimage.RootFS = &docker.V2S2RootFS{}
|
|
|
|
dimage.RootFS.Type = docker.TypeLayers
|
|
|
|
dimage.RootFS.DiffIDs = []digest.Digest{}
|
2017-01-27 22:38:32 +08:00
|
|
|
|
2017-01-27 00:58:00 +08:00
|
|
|
for _, layerID := range layers {
|
|
|
|
rc, err := i.store.Diff("", layerID)
|
|
|
|
if err != nil {
|
2017-06-02 03:23:02 +08:00
|
|
|
return nil, errors.Wrapf(err, "error extracting layer %q", layerID)
|
2017-01-27 00:58:00 +08:00
|
|
|
}
|
|
|
|
defer rc.Close()
|
|
|
|
uncompressed, err := archive.DecompressStream(rc)
|
|
|
|
if err != nil {
|
2017-06-02 03:23:02 +08:00
|
|
|
return nil, errors.Wrapf(err, "error decompressing layer %q", layerID)
|
2017-01-27 00:58:00 +08:00
|
|
|
}
|
|
|
|
defer uncompressed.Close()
|
2017-01-28 15:18:02 +08:00
|
|
|
srcHasher := digest.Canonical.Digester()
|
|
|
|
reader := io.TeeReader(uncompressed, srcHasher.Hash())
|
2017-01-27 00:58:00 +08:00
|
|
|
layerFile, err := os.OpenFile(filepath.Join(path, "layer"), os.O_CREATE|os.O_WRONLY, 0600)
|
|
|
|
if err != nil {
|
2017-06-02 03:23:02 +08:00
|
|
|
return nil, errors.Wrapf(err, "error opening file for layer %q", layerID)
|
2017-01-27 00:58:00 +08:00
|
|
|
}
|
2017-01-28 15:18:02 +08:00
|
|
|
destHasher := digest.Canonical.Digester()
|
|
|
|
counter := ioutils.NewWriteCounter(layerFile)
|
|
|
|
multiWriter := io.MultiWriter(counter, destHasher.Hash())
|
2017-05-18 05:01:06 +08:00
|
|
|
omediaType := v1.MediaTypeImageLayer
|
|
|
|
dmediaType := docker.V2S2MediaTypeUncompressedLayer
|
2017-01-28 15:18:02 +08:00
|
|
|
if i.compression != archive.Uncompressed {
|
|
|
|
switch i.compression {
|
|
|
|
case archive.Gzip:
|
2017-05-18 05:01:06 +08:00
|
|
|
omediaType = v1.MediaTypeImageLayerGzip
|
|
|
|
dmediaType = docker.V2S2MediaTypeLayer
|
2017-01-28 15:18:02 +08:00
|
|
|
logrus.Debugf("compressing layer %q with gzip", layerID)
|
|
|
|
case archive.Bzip2:
|
|
|
|
logrus.Debugf("compressing layer %q with bzip2", layerID)
|
|
|
|
default:
|
|
|
|
logrus.Debugf("compressing layer %q with unknown compressor(?)", layerID)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
compressor, err := archive.CompressStream(multiWriter, i.compression)
|
|
|
|
if err != nil {
|
2017-06-02 03:23:02 +08:00
|
|
|
return nil, errors.Wrapf(err, "error compressing layer %q", layerID)
|
2017-01-28 15:18:02 +08:00
|
|
|
}
|
|
|
|
size, err := io.Copy(compressor, reader)
|
2017-01-27 00:58:00 +08:00
|
|
|
if err != nil {
|
2017-06-02 03:23:02 +08:00
|
|
|
return nil, errors.Wrapf(err, "error storing layer %q to file", layerID)
|
2017-01-27 00:58:00 +08:00
|
|
|
}
|
2017-01-28 15:18:02 +08:00
|
|
|
compressor.Close()
|
2017-01-27 00:58:00 +08:00
|
|
|
layerFile.Close()
|
2017-01-28 15:18:02 +08:00
|
|
|
if i.compression == archive.Uncompressed {
|
|
|
|
if size != counter.Count {
|
2017-06-03 00:17:27 +08:00
|
|
|
return nil, errors.Errorf("error storing layer %q to file: inconsistent layer size (copied %d, wrote %d)", layerID, size, counter.Count)
|
2017-01-28 15:18:02 +08:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
size = counter.Count
|
|
|
|
}
|
|
|
|
logrus.Debugf("layer %q size is %d bytes", layerID, size)
|
|
|
|
err = os.Rename(filepath.Join(path, "layer"), filepath.Join(path, destHasher.Digest().String()))
|
2017-03-07 23:41:25 +08:00
|
|
|
if err != nil {
|
2017-06-02 03:23:02 +08:00
|
|
|
return nil, errors.Wrapf(err, "error storing layer %q to file", layerID)
|
2017-03-07 23:41:25 +08:00
|
|
|
}
|
2017-05-18 05:01:06 +08:00
|
|
|
olayerDescriptor := v1.Descriptor{
|
|
|
|
MediaType: omediaType,
|
|
|
|
Digest: destHasher.Digest(),
|
|
|
|
Size: size,
|
|
|
|
}
|
|
|
|
omanifest.Layers = append(omanifest.Layers, olayerDescriptor)
|
|
|
|
dlayerDescriptor := docker.V2S2Descriptor{
|
|
|
|
MediaType: dmediaType,
|
2017-02-14 00:44:47 +08:00
|
|
|
Digest: destHasher.Digest(),
|
2017-01-27 00:58:00 +08:00
|
|
|
Size: size,
|
|
|
|
}
|
2017-05-18 05:01:06 +08:00
|
|
|
dmanifest.Layers = append(dmanifest.Layers, dlayerDescriptor)
|
|
|
|
oimage.RootFS.DiffIDs = append(oimage.RootFS.DiffIDs, srcHasher.Digest().String())
|
|
|
|
dimage.RootFS.DiffIDs = append(dimage.RootFS.DiffIDs, srcHasher.Digest())
|
2017-01-27 22:38:32 +08:00
|
|
|
}
|
|
|
|
|
2017-05-18 05:01:06 +08:00
|
|
|
onews := v1.History{
|
2017-02-14 00:44:47 +08:00
|
|
|
Created: created,
|
2017-02-11 00:48:15 +08:00
|
|
|
CreatedBy: i.createdBy,
|
2017-05-18 05:01:06 +08:00
|
|
|
Author: oimage.Author,
|
2017-01-27 22:38:32 +08:00
|
|
|
EmptyLayer: false,
|
|
|
|
}
|
2017-05-18 05:01:06 +08:00
|
|
|
oimage.History = append(oimage.History, onews)
|
|
|
|
dnews := docker.V2S2History{
|
|
|
|
Created: created,
|
|
|
|
CreatedBy: i.createdBy,
|
|
|
|
Author: dimage.Author,
|
|
|
|
EmptyLayer: false,
|
|
|
|
}
|
|
|
|
dimage.History = append(dimage.History, dnews)
|
2017-01-27 22:38:32 +08:00
|
|
|
|
2017-05-18 05:01:06 +08:00
|
|
|
oconfig, err := json.Marshal(&oimage)
|
2017-01-27 22:38:32 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2017-01-27 00:58:00 +08:00
|
|
|
}
|
2017-05-18 05:01:06 +08:00
|
|
|
logrus.Debugf("OCIv1 config = %s", oconfig)
|
|
|
|
i.oconfig = oconfig
|
2017-01-27 22:38:32 +08:00
|
|
|
|
2017-05-18 05:01:06 +08:00
|
|
|
omanifest.Config.Digest = digest.FromBytes(oconfig)
|
|
|
|
omanifest.Config.Size = int64(len(oconfig))
|
|
|
|
omanifest.Config.MediaType = v1.MediaTypeImageConfig
|
|
|
|
|
|
|
|
omanifestbytes, err := json.Marshal(&omanifest)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
logrus.Debugf("OCIv1 manifest = %s", omanifestbytes)
|
2017-01-27 00:58:00 +08:00
|
|
|
|
2017-05-18 05:01:06 +08:00
|
|
|
dconfig, err := json.Marshal(&dimage)
|
2017-01-27 00:58:00 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-05-18 05:01:06 +08:00
|
|
|
logrus.Debugf("Docker v2s2 config = %s", dconfig)
|
|
|
|
i.dconfig = dconfig
|
2017-01-27 00:58:00 +08:00
|
|
|
|
2017-05-18 05:01:06 +08:00
|
|
|
dmanifest.Config.Digest = digest.FromBytes(dconfig)
|
|
|
|
dmanifest.Config.Size = int64(len(dconfig))
|
|
|
|
dmanifest.Config.MediaType = docker.V2S2MediaTypeImageConfig
|
|
|
|
|
|
|
|
dmanifestbytes, err := json.Marshal(&dmanifest)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
logrus.Debugf("Docker v2s2 manifest = %s", dmanifestbytes)
|
|
|
|
|
|
|
|
var config []byte
|
|
|
|
var manifest []byte
|
|
|
|
switch manifestType {
|
|
|
|
case v1.MediaTypeImageManifest:
|
|
|
|
manifest = omanifestbytes
|
|
|
|
config = i.oconfig
|
|
|
|
case docker.V2S2MediaTypeManifest:
|
|
|
|
manifest = dmanifestbytes
|
|
|
|
config = i.dconfig
|
|
|
|
default:
|
|
|
|
panic("unreachable code: unsupported manifest type")
|
|
|
|
}
|
2017-01-27 00:58:00 +08:00
|
|
|
src = &containerImageSource{
|
|
|
|
path: path,
|
|
|
|
ref: i,
|
|
|
|
store: i.store,
|
|
|
|
container: i.container,
|
2017-01-28 15:18:02 +08:00
|
|
|
compression: i.compression,
|
2017-05-18 05:01:06 +08:00
|
|
|
manifest: manifest,
|
|
|
|
manifestType: manifestType,
|
|
|
|
config: config,
|
2017-01-28 05:20:28 +08:00
|
|
|
configDigest: digest.FromBytes(config),
|
2017-01-27 00:58:00 +08:00
|
|
|
}
|
|
|
|
return src, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i *containerImageRef) NewImageDestination(sc *types.SystemContext) (types.ImageDestination, error) {
|
2017-06-03 00:17:27 +08:00
|
|
|
return nil, errors.Errorf("can't write to a container")
|
2017-01-27 00:58:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (i *containerImageRef) DockerReference() reference.Named {
|
|
|
|
return i.name
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i *containerImageRef) StringWithinTransport() string {
|
|
|
|
if len(i.container.Names) > 0 {
|
|
|
|
return i.container.Names[0]
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i *containerImageRef) DeleteImage(*types.SystemContext) error {
|
|
|
|
// we were never here
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i *containerImageRef) PolicyConfigurationIdentity() string {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i *containerImageRef) PolicyConfigurationNamespaces() []string {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i *containerImageRef) Transport() types.ImageTransport {
|
|
|
|
return is.Transport
|
|
|
|
}
|
|
|
|
|
2017-03-22 04:38:50 +08:00
|
|
|
func (i *containerImageSource) Close() error {
|
2017-01-27 00:58:00 +08:00
|
|
|
err := os.RemoveAll(i.path)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Errorf("error removing %q: %v", i.path, err)
|
|
|
|
}
|
2017-03-22 04:38:50 +08:00
|
|
|
return err
|
2017-01-27 00:58:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (i *containerImageSource) Reference() types.ImageReference {
|
|
|
|
return i.ref
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i *containerImageSource) GetSignatures() ([][]byte, error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i *containerImageSource) GetTargetManifest(digest digest.Digest) ([]byte, string, error) {
|
2017-06-03 00:17:27 +08:00
|
|
|
return []byte{}, "", errors.Errorf("TODO")
|
2017-01-27 00:58:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (i *containerImageSource) GetManifest() ([]byte, string, error) {
|
2017-05-18 05:01:06 +08:00
|
|
|
return i.manifest, i.manifestType, nil
|
2017-01-27 00:58:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (i *containerImageSource) GetBlob(blob types.BlobInfo) (reader io.ReadCloser, size int64, err error) {
|
|
|
|
if blob.Digest == i.configDigest {
|
|
|
|
logrus.Debugf("start reading config")
|
|
|
|
reader := bytes.NewReader(i.config)
|
|
|
|
closer := func() error {
|
|
|
|
logrus.Debugf("finished reading config")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return ioutils.NewReadCloserWrapper(reader, closer), reader.Size(), nil
|
|
|
|
}
|
|
|
|
layerFile, err := os.OpenFile(filepath.Join(i.path, blob.Digest.String()), os.O_RDONLY, 0600)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Debugf("error reading layer %q: %v", blob.Digest.String(), err)
|
|
|
|
return nil, -1, err
|
|
|
|
}
|
|
|
|
size = -1
|
|
|
|
st, err := layerFile.Stat()
|
|
|
|
if err != nil {
|
|
|
|
logrus.Warnf("error reading size of layer %q: %v", blob.Digest.String(), err)
|
|
|
|
} else {
|
|
|
|
size = st.Size()
|
|
|
|
}
|
|
|
|
logrus.Debugf("reading layer %q", blob.Digest.String())
|
2017-01-27 19:28:41 +08:00
|
|
|
closer := func() error {
|
|
|
|
layerFile.Close()
|
|
|
|
logrus.Debugf("finished reading layer %q", blob.Digest.String())
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return ioutils.NewReadCloserWrapper(layerFile, closer), size, nil
|
2017-01-27 00:58:00 +08:00
|
|
|
}
|
|
|
|
|
2017-05-18 05:02:40 +08:00
|
|
|
func (b *Builder) makeContainerImageRef(manifestType string, compress archive.Compression) (types.ImageReference, error) {
|
2017-01-27 00:58:00 +08:00
|
|
|
var name reference.Named
|
2017-05-18 05:02:40 +08:00
|
|
|
if manifestType == "" {
|
|
|
|
manifestType = OCIv1ImageManifest
|
|
|
|
}
|
2017-05-17 23:53:28 +08:00
|
|
|
container, err := b.store.Container(b.ContainerID)
|
2017-02-11 00:48:15 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-01-27 00:58:00 +08:00
|
|
|
if len(container.Names) > 0 {
|
|
|
|
name, err = reference.ParseNamed(container.Names[0])
|
|
|
|
if err != nil {
|
|
|
|
name = nil
|
|
|
|
}
|
|
|
|
}
|
2017-05-18 05:01:06 +08:00
|
|
|
oconfig, err := json.Marshal(&b.OCIv1)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
dconfig, err := json.Marshal(&b.Docker)
|
Maintain multiple working container configs
Maintain the container configuration in multiple formats in the Buildah
object, initializing one based on the other, depending on which format
the source image used for its configuration.
Replace directly manipulated fields in the Buildah object (Annotations,
CreatedBy, OS, Architecture, Maintainer, User, Workdir, Env, Cmd,
Entrypoint, Expose, Labels, and Volumes) with accessor functions which
update both configurations and which read from whichever one we consider
to be authoritative. Drop Args because we weren't using them.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
Closes: #102
Approved by: rhatdan
2017-05-16 23:08:52 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-02-11 00:48:15 +08:00
|
|
|
ref := &containerImageRef{
|
2017-05-18 05:02:40 +08:00
|
|
|
store: b.store,
|
|
|
|
container: container,
|
|
|
|
compression: compress,
|
|
|
|
name: name,
|
|
|
|
oconfig: oconfig,
|
|
|
|
dconfig: dconfig,
|
|
|
|
createdBy: b.CreatedBy(),
|
|
|
|
annotations: b.Annotations(),
|
|
|
|
preferredManifestType: manifestType,
|
2017-01-27 00:58:00 +08:00
|
|
|
}
|
2017-02-11 00:48:15 +08:00
|
|
|
return ref, nil
|
2017-01-27 00:58:00 +08:00
|
|
|
}
|