Vendor in latest buildah 1.7.1

This release updates buildah to use containers/image v1.5
Which fixes a crash issue when pulling container images.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
Daniel J Walsh
2019-02-26 15:36:27 -05:00
parent ee667dcf97
commit e3b428686d
10 changed files with 349 additions and 26 deletions

View File

@ -93,7 +93,7 @@ k8s.io/apimachinery kubernetes-1.10.13-beta.0 https://github.com/kubernetes/apim
k8s.io/client-go kubernetes-1.10.13-beta.0 https://github.com/kubernetes/client-go
github.com/mrunalp/fileutils 7d4729fb36185a7c1719923406c9d40e54fb93c7
github.com/varlink/go 3ac79db6fd6aec70924193b090962f92985fe199
github.com/containers/buildah v1.7
github.com/containers/buildah v1.7.1
# TODO: Gotty has not been updated since 2012. Can we find replacement?
github.com/Nvveen/Gotty cd527374f1e5bff4938207604a14f2e38a9cf512
# do not go beyond the below commit as the next one requires a more recent

View File

@ -35,18 +35,23 @@ For blogs, release announcements and more, please checkout the [buildah.io](http
## Buildah and Podman relationship
Buildah and Podman are two complementary Open-source projects that are available on
most Linux platforms and both projects reside at [GitHub.com](https://github.com)
with Buildah [here](https://github.com/containers/buildah) and
Podman [here](https://github.com/containers/libpod). Both Buildah and Podman are
command line tools that work on OCI images and containers. The two projects
differentiate in their specialization.
Buildah and Podman are two complementary open-source projects that are
available on most Linux platforms and both projects reside at
[GitHub.com](https://github.com) with Buildah
[here](https://github.com/containers/buildah) and Podman
[here](https://github.com/containers/libpod). Both, Buildah and Podman are
command line tools that work on Open Container Initiative (OCI) images and
containers. The two projects differentiate in their specialization.
Buildah specializes in building OCI images. Buildah's commands replicate all
of the commands that are found in a Dockerfile. Buildahs goal is also to
provide a lower level coreutils interface to build images, allowing people to build
containers without requiring a Dockerfile. The intent with Buildah is to allow other
scripting languages to build container images, without requiring a daemon.
of the commands that are found in a Dockerfile. This allows building images
with and without Dockerfiles while not requiring any root privileges.
Buildahs ultimate goal is to provide a lower-level coreutils interface to
build images. The flexibility of building images without Dockerfiles allows
for the integration of other scripting languages into the build process.
Buildah follows a simple fork-exec model and does not run as a daemon
but it is based on a comprehensive API in golang, which can be vendored
into other tools.
Podman specializes in all of the commands and functions that help you to maintain and modify
OCI images, such as pulling and tagging. It also allows you to create, run, and maintain those containers
@ -60,7 +65,7 @@ to be added back to the container image. An easy way to think of it is the
command emulates the `docker run` command in functionality. Because of this and their underlying
storage differences, you can not see Podman containers from within Buildah or vice versa.
In short Buildah is an efficient way to create OCI images while Podman allows
In short, Buildah is an efficient way to create OCI images while Podman allows
you to manage and maintain those images and containers in a production environment using
familiar container cli commands. For more details, see the
[Container Tools Guide](https://github.com/containers/buildah/tree/master/docs/containertools).

View File

@ -26,7 +26,7 @@ const (
Package = "buildah"
// Version for the Package. Bump version in contrib/rpm/buildah.spec
// too.
Version = "1.7"
Version = "1.7.1"
// The value we use to identify what type of information, currently a
// serialized Builder structure, we are using as per-container state.
// This should only be changed when we make incompatible changes to

View File

@ -303,7 +303,7 @@ func newBuilder(ctx context.Context, store storage.Store, options BuilderOptions
}
conflict := 100
for true {
for {
coptions := storage.ContainerOptions{
LabelOpts: options.CommonBuildOpts.LabelOpts,
IDMappingOptions: newContainerIDMappingOptions(options.IDMappingOptions),

View File

@ -125,7 +125,7 @@ func GetNameSpaceFlags(flags *NameSpaceResults) pflag.FlagSet {
func GetLayerFlags(flags *LayerResults) pflag.FlagSet {
fs := pflag.FlagSet{}
fs.BoolVar(&flags.ForceRm, "force-rm", false, "Always remove intermediate containers after a build, even if the build is unsuccessful.")
fs.BoolVar(&flags.Layers, "layers", false, fmt.Sprintf("cache intermediate layers during build. Use BUILDAH_LAYERS environment variable to override. (default %t)", UseLayers()))
fs.BoolVar(&flags.Layers, "layers", UseLayers(), fmt.Sprintf("cache intermediate layers during build. Use BUILDAH_LAYERS environment variable to override."))
return fs
}
@ -152,7 +152,7 @@ func GetBudFlags(flags *BudResults) pflag.FlagSet {
fs.BoolVar(&flags.Pull, "pull", true, "pull the image if not present")
fs.BoolVar(&flags.PullAlways, "pull-always", false, "pull the image, even if a version is present")
fs.BoolVarP(&flags.Quiet, "quiet", "q", false, "refrain from announcing build instructions and image read/write progress")
fs.BoolVar(&flags.Rm, "rm", true, "Remove intermediate containers after a successful build (default true)")
fs.BoolVar(&flags.Rm, "rm", true, "Remove intermediate containers after a successful build")
fs.StringVar(&flags.Runtime, "runtime", util.Runtime(), "`path` to an alternate runtime. Use BUILDAH_RUNTIME environment variable to override.")
fs.StringSliceVar(&flags.RuntimeFlags, "runtime-flag", []string{}, "add global flags for the container runtime")
fs.StringVar(&flags.SignaturePolicy, "signature-policy", "", "`pathname` of signature policy file (not usually used)")

View File

@ -0,0 +1,319 @@
package secrets
import (
"bufio"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/containers/libpod/pkg/rootless"
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" overridden by the user
OverrideMountsFile = "/etc/containers/mounts.conf"
// UserOverrideMountsFile holds the default mount paths in the form
// "host_path:container_path" overridden by the rootless user
UserOverrideMountsFile = filepath.Join(os.Getenv("HOME"), ".config/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 {
// This is expected on most systems
logrus.Debugf("file %q not found, skipping...", filePath)
return nil
}
defer file.Close()
scanner := bufio.NewScanner(file)
if err = scanner.Err(); err != nil {
logrus.Errorf("error reading file %q, %v skipping...", filePath, err)
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")
}
// SecretMounts copies, adds, and mounts the secrets to the container root filesystem
func SecretMounts(mountLabel, containerWorkingDir, mountFile string) []rspec.Mount {
return SecretMountsWithUIDGID(mountLabel, containerWorkingDir, mountFile, containerWorkingDir, 0, 0)
}
// SecretMountsWithUIDGID specifies the uid/gid of the owner
func SecretMountsWithUIDGID(mountLabel, containerWorkingDir, mountFile, mountPrefix string, uid, gid int) []rspec.Mount {
var (
secretMounts []rspec.Mount
mountFiles []string
)
// Add secrets from paths given in the mounts.conf files
// mountFile will have a value if the hidden --default-mounts-file flag is set
// Note for testing purposes only
if mountFile == "" {
mountFiles = append(mountFiles, []string{OverrideMountsFile, DefaultMountsFile}...)
if rootless.IsRootless() {
mountFiles = append([]string{UserOverrideMountsFile}, mountFiles...)
_, err := os.Stat(UserOverrideMountsFile)
if err != nil && os.IsNotExist(err) {
os.MkdirAll(filepath.Dir(UserOverrideMountsFile), 0755)
if f, err := os.Create(UserOverrideMountsFile); err != nil {
logrus.Warnf("could not create file %s: %v", UserOverrideMountsFile, err)
} else {
f.Close()
}
}
}
} else {
mountFiles = append(mountFiles, mountFile)
}
for _, file := range mountFiles {
if _, err := os.Stat(file); err == nil {
mounts, err := addSecretsFromMountsFile(file, mountLabel, containerWorkingDir, mountPrefix, uid, gid)
if err != nil {
logrus.Warnf("error mounting secrets, skipping: %v", err)
}
secretMounts = mounts
break
}
}
// Add FIPS mode secret if /etc/system-fips exists on the host
_, err := os.Stat("/etc/system-fips")
if err == nil {
if err := addFIPSModeSecret(&secretMounts, containerWorkingDir); err != nil {
logrus.Errorf("error adding FIPS mode secret to container: %v", err)
}
} else if os.IsNotExist(err) {
logrus.Debug("/etc/system-fips does not exist on host, not mounting FIPS mode secret")
} else {
logrus.Errorf("stat /etc/system-fips failed for FIPS mode secret: %v", err)
}
return secretMounts
}
func rchown(chowndir string, uid, gid int) error {
return filepath.Walk(chowndir, func(filePath string, f os.FileInfo, err error) error {
return os.Lchown(filePath, uid, gid)
})
}
// addSecretsFromMountsFile copies the contents of host directory to container directory
// and returns a list of mounts
func addSecretsFromMountsFile(filePath, mountLabel, containerWorkingDir, mountPrefix string, uid, gid int) ([]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); err != nil {
if os.IsNotExist(err) {
logrus.Warnf("Path %q from %q doesn't exist, skipping", hostDir, filePath)
continue
}
return nil, errors.Wrapf(err, "failed to stat %q", hostDir)
}
ctrDirOnHost := filepath.Join(containerWorkingDir, ctrDir)
// In the event of a restart, don't want to copy secrets over again as they already would exist in ctrDirOnHost
_, err = os.Stat(ctrDirOnHost)
if os.IsNotExist(err) {
if err = os.MkdirAll(ctrDirOnHost, 0755); err != nil {
return nil, errors.Wrapf(err, "making container directory %q failed", ctrDirOnHost)
}
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")
}
if uid != 0 || gid != 0 {
if err := rchown(ctrDirOnHost, uid, gid); err != nil {
return nil, err
}
}
} else if err != nil {
return nil, errors.Wrapf(err, "error getting status of %q", ctrDirOnHost)
}
m := rspec.Mount{
Source: filepath.Join(mountPrefix, ctrDir),
Destination: ctrDir,
Type: "bind",
Options: []string{"bind", "rprivate"},
}
mounts = append(mounts, m)
}
return mounts, nil
}
// addFIPSModeSecret creates /run/secrets/system-fips in the container
// root filesystem if /etc/system-fips exists on hosts.
// This enables the container to be FIPS compliant and run openssl in
// FIPS mode as the host is also in FIPS mode.
func addFIPSModeSecret(mounts *[]rspec.Mount, containerWorkingDir string) error {
secretsDir := "/run/secrets"
ctrDirOnHost := filepath.Join(containerWorkingDir, secretsDir)
if _, err := os.Stat(ctrDirOnHost); os.IsNotExist(err) {
if err = os.MkdirAll(ctrDirOnHost, 0755); err != nil {
return errors.Wrapf(err, "making container directory on host failed")
}
}
fipsFile := filepath.Join(ctrDirOnHost, "system-fips")
// In the event of restart, it is possible for the FIPS mode file to already exist
if _, err := os.Stat(fipsFile); os.IsNotExist(err) {
file, err := os.Create(fipsFile)
if err != nil {
return errors.Wrapf(err, "error creating system-fips file in container for FIPS mode")
}
defer file.Close()
}
if !mountExists(*mounts, secretsDir) {
m := rspec.Mount{
Source: ctrDirOnHost,
Destination: secretsDir,
Type: "bind",
Options: []string{"bind", "rprivate"},
}
*mounts = append(*mounts, m)
}
return nil
}
// mountExists checks if a mount already exists in the spec
func mountExists(mounts []rspec.Mount, dest string) bool {
for _, mount := range mounts {
if mount.Destination == dest {
return true
}
}
return false
}
// 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)
}

View File

@ -194,12 +194,12 @@ func Pull(ctx context.Context, imageName string, options PullOptions) error {
errs = multierror.Append(errs, err)
continue
}
img, err := is.Transport.GetStoreImage(options.Store, ref)
taggedImg, err := is.Transport.GetStoreImage(options.Store, ref)
if err != nil {
errs = multierror.Append(errs, err)
continue
}
fmt.Printf("%s\n", img.ID)
fmt.Printf("%s\n", taggedImg.ID)
}
} else {
fmt.Printf("%s\n", img.ID)

View File

@ -21,15 +21,15 @@ import (
"github.com/containernetworking/cni/libcni"
"github.com/containers/buildah/bind"
"github.com/containers/buildah/chroot"
"github.com/containers/buildah/pkg/secrets"
"github.com/containers/buildah/util"
"github.com/containers/libpod/pkg/secrets"
"github.com/containers/storage/pkg/idtools"
"github.com/containers/storage/pkg/ioutils"
"github.com/containers/storage/pkg/reexec"
"github.com/containers/storage/pkg/stringid"
units "github.com/docker/go-units"
digest "github.com/opencontainers/go-digest"
"github.com/opencontainers/runtime-spec/specs-go"
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
@ -840,7 +840,7 @@ func setupNamespaces(g *generate.Generator, namespaceOptions NamespaceOptions, i
// valid resolution.
func runLookupPath(g *generate.Generator, command []string) []string {
// Look for the configured $PATH.
spec := g.Spec()
spec := g.Config
envPath := ""
for i := range spec.Process.Env {
if strings.HasPrefix(spec.Process.Env[i], "PATH=") {
@ -953,7 +953,7 @@ func (b *Builder) configureNamespaces(g *generate.Generator, options RunOptions)
}
found := false
spec := g.Spec()
spec := g.Config
for i := range spec.Process.Env {
if strings.HasPrefix(spec.Process.Env[i], "HOSTNAME=") {
found = true
@ -1054,7 +1054,7 @@ func (b *Builder) Run(command []string, options RunOptions) error {
// Now grab the spec from the generator. Set the generator to nil so that future contributors
// will quickly be able to tell that they're supposed to be modifying the spec directly from here.
spec := g.Spec()
spec := g.Config
g = nil
logrus.Debugf("ensuring working directory %q exists", filepath.Join(mountPoint, spec.Process.Cwd))

View File

@ -1 +0,0 @@
package unshare

View File

@ -3,7 +3,7 @@ github.com/blang/semver v3.5.0
github.com/BurntSushi/toml v0.2.0
github.com/containerd/continuity 004b46473808b3e7a4a3049c20e4376c91eb966d
github.com/containernetworking/cni v0.7.0-alpha1
github.com/containers/image v1.4
github.com/containers/image v1.5
github.com/vbauerster/mpb v3.3.4
github.com/mattn/go-isatty v0.0.4
github.com/VividCortex/ewma v1.1.1