Vendor in latest buildah

Adds in --iidfile flag to podman build.

Signed-off-by: umohnani8 <umohnani@redhat.com>

Closes: #707
Approved by: mheon
This commit is contained in:
umohnani8
2018-05-01 13:25:30 -04:00
committed by Atomic Bot
parent 7a0a8552cb
commit e98ad5751d
9 changed files with 65 additions and 215 deletions

View File

@ -89,6 +89,8 @@ type Builder struct {
ImageAnnotations map[string]string `json:"annotations,omitempty"` ImageAnnotations map[string]string `json:"annotations,omitempty"`
// ImageCreatedBy is a description of how this container was built. // ImageCreatedBy is a description of how this container was built.
ImageCreatedBy string `json:"created-by,omitempty"` ImageCreatedBy string `json:"created-by,omitempty"`
// ImageHistoryComment is a description of how our added layers were built.
ImageHistoryComment string `json:"history-comment,omitempty"`
// Image metadata and runtime settings, in multiple formats. // Image metadata and runtime settings, in multiple formats.
OCIv1 v1.Image `json:"ociv1,omitempty"` OCIv1 v1.Image `json:"ociv1,omitempty"`

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"time" "time"
cp "github.com/containers/image/copy" cp "github.com/containers/image/copy"
@ -46,6 +47,8 @@ type CommitOptions struct {
// github.com/containers/image/types SystemContext to hold credentials // github.com/containers/image/types SystemContext to hold credentials
// and other authentication/authorization information. // and other authentication/authorization information.
SystemContext *types.SystemContext SystemContext *types.SystemContext
// IIDFile tells the builder to write the image ID to the specified file
IIDFile string
} }
// PushOptions can be used to alter how an image is copied somewhere. // PushOptions can be used to alter how an image is copied somewhere.
@ -121,8 +124,14 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
img, err := is.Transport.GetStoreImage(b.store, dest) img, err := is.Transport.GetStoreImage(b.store, dest)
if err == nil { if err == nil {
if options.IIDFile != "" {
if err := ioutil.WriteFile(options.IIDFile, []byte(img.ID), 0644); err != nil {
return errors.Wrapf(err, "failed to write Image ID File %q", options.IIDFile)
}
} else {
fmt.Printf("%s\n", img.ID) fmt.Printf("%s\n", img.ID)
} }
}
return nil return nil
} }

View File

@ -588,7 +588,7 @@ func (b *Builder) Comment() string {
return b.Docker.Comment return b.Docker.Comment
} }
// SetComment sets the Comment which will be set in the container and in // SetComment sets the comment which will be set in the container and in
// containers built using images built from the container. // containers built using images built from the container.
// Note: this setting is not present in the OCIv1 image format, so it is // Note: this setting is not present in the OCIv1 image format, so it is
// discarded when writing images using OCIv1 formats. // discarded when writing images using OCIv1 formats.
@ -596,6 +596,18 @@ func (b *Builder) SetComment(comment string) {
b.Docker.Comment = comment b.Docker.Comment = comment
} }
// HistoryComment returns the comment which will be used in the history item
// which will describe the latest layer when we commit an image.
func (b *Builder) HistoryComment() string {
return b.ImageHistoryComment
}
// SetHistoryComment sets the comment which will be used in the history item
// which will describe the latest layer when we commit an image.
func (b *Builder) SetHistoryComment(comment string) {
b.ImageHistoryComment = comment
}
// StopSignal returns the signal which will be set in the container and in // StopSignal returns the signal which will be set in the container and in
// containers built using images buiilt from the container // containers built using images buiilt from the container
func (b *Builder) StopSignal() string { func (b *Builder) StopSignal() string {

View File

@ -46,6 +46,7 @@ type containerImageRef struct {
dconfig []byte dconfig []byte
created time.Time created time.Time
createdBy string createdBy string
historyComment string
annotations map[string]string annotations map[string]string
preferredManifestType string preferredManifestType string
exporting bool exporting bool
@ -303,6 +304,7 @@ func (i *containerImageRef) NewImageSource(ctx context.Context, sc *types.System
Created: &i.created, Created: &i.created,
CreatedBy: i.createdBy, CreatedBy: i.createdBy,
Author: oimage.Author, Author: oimage.Author,
Comment: i.historyComment,
EmptyLayer: false, EmptyLayer: false,
} }
oimage.History = append(oimage.History, onews) oimage.History = append(oimage.History, onews)
@ -310,6 +312,7 @@ func (i *containerImageRef) NewImageSource(ctx context.Context, sc *types.System
Created: i.created, Created: i.created,
CreatedBy: i.createdBy, CreatedBy: i.createdBy,
Author: dimage.Author, Author: dimage.Author,
Comment: i.historyComment,
EmptyLayer: false, EmptyLayer: false,
} }
dimage.History = append(dimage.History, dnews) dimage.History = append(dimage.History, dnews)
@ -521,6 +524,7 @@ func (b *Builder) makeImageRef(manifestType string, exporting bool, compress arc
dconfig: dconfig, dconfig: dconfig,
created: created, created: created,
createdBy: b.CreatedBy(), createdBy: b.CreatedBy(),
historyComment: b.HistoryComment(),
annotations: b.Annotations(), annotations: b.Annotations(),
preferredManifestType: manifestType, preferredManifestType: manifestType,
exporting: exporting, exporting: exporting,

View File

@ -110,6 +110,8 @@ type BuildOptions struct {
CommonBuildOpts *buildah.CommonBuildOptions CommonBuildOpts *buildah.CommonBuildOptions
// DefaultMountsFilePath is the file path holding the mounts to be mounted in "host-path:container-path" format // DefaultMountsFilePath is the file path holding the mounts to be mounted in "host-path:container-path" format
DefaultMountsFilePath string DefaultMountsFilePath string
// IIDFile tells the builder to write the image ID to the specified file
IIDFile string
} }
// Executor is a buildah-based implementation of the imagebuilder.Executor // Executor is a buildah-based implementation of the imagebuilder.Executor
@ -146,6 +148,7 @@ type Executor struct {
reportWriter io.Writer reportWriter io.Writer
commonBuildOptions *buildah.CommonBuildOptions commonBuildOptions *buildah.CommonBuildOptions
defaultMountsFilePath string defaultMountsFilePath string
iidfile string
} }
// withName creates a new child executor that will be used whenever a COPY statement uses --from=NAME. // withName creates a new child executor that will be used whenever a COPY statement uses --from=NAME.
@ -477,6 +480,7 @@ func NewExecutor(store storage.Store, options BuildOptions) (*Executor, error) {
reportWriter: options.ReportWriter, reportWriter: options.ReportWriter,
commonBuildOptions: options.CommonBuildOpts, commonBuildOptions: options.CommonBuildOpts,
defaultMountsFilePath: options.DefaultMountsFilePath, defaultMountsFilePath: options.DefaultMountsFilePath,
iidfile: options.IIDFile,
} }
if exec.err == nil { if exec.err == nil {
exec.err = os.Stderr exec.err = os.Stderr
@ -683,6 +687,7 @@ func (b *Executor) Commit(ctx context.Context, ib *imagebuilder.Builder) (err er
AdditionalTags: b.additionalTags, AdditionalTags: b.additionalTags,
ReportWriter: b.reportWriter, ReportWriter: b.reportWriter,
PreferredManifestType: b.outputFormat, PreferredManifestType: b.outputFormat,
IIDFile: b.iidfile,
} }
return b.builder.Commit(ctx, imageRef, options) return b.builder.Commit(ctx, imageRef, options)
} }

View File

@ -24,6 +24,10 @@ var (
Value: "", Value: "",
Usage: "use certificates at the specified path to access the registry", Usage: "use certificates at the specified path to access the registry",
}, },
cli.BoolFlag{
Name: "compress",
Usage: "This is legacy option, which has no effect on the image",
},
cli.StringFlag{ cli.StringFlag{
Name: "creds", Name: "creds",
Value: "", Value: "",
@ -37,6 +41,10 @@ var (
Name: "format", Name: "format",
Usage: "`format` of the built image's manifest and metadata", Usage: "`format` of the built image's manifest and metadata",
}, },
cli.StringFlag{
Name: "iidfile",
Usage: "Write the image ID to the file",
},
cli.BoolTFlag{ cli.BoolTFlag{
Name: "pull", Name: "pull",
Usage: "pull the image if not present", Usage: "pull the image if not present",
@ -49,6 +57,10 @@ var (
Name: "quiet, q", Name: "quiet, q",
Usage: "refrain from announcing build instructions and image read/write progress", Usage: "refrain from announcing build instructions and image read/write progress",
}, },
cli.BoolFlag{
Name: "rm",
Usage: "Remove intermediate containers after a successful build. Buildah does not currently support cacheing so this is a NOOP.",
},
cli.StringFlag{ cli.StringFlag{
Name: "runtime", Name: "runtime",
Usage: "`path` to an alternate runtime", Usage: "`path` to an alternate runtime",
@ -62,6 +74,10 @@ var (
Name: "signature-policy", Name: "signature-policy",
Usage: "`pathname` of signature policy file (not usually used)", Usage: "`pathname` of signature policy file (not usually used)",
}, },
cli.BoolFlag{
Name: "squash",
Usage: "Squash newly built layers into a single new layer. Buildah does not currently support cacheing so this is a NOOP.",
},
cli.StringSliceFlag{ cli.StringSliceFlag{
Name: "tag, t", Name: "tag, t",
Usage: "`tag` to apply to the built image", Usage: "`tag` to apply to the built image",

View File

@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"net" "net"
"os" "os"
"path/filepath"
"reflect" "reflect"
"regexp" "regexp"
"strings" "strings"
@ -56,7 +57,7 @@ func ParseCommonBuildOptions(c *cli.Context) (*buildah.CommonBuildOptions, error
if _, err := units.FromHumanSize(c.String("shm-size")); err != nil { if _, err := units.FromHumanSize(c.String("shm-size")); err != nil {
return nil, errors.Wrapf(err, "invalid --shm-size") return nil, errors.Wrapf(err, "invalid --shm-size")
} }
if err := parseVolumes(c.StringSlice("volume")); err != nil { if err := ParseVolumes(c.StringSlice("volume")); err != nil {
return nil, err return nil, err
} }
@ -122,7 +123,8 @@ func parseSecurityOpts(securityOpts []string, commonOpts *buildah.CommonBuildOpt
return nil return nil
} }
func parseVolumes(volumes []string) error { // ParseVolumes validates the host and container paths passed in to the --volume flag
func ParseVolumes(volumes []string) error {
if len(volumes) == 0 { if len(volumes) == 0 {
return nil return nil
} }
@ -147,6 +149,9 @@ func parseVolumes(volumes []string) error {
} }
func validateVolumeHostDir(hostDir string) error { func validateVolumeHostDir(hostDir string) error {
if !filepath.IsAbs(hostDir) {
return errors.Errorf("invalid host path, must be an absolute path %q", hostDir)
}
if _, err := os.Stat(hostDir); err != nil { if _, err := os.Stat(hostDir); err != nil {
return errors.Wrapf(err, "error checking path %q", hostDir) return errors.Wrapf(err, "error checking path %q", hostDir)
} }
@ -154,8 +159,8 @@ func validateVolumeHostDir(hostDir string) error {
} }
func validateVolumeCtrDir(ctrDir string) error { func validateVolumeCtrDir(ctrDir string) error {
if ctrDir[0] != '/' { if !filepath.IsAbs(ctrDir) {
return errors.Errorf("invalid container directory path %q", ctrDir) return errors.Errorf("invalid container path, must be an absolute path %q", ctrDir)
} }
return nil return nil
} }

View File

@ -19,6 +19,7 @@ import (
"github.com/opencontainers/runtime-tools/generate" "github.com/opencontainers/runtime-tools/generate"
"github.com/opencontainers/selinux/go-selinux/label" "github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/projectatomic/libpod/pkg/secrets"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"golang.org/x/crypto/ssh/terminal" "golang.org/x/crypto/ssh/terminal"
) )
@ -197,20 +198,14 @@ func (b *Builder) setupMounts(mountPoint string, spec *specs.Spec, optionMounts
} }
// Add secrets mounts // Add secrets mounts
mountsFiles := []string{OverrideMountsFile, b.DefaultMountsFilePath} secretMounts := secrets.SecretMounts(b.MountLabel, cdir, b.DefaultMountsFilePath)
for _, file := range mountsFiles {
secretMounts, err := secretMounts(file, b.MountLabel, cdir)
if err != nil {
logrus.Warn("error mounting secrets, skipping...")
continue
}
for _, mount := range secretMounts { for _, mount := range secretMounts {
if haveMount(mount.Destination) { if haveMount(mount.Destination) {
continue continue
} }
mounts = append(mounts, mount) mounts = append(mounts, mount)
} }
}
// Add temporary copies of the contents of volume locations at the // Add temporary copies of the contents of volume locations at the
// volume locations, unless we already have something there. // volume locations, unless we already have something there.
for _, volume := range builtinVolumes { for _, volume := range builtinVolumes {

View File

@ -1,198 +0,0 @@
package buildah
import (
"bufio"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
rspec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
var (
// DefaultMountsFile holds the default mount paths in the form
// "host_path:container_path"
DefaultMountsFile = "/usr/share/containers/mounts.conf"
// OverrideMountsFile holds the default mount paths in the form
// "host_path:container_path" overriden by the user
OverrideMountsFile = "/etc/containers/mounts.conf"
)
// secretData stores the name of the file and the content read from it
type secretData struct {
name string
data []byte
}
// saveTo saves secret data to given directory
func (s secretData) saveTo(dir string) error {
path := filepath.Join(dir, s.name)
if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil && !os.IsExist(err) {
return err
}
return ioutil.WriteFile(path, s.data, 0700)
}
func readAll(root, prefix string) ([]secretData, error) {
path := filepath.Join(root, prefix)
data := []secretData{}
files, err := ioutil.ReadDir(path)
if err != nil {
if os.IsNotExist(err) {
return data, nil
}
return nil, err
}
for _, f := range files {
fileData, err := readFile(root, filepath.Join(prefix, f.Name()))
if err != nil {
// If the file did not exist, might be a dangling symlink
// Ignore the error
if os.IsNotExist(err) {
continue
}
return nil, err
}
data = append(data, fileData...)
}
return data, nil
}
func readFile(root, name string) ([]secretData, error) {
path := filepath.Join(root, name)
s, err := os.Stat(path)
if err != nil {
return nil, err
}
if s.IsDir() {
dirData, err := readAll(root, name)
if err != nil {
return nil, err
}
return dirData, nil
}
bytes, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
return []secretData{{name: name, data: bytes}}, nil
}
func getHostSecretData(hostDir string) ([]secretData, error) {
var allSecrets []secretData
hostSecrets, err := readAll(hostDir, "")
if err != nil {
return nil, errors.Wrapf(err, "failed to read secrets from %q", hostDir)
}
return append(allSecrets, hostSecrets...), nil
}
func getMounts(filePath string) []string {
file, err := os.Open(filePath)
if err != nil {
logrus.Warnf("file %q not found, skipping...", filePath)
return nil
}
defer file.Close()
scanner := bufio.NewScanner(file)
if err = scanner.Err(); err != nil {
logrus.Warnf("error reading file %q, skipping...", filePath)
return nil
}
var mounts []string
for scanner.Scan() {
mounts = append(mounts, scanner.Text())
}
return mounts
}
// getHostAndCtrDir separates the host:container paths
func getMountsMap(path string) (string, string, error) {
arr := strings.SplitN(path, ":", 2)
if len(arr) == 2 {
return arr[0], arr[1], nil
}
return "", "", errors.Errorf("unable to get host and container dir")
}
// secretMount copies the contents of host directory to container directory
// and returns a list of mounts
func secretMounts(filePath, mountLabel, containerWorkingDir string) ([]rspec.Mount, error) {
var mounts []rspec.Mount
defaultMountsPaths := getMounts(filePath)
for _, path := range defaultMountsPaths {
hostDir, ctrDir, err := getMountsMap(path)
if err != nil {
return nil, err
}
// skip if the hostDir path doesn't exist
if _, err = os.Stat(hostDir); os.IsNotExist(err) {
logrus.Warnf("%q doesn't exist, skipping", hostDir)
continue
}
ctrDirOnHost := filepath.Join(containerWorkingDir, ctrDir)
if err = os.RemoveAll(ctrDirOnHost); err != nil {
return nil, fmt.Errorf("remove container directory failed: %v", err)
}
if err = os.MkdirAll(ctrDirOnHost, 0755); err != nil {
return nil, fmt.Errorf("making container directory failed: %v", err)
}
hostDir, err = resolveSymbolicLink(hostDir)
if err != nil {
return nil, err
}
data, err := getHostSecretData(hostDir)
if err != nil {
return nil, errors.Wrapf(err, "getting host secret data failed")
}
for _, s := range data {
if err := s.saveTo(ctrDirOnHost); err != nil {
return nil, errors.Wrapf(err, "error saving data to container filesystem on host %q", ctrDirOnHost)
}
}
err = label.Relabel(ctrDirOnHost, mountLabel, false)
if err != nil {
return nil, errors.Wrap(err, "error applying correct labels")
}
m := rspec.Mount{
Source: ctrDirOnHost,
Destination: ctrDir,
Type: "bind",
Options: []string{"bind"},
}
mounts = append(mounts, m)
}
return mounts, nil
}
// resolveSymbolicLink resolves a possbile symlink path. If the path is a symlink, returns resolved
// path; if not, returns the original path.
func resolveSymbolicLink(path string) (string, error) {
info, err := os.Lstat(path)
if err != nil {
return "", err
}
if info.Mode()&os.ModeSymlink != os.ModeSymlink {
return path, nil
}
return filepath.EvalSymlinks(path)
}