From e3b428686d4b572d7c9658c7ad8c4e6936cfe73f Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Tue, 26 Feb 2019 15:36:27 -0500 Subject: 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 --- vendor.conf | 2 +- vendor/github.com/containers/buildah/README.md | 29 +- vendor/github.com/containers/buildah/buildah.go | 2 +- vendor/github.com/containers/buildah/new.go | 2 +- .../containers/buildah/pkg/cli/common.go | 4 +- .../containers/buildah/pkg/secrets/secrets.go | 319 +++++++++++++++++++++ vendor/github.com/containers/buildah/pull.go | 4 +- vendor/github.com/containers/buildah/run.go | 10 +- .../buildah/unshare/unshare_unsupported.go | 1 - vendor/github.com/containers/buildah/vendor.conf | 2 +- 10 files changed, 349 insertions(+), 26 deletions(-) create mode 100644 vendor/github.com/containers/buildah/pkg/secrets/secrets.go delete mode 100644 vendor/github.com/containers/buildah/unshare/unshare_unsupported.go diff --git a/vendor.conf b/vendor.conf index 678807d1c..f739c76f4 100644 --- a/vendor.conf +++ b/vendor.conf @@ -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 diff --git a/vendor/github.com/containers/buildah/README.md b/vendor/github.com/containers/buildah/README.md index 12eafdf88..913a4336f 100644 --- a/vendor/github.com/containers/buildah/README.md +++ b/vendor/github.com/containers/buildah/README.md @@ -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. Buildah’s 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. +Buildah’s 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 @@ -55,12 +60,12 @@ created from those images. A major difference between Podman and Buildah is their concept of a container. Podman allows users to create "traditional containers" where the intent of these containers is to be long lived. While Buildah containers are really just created to allow content -to be added back to the container image. An easy way to think of it is the +to be added back to the container image. An easy way to think of it is the `buildah run` command emulates the RUN command in a Dockerfile while the `podman run` 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). diff --git a/vendor/github.com/containers/buildah/buildah.go b/vendor/github.com/containers/buildah/buildah.go index 755bc348e..cca80a308 100644 --- a/vendor/github.com/containers/buildah/buildah.go +++ b/vendor/github.com/containers/buildah/buildah.go @@ -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 diff --git a/vendor/github.com/containers/buildah/new.go b/vendor/github.com/containers/buildah/new.go index 01c2e733f..768cdd0c6 100644 --- a/vendor/github.com/containers/buildah/new.go +++ b/vendor/github.com/containers/buildah/new.go @@ -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), diff --git a/vendor/github.com/containers/buildah/pkg/cli/common.go b/vendor/github.com/containers/buildah/pkg/cli/common.go index 09f951b35..f167353b8 100644 --- a/vendor/github.com/containers/buildah/pkg/cli/common.go +++ b/vendor/github.com/containers/buildah/pkg/cli/common.go @@ -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)") diff --git a/vendor/github.com/containers/buildah/pkg/secrets/secrets.go b/vendor/github.com/containers/buildah/pkg/secrets/secrets.go new file mode 100644 index 000000000..242953609 --- /dev/null +++ b/vendor/github.com/containers/buildah/pkg/secrets/secrets.go @@ -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) +} diff --git a/vendor/github.com/containers/buildah/pull.go b/vendor/github.com/containers/buildah/pull.go index d1f33fb01..363cf5ce2 100644 --- a/vendor/github.com/containers/buildah/pull.go +++ b/vendor/github.com/containers/buildah/pull.go @@ -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) diff --git a/vendor/github.com/containers/buildah/run.go b/vendor/github.com/containers/buildah/run.go index 3a248f4f2..4d6d28380 100644 --- a/vendor/github.com/containers/buildah/run.go +++ b/vendor/github.com/containers/buildah/run.go @@ -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)) diff --git a/vendor/github.com/containers/buildah/unshare/unshare_unsupported.go b/vendor/github.com/containers/buildah/unshare/unshare_unsupported.go deleted file mode 100644 index feeceae66..000000000 --- a/vendor/github.com/containers/buildah/unshare/unshare_unsupported.go +++ /dev/null @@ -1 +0,0 @@ -package unshare diff --git a/vendor/github.com/containers/buildah/vendor.conf b/vendor/github.com/containers/buildah/vendor.conf index 7438fc909..27bf45541 100644 --- a/vendor/github.com/containers/buildah/vendor.conf +++ b/vendor/github.com/containers/buildah/vendor.conf @@ -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 -- cgit v1.2.3-54-g00ecf