| 
									
										
										
										
											2017-02-14 05:12:02 +08:00
										 |  |  | package buildah | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2018-02-14 03:58:56 +08:00
										 |  |  | 	"bufio" | 
					
						
							| 
									
										
										
										
											2017-02-14 05:12:02 +08:00
										 |  |  | 	"encoding/json" | 
					
						
							| 
									
										
										
										
											2018-02-14 03:58:56 +08:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2018-03-20 19:31:51 +08:00
										 |  |  | 	"io" | 
					
						
							| 
									
										
										
										
											2017-02-14 05:12:02 +08:00
										 |  |  | 	"io/ioutil" | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | 	"os/exec" | 
					
						
							|  |  |  | 	"path/filepath" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/containers/storage/pkg/ioutils" | 
					
						
							| 
									
										
										
										
											2018-02-14 03:58:56 +08:00
										 |  |  | 	"github.com/docker/docker/profiles/seccomp" | 
					
						
							|  |  |  | 	units "github.com/docker/go-units" | 
					
						
							| 
									
										
										
										
											2017-06-21 05:37:50 +08:00
										 |  |  | 	digest "github.com/opencontainers/go-digest" | 
					
						
							| 
									
										
										
										
											2017-02-18 02:58:34 +08:00
										 |  |  | 	"github.com/opencontainers/runtime-spec/specs-go" | 
					
						
							| 
									
										
										
										
											2017-02-14 05:12:02 +08:00
										 |  |  | 	"github.com/opencontainers/runtime-tools/generate" | 
					
						
							| 
									
										
										
										
											2017-11-29 03:22:47 +08:00
										 |  |  | 	"github.com/opencontainers/selinux/go-selinux/label" | 
					
						
							| 
									
										
										
										
											2017-06-02 03:23:02 +08:00
										 |  |  | 	"github.com/pkg/errors" | 
					
						
							| 
									
										
										
										
											2018-04-27 01:18:34 +08:00
										 |  |  | 	"github.com/projectatomic/libpod/pkg/secrets" | 
					
						
							| 
									
										
										
										
											2017-10-10 03:05:56 +08:00
										 |  |  | 	"github.com/sirupsen/logrus" | 
					
						
							|  |  |  | 	"golang.org/x/crypto/ssh/terminal" | 
					
						
							| 
									
										
										
										
											2017-02-14 05:12:02 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 	// DefaultWorkingDir is used if none was specified.
 | 
					
						
							|  |  |  | 	DefaultWorkingDir = "/" | 
					
						
							| 
									
										
										
										
											2017-02-18 02:54:49 +08:00
										 |  |  | 	// DefaultRuntime is the default command to use to run the container.
 | 
					
						
							|  |  |  | 	DefaultRuntime = "runc" | 
					
						
							| 
									
										
										
										
											2017-02-14 05:12:02 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-05 06:36:55 +08:00
										 |  |  | const ( | 
					
						
							| 
									
										
										
										
											2017-04-04 01:43:34 +08:00
										 |  |  | 	// DefaultTerminal indicates that this Run invocation should be
 | 
					
						
							|  |  |  | 	// connected to a pseudoterminal if we're connected to a terminal.
 | 
					
						
							| 
									
										
										
										
											2017-04-05 06:36:55 +08:00
										 |  |  | 	DefaultTerminal = iota | 
					
						
							| 
									
										
										
										
											2017-04-04 01:43:34 +08:00
										 |  |  | 	// WithoutTerminal indicates that this Run invocation should NOT be
 | 
					
						
							|  |  |  | 	// connected to a pseudoterminal.
 | 
					
						
							| 
									
										
										
										
											2017-04-05 06:36:55 +08:00
										 |  |  | 	WithoutTerminal | 
					
						
							| 
									
										
										
										
											2017-04-04 01:43:34 +08:00
										 |  |  | 	// WithTerminal indicates that this Run invocation should be connected
 | 
					
						
							|  |  |  | 	// to a pseudoterminal.
 | 
					
						
							| 
									
										
										
										
											2017-04-05 06:36:55 +08:00
										 |  |  | 	WithTerminal | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-14 05:12:02 +08:00
										 |  |  | // RunOptions can be used to alter how a command is run in the container.
 | 
					
						
							|  |  |  | type RunOptions struct { | 
					
						
							|  |  |  | 	// Hostname is the hostname we set for the running container.
 | 
					
						
							|  |  |  | 	Hostname string | 
					
						
							| 
									
										
										
										
											2017-02-18 02:54:49 +08:00
										 |  |  | 	// Runtime is the name of the command to run.  It should accept the same arguments that runc does.
 | 
					
						
							|  |  |  | 	Runtime string | 
					
						
							|  |  |  | 	// Args adds global arguments for the runtime.
 | 
					
						
							|  |  |  | 	Args []string | 
					
						
							| 
									
										
										
										
											2017-02-18 02:58:34 +08:00
										 |  |  | 	// Mounts are additional mount points which we want to provide.
 | 
					
						
							|  |  |  | 	Mounts []specs.Mount | 
					
						
							| 
									
										
										
										
											2017-03-28 02:46:35 +08:00
										 |  |  | 	// Env is additional environment variables to set.
 | 
					
						
							|  |  |  | 	Env []string | 
					
						
							|  |  |  | 	// User is the user as whom to run the command.
 | 
					
						
							|  |  |  | 	User string | 
					
						
							|  |  |  | 	// WorkingDir is an override for the working directory.
 | 
					
						
							|  |  |  | 	WorkingDir string | 
					
						
							| 
									
										
										
										
											2018-03-16 19:57:36 +08:00
										 |  |  | 	// Shell is default shell to run in a container.
 | 
					
						
							|  |  |  | 	Shell string | 
					
						
							| 
									
										
										
										
											2017-03-28 02:46:35 +08:00
										 |  |  | 	// Cmd is an override for the configured default command.
 | 
					
						
							|  |  |  | 	Cmd []string | 
					
						
							|  |  |  | 	// Entrypoint is an override for the configured entry point.
 | 
					
						
							|  |  |  | 	Entrypoint []string | 
					
						
							|  |  |  | 	// NetworkDisabled puts the container into its own network namespace.
 | 
					
						
							|  |  |  | 	NetworkDisabled bool | 
					
						
							| 
									
										
										
										
											2017-04-05 06:36:55 +08:00
										 |  |  | 	// Terminal provides a way to specify whether or not the command should
 | 
					
						
							|  |  |  | 	// be run with a pseudoterminal.  By default (DefaultTerminal), a
 | 
					
						
							|  |  |  | 	// terminal is used if os.Stdout is connected to a terminal, but that
 | 
					
						
							|  |  |  | 	// decision can be overridden by specifying either WithTerminal or
 | 
					
						
							|  |  |  | 	// WithoutTerminal.
 | 
					
						
							|  |  |  | 	Terminal int | 
					
						
							| 
									
										
										
										
											2018-01-24 00:17:31 +08:00
										 |  |  | 	// Quiet tells the run to turn off output to stdout.
 | 
					
						
							|  |  |  | 	Quiet bool | 
					
						
							| 
									
										
										
										
											2017-02-14 05:12:02 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-14 03:58:56 +08:00
										 |  |  | func addRlimits(ulimit []string, g *generate.Generator) error { | 
					
						
							|  |  |  | 	var ( | 
					
						
							|  |  |  | 		ul  *units.Ulimit | 
					
						
							|  |  |  | 		err error | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, u := range ulimit { | 
					
						
							|  |  |  | 		if ul, err = units.ParseUlimit(u); err != nil { | 
					
						
							|  |  |  | 			return errors.Wrapf(err, "ulimit option %q requires name=SOFT:HARD, failed to be parsed", u) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		g.AddProcessRlimits("RLIMIT_"+strings.ToUpper(ul.Name), uint64(ul.Hard), uint64(ul.Soft)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-20 19:31:51 +08:00
										 |  |  | func addHosts(hosts []string, w io.Writer) error { | 
					
						
							|  |  |  | 	buf := bufio.NewWriter(w) | 
					
						
							|  |  |  | 	for _, host := range hosts { | 
					
						
							|  |  |  | 		fmt.Fprintln(buf, host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return buf.Flush() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func addHostsToFile(hosts []string, filename string) error { | 
					
						
							| 
									
										
										
										
											2018-02-22 03:59:25 +08:00
										 |  |  | 	if len(hosts) == 0 { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-03-20 19:31:51 +08:00
										 |  |  | 	file, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, os.ModeAppend) | 
					
						
							| 
									
										
										
										
											2018-02-14 03:58:56 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer file.Close() | 
					
						
							| 
									
										
										
										
											2018-03-20 19:31:51 +08:00
										 |  |  | 	return addHosts(hosts, file) | 
					
						
							| 
									
										
										
										
											2018-02-14 03:58:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func addCommonOptsToSpec(commonOpts *CommonBuildOptions, g *generate.Generator) error { | 
					
						
							|  |  |  | 	// RESOURCES - CPU
 | 
					
						
							|  |  |  | 	if commonOpts.CPUPeriod != 0 { | 
					
						
							|  |  |  | 		g.SetLinuxResourcesCPUPeriod(commonOpts.CPUPeriod) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if commonOpts.CPUQuota != 0 { | 
					
						
							|  |  |  | 		g.SetLinuxResourcesCPUQuota(commonOpts.CPUQuota) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if commonOpts.CPUShares != 0 { | 
					
						
							|  |  |  | 		g.SetLinuxResourcesCPUShares(commonOpts.CPUShares) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if commonOpts.CPUSetCPUs != "" { | 
					
						
							|  |  |  | 		g.SetLinuxResourcesCPUCpus(commonOpts.CPUSetCPUs) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if commonOpts.CPUSetMems != "" { | 
					
						
							|  |  |  | 		g.SetLinuxResourcesCPUMems(commonOpts.CPUSetMems) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// RESOURCES - MEMORY
 | 
					
						
							|  |  |  | 	if commonOpts.Memory != 0 { | 
					
						
							|  |  |  | 		g.SetLinuxResourcesMemoryLimit(commonOpts.Memory) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if commonOpts.MemorySwap != 0 { | 
					
						
							|  |  |  | 		g.SetLinuxResourcesMemorySwap(commonOpts.MemorySwap) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if commonOpts.CgroupParent != "" { | 
					
						
							|  |  |  | 		g.SetLinuxCgroupsPath(commonOpts.CgroupParent) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err := addRlimits(commonOpts.Ulimit, g); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-03-20 19:31:51 +08:00
										 |  |  | 	if err := addHostsToFile(commonOpts.AddHost, "/etc/hosts"); err != nil { | 
					
						
							| 
									
										
										
										
											2018-02-14 03:58:56 +08:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	logrus.Debugln("Resources:", commonOpts) | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-23 01:41:22 +08:00
										 |  |  | func (b *Builder) setupMounts(mountPoint string, spec *specs.Spec, optionMounts []specs.Mount, bindFiles, builtinVolumes, volumeMounts []string, shmSize string) error { | 
					
						
							| 
									
										
										
										
											2017-05-24 06:04:13 +08:00
										 |  |  | 	// The passed-in mounts matter the most to us.
 | 
					
						
							|  |  |  | 	mounts := make([]specs.Mount, len(optionMounts)) | 
					
						
							|  |  |  | 	copy(mounts, optionMounts) | 
					
						
							|  |  |  | 	haveMount := func(destination string) bool { | 
					
						
							|  |  |  | 		for _, mount := range mounts { | 
					
						
							|  |  |  | 			if mount.Destination == destination { | 
					
						
							|  |  |  | 				// Already have something to mount there.
 | 
					
						
							|  |  |  | 				return true | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Add mounts from the generated list, unless they conflict.
 | 
					
						
							|  |  |  | 	for _, specMount := range spec.Mounts { | 
					
						
							| 
									
										
										
										
											2018-02-23 01:41:22 +08:00
										 |  |  | 		if specMount.Destination == "/dev/shm" { | 
					
						
							|  |  |  | 			specMount.Options = []string{"nosuid", "noexec", "nodev", "mode=1777", "size=" + shmSize} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-05-24 06:04:13 +08:00
										 |  |  | 		if haveMount(specMount.Destination) { | 
					
						
							|  |  |  | 			// Already have something to mount there, so skip this one.
 | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		mounts = append(mounts, specMount) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Add bind mounts for important files, unless they conflict.
 | 
					
						
							|  |  |  | 	for _, boundFile := range bindFiles { | 
					
						
							|  |  |  | 		if haveMount(boundFile) { | 
					
						
							|  |  |  | 			// Already have something to mount there, so skip this one.
 | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		mounts = append(mounts, specs.Mount{ | 
					
						
							|  |  |  | 			Source:      boundFile, | 
					
						
							|  |  |  | 			Destination: boundFile, | 
					
						
							|  |  |  | 			Type:        "bind", | 
					
						
							|  |  |  | 			Options:     []string{"rbind", "ro"}, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-08 06:44:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	cdir, err := b.store.ContainerDirectory(b.ContainerID) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return errors.Wrapf(err, "error determining work directory for container %q", b.ContainerID) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Add secrets mounts
 | 
					
						
							| 
									
										
										
										
											2018-04-27 01:18:34 +08:00
										 |  |  | 	secretMounts := secrets.SecretMounts(b.MountLabel, cdir, b.DefaultMountsFilePath) | 
					
						
							|  |  |  | 	for _, mount := range secretMounts { | 
					
						
							|  |  |  | 		if haveMount(mount.Destination) { | 
					
						
							| 
									
										
										
										
											2018-01-04 04:40:55 +08:00
										 |  |  | 			continue | 
					
						
							| 
									
										
										
										
											2017-11-08 06:44:24 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-04-27 01:18:34 +08:00
										 |  |  | 		mounts = append(mounts, mount) | 
					
						
							| 
									
										
										
										
											2017-11-08 06:44:24 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-04-27 01:18:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-21 05:37:50 +08:00
										 |  |  | 	// Add temporary copies of the contents of volume locations at the
 | 
					
						
							|  |  |  | 	// volume locations, unless we already have something there.
 | 
					
						
							| 
									
										
										
										
											2018-02-23 01:41:22 +08:00
										 |  |  | 	for _, volume := range builtinVolumes { | 
					
						
							| 
									
										
										
										
											2017-05-24 06:04:13 +08:00
										 |  |  | 		if haveMount(volume) { | 
					
						
							| 
									
										
										
										
											2017-06-21 05:37:50 +08:00
										 |  |  | 			// Already mounting something there, no need to bother.
 | 
					
						
							| 
									
										
										
										
											2017-05-24 06:04:13 +08:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-06-21 05:37:50 +08:00
										 |  |  | 		subdir := digest.Canonical.FromString(volume).Hex() | 
					
						
							|  |  |  | 		volumePath := filepath.Join(cdir, "buildah-volumes", subdir) | 
					
						
							|  |  |  | 		// If we need to, initialize the volume path's initial contents.
 | 
					
						
							|  |  |  | 		if _, err = os.Stat(volumePath); os.IsNotExist(err) { | 
					
						
							|  |  |  | 			if err = os.MkdirAll(volumePath, 0755); err != nil { | 
					
						
							|  |  |  | 				return errors.Wrapf(err, "error creating directory %q for volume %q in container %q", volumePath, volume, b.ContainerID) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-11-29 03:22:47 +08:00
										 |  |  | 			if err = label.Relabel(volumePath, b.MountLabel, false); err != nil { | 
					
						
							|  |  |  | 				return errors.Wrapf(err, "error relabeling directory %q for volume %q in container %q", volumePath, volume, b.ContainerID) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-06-21 05:37:50 +08:00
										 |  |  | 			srcPath := filepath.Join(mountPoint, volume) | 
					
						
							| 
									
										
										
										
											2018-02-12 23:17:25 +08:00
										 |  |  | 			if err = copyWithTar(srcPath, volumePath); err != nil && !os.IsNotExist(err) { | 
					
						
							| 
									
										
										
										
											2017-06-21 05:37:50 +08:00
										 |  |  | 				return errors.Wrapf(err, "error populating directory %q for volume %q in container %q using contents of %q", volumePath, volume, b.ContainerID, srcPath) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// Add the bind mount.
 | 
					
						
							| 
									
										
										
										
											2017-05-24 06:04:13 +08:00
										 |  |  | 		mounts = append(mounts, specs.Mount{ | 
					
						
							| 
									
										
										
										
											2017-06-21 05:37:50 +08:00
										 |  |  | 			Source:      volumePath, | 
					
						
							| 
									
										
										
										
											2017-05-24 06:04:13 +08:00
										 |  |  | 			Destination: volume, | 
					
						
							| 
									
										
										
										
											2017-06-21 05:37:50 +08:00
										 |  |  | 			Type:        "bind", | 
					
						
							|  |  |  | 			Options:     []string{"bind"}, | 
					
						
							| 
									
										
										
										
											2017-05-24 06:04:13 +08:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-02-23 01:41:22 +08:00
										 |  |  | 	// Bind mount volumes given by the user at execution
 | 
					
						
							|  |  |  | 	var options []string | 
					
						
							|  |  |  | 	for _, i := range volumeMounts { | 
					
						
							|  |  |  | 		spliti := strings.Split(i, ":") | 
					
						
							|  |  |  | 		if len(spliti) > 2 { | 
					
						
							|  |  |  | 			options = strings.Split(spliti[2], ",") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if haveMount(spliti[1]) { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		options = append(options, "rbind") | 
					
						
							|  |  |  | 		var foundrw, foundro, foundz, foundZ bool | 
					
						
							|  |  |  | 		var rootProp string | 
					
						
							|  |  |  | 		for _, opt := range options { | 
					
						
							|  |  |  | 			switch opt { | 
					
						
							|  |  |  | 			case "rw": | 
					
						
							|  |  |  | 				foundrw = true | 
					
						
							|  |  |  | 			case "ro": | 
					
						
							|  |  |  | 				foundro = true | 
					
						
							|  |  |  | 			case "z": | 
					
						
							|  |  |  | 				foundz = true | 
					
						
							|  |  |  | 			case "Z": | 
					
						
							|  |  |  | 				foundZ = true | 
					
						
							|  |  |  | 			case "private", "rprivate", "slave", "rslave", "shared", "rshared": | 
					
						
							|  |  |  | 				rootProp = opt | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if !foundrw && !foundro { | 
					
						
							|  |  |  | 			options = append(options, "rw") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if foundz { | 
					
						
							|  |  |  | 			if err := label.Relabel(spliti[0], spec.Linux.MountLabel, true); err != nil { | 
					
						
							|  |  |  | 				return errors.Wrapf(err, "relabel failed %q", spliti[0]) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if foundZ { | 
					
						
							|  |  |  | 			if err := label.Relabel(spliti[0], spec.Linux.MountLabel, false); err != nil { | 
					
						
							|  |  |  | 				return errors.Wrapf(err, "relabel failed %q", spliti[0]) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if rootProp == "" { | 
					
						
							|  |  |  | 			options = append(options, "private") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		mounts = append(mounts, specs.Mount{ | 
					
						
							|  |  |  | 			Destination: spliti[1], | 
					
						
							|  |  |  | 			Type:        "bind", | 
					
						
							|  |  |  | 			Source:      spliti[0], | 
					
						
							|  |  |  | 			Options:     options, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-24 06:04:13 +08:00
										 |  |  | 	// Set the list in the spec.
 | 
					
						
							|  |  |  | 	spec.Mounts = mounts | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-14 05:12:02 +08:00
										 |  |  | // Run runs the specified command in the container's root filesystem.
 | 
					
						
							|  |  |  | func (b *Builder) Run(command []string, options RunOptions) error { | 
					
						
							| 
									
										
										
										
											2017-03-28 02:46:35 +08:00
										 |  |  | 	var user specs.User | 
					
						
							| 
									
										
										
										
											2017-02-14 05:12:02 +08:00
										 |  |  | 	path, err := ioutil.TempDir(os.TempDir(), Package) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	logrus.Debugf("using %q to hold bundle data", path) | 
					
						
							|  |  |  | 	defer func() { | 
					
						
							|  |  |  | 		if err2 := os.RemoveAll(path); err2 != nil { | 
					
						
							|  |  |  | 			logrus.Errorf("error removing %q: %v", path, err2) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 	g := generate.New() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												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
										 |  |  | 	for _, envSpec := range append(b.Env(), options.Env...) { | 
					
						
							| 
									
										
										
										
											2017-02-14 05:12:02 +08:00
										 |  |  | 		env := strings.SplitN(envSpec, "=", 2) | 
					
						
							|  |  |  | 		if len(env) > 1 { | 
					
						
							|  |  |  | 			g.AddProcessEnv(env[0], env[1]) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-02-14 03:58:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 07:43:36 +08:00
										 |  |  | 	if b.CommonBuildOpts == nil { | 
					
						
							|  |  |  | 		return errors.Errorf("Invalid format on container you must recreate the container") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-14 03:58:56 +08:00
										 |  |  | 	if err := addCommonOptsToSpec(b.CommonBuildOpts, &g); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-14 05:12:02 +08:00
										 |  |  | 	if len(command) > 0 { | 
					
						
							| 
									
										
										
										
											2018-04-24 06:15:58 +08:00
										 |  |  | 		g.SetProcessArgs(command) | 
					
						
							| 
									
										
										
										
											2017-06-23 23:53:51 +08:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		cmd := b.Cmd() | 
					
						
							|  |  |  | 		if len(options.Cmd) > 0 { | 
					
						
							|  |  |  | 			cmd = options.Cmd | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-04-24 06:15:58 +08:00
										 |  |  | 		entrypoint := b.Entrypoint() | 
					
						
							|  |  |  | 		if len(options.Entrypoint) > 0 { | 
					
						
							|  |  |  | 			entrypoint = options.Entrypoint | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-04-11 23:20:56 +08:00
										 |  |  | 		g.SetProcessArgs(append(entrypoint, cmd...)) | 
					
						
							| 
									
										
										
										
											2017-02-14 05:12:02 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-03-28 02:46:35 +08:00
										 |  |  | 	if options.WorkingDir != "" { | 
					
						
							|  |  |  | 		g.SetProcessCwd(options.WorkingDir) | 
					
						
							| 
									
										
										
											
												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
										 |  |  | 	} else if b.WorkDir() != "" { | 
					
						
							|  |  |  | 		g.SetProcessCwd(b.WorkDir()) | 
					
						
							| 
									
										
										
										
											2017-02-14 05:12:02 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if options.Hostname != "" { | 
					
						
							|  |  |  | 		g.SetHostname(options.Hostname) | 
					
						
							| 
									
										
										
										
											2017-05-24 06:03:19 +08:00
										 |  |  | 	} else if b.Hostname() != "" { | 
					
						
							|  |  |  | 		g.SetHostname(b.Hostname()) | 
					
						
							| 
									
										
										
										
											2017-02-14 05:12:02 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-10-20 05:47:15 +08:00
										 |  |  | 	g.SetProcessSelinuxLabel(b.ProcessLabel) | 
					
						
							|  |  |  | 	g.SetLinuxMountLabel(b.MountLabel) | 
					
						
							|  |  |  | 	mountPoint, err := b.Mount(b.MountLabel) | 
					
						
							| 
									
										
										
										
											2017-02-14 05:12:02 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer func() { | 
					
						
							|  |  |  | 		if err2 := b.Unmount(); err2 != nil { | 
					
						
							|  |  |  | 			logrus.Errorf("error unmounting container: %v", err2) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							| 
									
										
										
										
											2017-11-22 22:42:16 +08:00
										 |  |  | 	for _, mp := range []string{ | 
					
						
							|  |  |  | 		"/proc/kcore", | 
					
						
							|  |  |  | 		"/proc/latency_stats", | 
					
						
							|  |  |  | 		"/proc/timer_list", | 
					
						
							|  |  |  | 		"/proc/timer_stats", | 
					
						
							|  |  |  | 		"/proc/sched_debug", | 
					
						
							|  |  |  | 		"/proc/scsi", | 
					
						
							|  |  |  | 		"/sys/firmware", | 
					
						
							|  |  |  | 	} { | 
					
						
							|  |  |  | 		g.AddLinuxMaskedPaths(mp) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, rp := range []string{ | 
					
						
							|  |  |  | 		"/proc/asound", | 
					
						
							|  |  |  | 		"/proc/bus", | 
					
						
							|  |  |  | 		"/proc/fs", | 
					
						
							|  |  |  | 		"/proc/irq", | 
					
						
							|  |  |  | 		"/proc/sys", | 
					
						
							|  |  |  | 		"/proc/sysrq-trigger", | 
					
						
							|  |  |  | 	} { | 
					
						
							|  |  |  | 		g.AddLinuxReadonlyPaths(rp) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-02-14 05:12:02 +08:00
										 |  |  | 	g.SetRootPath(mountPoint) | 
					
						
							| 
									
										
										
										
											2017-04-05 06:36:55 +08:00
										 |  |  | 	switch options.Terminal { | 
					
						
							|  |  |  | 	case DefaultTerminal: | 
					
						
							| 
									
										
										
										
											2017-10-10 03:05:56 +08:00
										 |  |  | 		g.SetProcessTerminal(terminal.IsTerminal(int(os.Stdout.Fd()))) | 
					
						
							| 
									
										
										
										
											2017-04-05 06:36:55 +08:00
										 |  |  | 	case WithTerminal: | 
					
						
							|  |  |  | 		g.SetProcessTerminal(true) | 
					
						
							|  |  |  | 	case WithoutTerminal: | 
					
						
							|  |  |  | 		g.SetProcessTerminal(false) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-03-28 02:46:35 +08:00
										 |  |  | 	if !options.NetworkDisabled { | 
					
						
							| 
									
										
										
										
											2017-04-04 05:44:23 +08:00
										 |  |  | 		if err = g.RemoveLinuxNamespace("network"); err != nil { | 
					
						
							| 
									
										
										
										
											2017-06-02 03:23:02 +08:00
										 |  |  | 			return errors.Wrapf(err, "error removing network namespace for run") | 
					
						
							| 
									
										
										
										
											2017-04-04 05:44:23 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-03-28 02:46:35 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-01-03 21:26:18 +08:00
										 |  |  | 	user, err = b.user(mountPoint, options.User) | 
					
						
							| 
									
										
										
										
											2017-04-05 05:31:02 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	g.SetProcessUID(user.UID) | 
					
						
							|  |  |  | 	g.SetProcessGID(user.GID) | 
					
						
							| 
									
										
										
										
											2017-02-14 05:12:02 +08:00
										 |  |  | 	spec := g.Spec() | 
					
						
							|  |  |  | 	if spec.Process.Cwd == "" { | 
					
						
							|  |  |  | 		spec.Process.Cwd = DefaultWorkingDir | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-11 04:08:03 +08:00
										 |  |  | 	if err = os.MkdirAll(filepath.Join(mountPoint, spec.Process.Cwd), 0755); err != nil { | 
					
						
							|  |  |  | 		return errors.Wrapf(err, "error ensuring working directory %q exists", spec.Process.Cwd) | 
					
						
							| 
									
										
										
										
											2017-03-24 01:47:07 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-24 06:04:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-14 03:58:56 +08:00
										 |  |  | 	//Security Opts
 | 
					
						
							|  |  |  | 	g.SetProcessApparmorProfile(b.CommonBuildOpts.ApparmorProfile) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// HANDLE SECCOMP
 | 
					
						
							|  |  |  | 	if b.CommonBuildOpts.SeccompProfilePath != "unconfined" { | 
					
						
							|  |  |  | 		if b.CommonBuildOpts.SeccompProfilePath != "" { | 
					
						
							|  |  |  | 			seccompProfile, err := ioutil.ReadFile(b.CommonBuildOpts.SeccompProfilePath) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return errors.Wrapf(err, "opening seccomp profile (%s) failed", b.CommonBuildOpts.SeccompProfilePath) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			seccompConfig, err := seccomp.LoadProfile(string(seccompProfile), spec) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return errors.Wrapf(err, "loading seccomp profile (%s) failed", b.CommonBuildOpts.SeccompProfilePath) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			spec.Linux.Seccomp = seccompConfig | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			seccompConfig, err := seccomp.GetDefaultProfile(spec) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return errors.Wrapf(err, "loading seccomp profile (%s) failed", b.CommonBuildOpts.SeccompProfilePath) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			spec.Linux.Seccomp = seccompConfig | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cgroupMnt := specs.Mount{ | 
					
						
							|  |  |  | 		Destination: "/sys/fs/cgroup", | 
					
						
							|  |  |  | 		Type:        "cgroup", | 
					
						
							|  |  |  | 		Source:      "cgroup", | 
					
						
							|  |  |  | 		Options:     []string{"nosuid", "noexec", "nodev", "relatime", "ro"}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	g.AddMount(cgroupMnt) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 06:04:13 +08:00
										 |  |  | 	bindFiles := []string{"/etc/hosts", "/etc/resolv.conf"} | 
					
						
							| 
									
										
										
										
											2018-02-23 01:41:22 +08:00
										 |  |  | 	err = b.setupMounts(mountPoint, spec, options.Mounts, bindFiles, b.Volumes(), b.CommonBuildOpts.Volumes, b.CommonBuildOpts.ShmSize) | 
					
						
							| 
									
										
										
										
											2017-05-24 06:04:13 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2017-06-02 03:23:02 +08:00
										 |  |  | 		return errors.Wrapf(err, "error resolving mountpoints for container") | 
					
						
							| 
									
										
										
										
											2017-02-18 02:58:34 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-02-14 05:12:02 +08:00
										 |  |  | 	specbytes, err := json.Marshal(spec) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	err = ioutils.AtomicWriteFile(filepath.Join(path, "config.json"), specbytes, 0600) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2017-06-02 03:23:02 +08:00
										 |  |  | 		return errors.Wrapf(err, "error storing runtime configuration") | 
					
						
							| 
									
										
										
										
											2017-02-14 05:12:02 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	logrus.Debugf("config = %v", string(specbytes)) | 
					
						
							| 
									
										
										
										
											2017-02-18 02:54:49 +08:00
										 |  |  | 	runtime := options.Runtime | 
					
						
							|  |  |  | 	if runtime == "" { | 
					
						
							|  |  |  | 		runtime = DefaultRuntime | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	args := append(options.Args, "run", "-b", path, Package+"-"+b.ContainerID) | 
					
						
							|  |  |  | 	cmd := exec.Command(runtime, args...) | 
					
						
							| 
									
										
										
										
											2017-02-14 05:12:02 +08:00
										 |  |  | 	cmd.Dir = mountPoint | 
					
						
							|  |  |  | 	cmd.Stdin = os.Stdin | 
					
						
							|  |  |  | 	cmd.Stdout = os.Stdout | 
					
						
							| 
									
										
										
										
											2018-01-24 00:17:31 +08:00
										 |  |  | 	if options.Quiet { | 
					
						
							|  |  |  | 		cmd.Stdout = nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-02-14 05:12:02 +08:00
										 |  |  | 	cmd.Stderr = os.Stderr | 
					
						
							|  |  |  | 	err = cmd.Run() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		logrus.Debugf("error running runc %v: %v", spec.Process.Args, err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return err | 
					
						
							|  |  |  | } |