diff options
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/podman/common/create_opts.go | 39 | ||||
-rw-r--r-- | cmd/podman/common/netflags.go | 2 | ||||
-rw-r--r-- | cmd/podman/common/volumes.go | 36 | ||||
-rw-r--r-- | cmd/podman/containers/cp.go | 54 | ||||
-rw-r--r-- | cmd/podman/containers/create.go | 6 | ||||
-rw-r--r-- | cmd/podman/images/build.go | 96 | ||||
-rw-r--r-- | cmd/podman/root.go | 19 |
7 files changed, 155 insertions, 97 deletions
diff --git a/cmd/podman/common/create_opts.go b/cmd/podman/common/create_opts.go index 78611371d..a296ef4f1 100644 --- a/cmd/podman/common/create_opts.go +++ b/cmd/podman/common/create_opts.go @@ -3,6 +3,7 @@ package common import ( "fmt" "net" + "os" "path/filepath" "strconv" "strings" @@ -13,6 +14,7 @@ import ( "github.com/containers/podman/v3/pkg/domain/entities" "github.com/containers/podman/v3/pkg/rootless" "github.com/containers/podman/v3/pkg/specgen" + "github.com/pkg/errors" ) type ContainerCLIOpts struct { @@ -311,6 +313,15 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, cgroup netInfo.CNINetworks = []string{string(cc.HostConfig.NetworkMode)} } + parsedTmp := make([]string, 0, len(cc.HostConfig.Tmpfs)) + for path, options := range cc.HostConfig.Tmpfs { + finalString := path + if options != "" { + finalString += ":" + options + } + parsedTmp = append(parsedTmp, finalString) + } + // Note: several options here are marked as "don't need". this is based // on speculation by Matt and I. We think that these come into play later // like with start. We believe this is just a difference in podman/compat @@ -367,7 +378,7 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, cgroup StorageOpt: stringMaptoArray(cc.HostConfig.StorageOpt), Sysctl: stringMaptoArray(cc.HostConfig.Sysctls), Systemd: "true", // podman default - TmpFS: stringMaptoArray(cc.HostConfig.Tmpfs), + TmpFS: parsedTmp, TTY: cc.Config.Tty, User: cc.Config.User, UserNS: string(cc.HostConfig.UsernsMode), @@ -386,8 +397,16 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, cgroup cliOpts.Ulimit = ulimits } } + if cc.HostConfig.Resources.NanoCPUs > 0 { + if cliOpts.CPUPeriod != 0 || cliOpts.CPUQuota != 0 { + return nil, nil, errors.Errorf("NanoCpus conflicts with CpuPeriod and CpuQuota") + } + cliOpts.CPUPeriod = 100000 + cliOpts.CPUQuota = cc.HostConfig.Resources.NanoCPUs / 10000 + } // volumes + volSources := make(map[string]bool) volDestinations := make(map[string]bool) for _, vol := range cc.HostConfig.Binds { cliOpts.Volume = append(cliOpts.Volume, vol) @@ -398,6 +417,7 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, cgroup case 1: volDestinations[vol] = true default: + volSources[splitVol[0]] = true volDestinations[splitVol[1]] = true } } @@ -412,6 +432,23 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, cgroup } cliOpts.Volume = append(cliOpts.Volume, vol) } + // Make mount points for compat volumes + for vol := range volSources { + // This might be a named volume. + // Assume it is if it's not an absolute path. + if !filepath.IsAbs(vol) { + continue + } + // If volume already exists, there is nothing to do + if _, err := os.Stat(vol); err == nil { + continue + } + if err := os.MkdirAll(vol, 0755); err != nil { + if !os.IsExist(err) { + return nil, nil, errors.Wrapf(err, "error making volume mountpoint for volume %s", vol) + } + } + } if len(cc.HostConfig.BlkioWeightDevice) > 0 { devices := make([]string, 0, len(cc.HostConfig.BlkioWeightDevice)) for _, d := range cc.HostConfig.BlkioWeightDevice { diff --git a/cmd/podman/common/netflags.go b/cmd/podman/common/netflags.go index bc4d54de0..4d0a554a6 100644 --- a/cmd/podman/common/netflags.go +++ b/cmd/podman/common/netflags.go @@ -80,7 +80,7 @@ func DefineNetFlags(cmd *cobra.Command) { _ = cmd.RegisterFlagCompletionFunc(publishFlagName, completion.AutocompleteNone) netFlags.Bool( - "no-hosts", false, + "no-hosts", containerConfig.Containers.NoHosts, "Do not create /etc/hosts within the container, instead use the version from the image", ) } diff --git a/cmd/podman/common/volumes.go b/cmd/podman/common/volumes.go index 19a49a6f2..aff323936 100644 --- a/cmd/podman/common/volumes.go +++ b/cmd/podman/common/volumes.go @@ -6,23 +6,13 @@ import ( "strings" "github.com/containers/common/pkg/parse" + "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/specgen" "github.com/containers/podman/v3/pkg/util" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" ) -const ( - // TypeBind is the type for mounting host dir - TypeBind = "bind" - // TypeVolume is the type for named volumes - TypeVolume = "volume" - // TypeTmpfs is the type for mounting tmpfs - TypeTmpfs = "tmpfs" - // TypeDevpts is the type for creating a devpts - TypeDevpts = "devpts" -) - var ( errDuplicateDest = errors.Errorf("duplicate mount destination") optionArgError = errors.Errorf("must provide an argument for option") @@ -90,7 +80,7 @@ func parseVolumes(volumeFlag, mountFlag, tmpfsFlag []string, addReadOnlyTmpfs bo } unifiedMounts[dest] = spec.Mount{ Destination: dest, - Type: TypeTmpfs, + Type: define.TypeTmpfs, Source: "tmpfs", Options: options, } @@ -131,7 +121,7 @@ func parseVolumes(volumeFlag, mountFlag, tmpfsFlag []string, addReadOnlyTmpfs bo // Final step: maps to arrays finalMounts := make([]spec.Mount, 0, len(unifiedMounts)) for _, mount := range unifiedMounts { - if mount.Type == TypeBind { + if mount.Type == define.TypeBind { absSrc, err := filepath.Abs(mount.Source) if err != nil { return nil, nil, nil, nil, errors.Wrapf(err, "error getting absolute path of %s", mount.Source) @@ -194,7 +184,7 @@ func getMounts(mountFlag []string) (map[string]spec.Mount, map[string]*specgen.N return nil, nil, nil, err } switch mountType { - case TypeBind: + case define.TypeBind: mount, err := getBindMount(tokens) if err != nil { return nil, nil, nil, err @@ -203,7 +193,7 @@ func getMounts(mountFlag []string) (map[string]spec.Mount, map[string]*specgen.N return nil, nil, nil, errors.Wrapf(errDuplicateDest, mount.Destination) } finalMounts[mount.Destination] = mount - case TypeTmpfs: + case define.TypeTmpfs: mount, err := getTmpfsMount(tokens) if err != nil { return nil, nil, nil, err @@ -212,7 +202,7 @@ func getMounts(mountFlag []string) (map[string]spec.Mount, map[string]*specgen.N return nil, nil, nil, errors.Wrapf(errDuplicateDest, mount.Destination) } finalMounts[mount.Destination] = mount - case TypeDevpts: + case define.TypeDevpts: mount, err := getDevptsMount(tokens) if err != nil { return nil, nil, nil, err @@ -250,7 +240,7 @@ func getMounts(mountFlag []string) (map[string]spec.Mount, map[string]*specgen.N // Parse a single bind mount entry from the --mount flag. func getBindMount(args []string) (spec.Mount, error) { newMount := spec.Mount{ - Type: TypeBind, + Type: define.TypeBind, } var setSource, setDest, setRORW, setSuid, setDev, setExec, setRelabel bool @@ -381,8 +371,8 @@ func getBindMount(args []string) (spec.Mount, error) { // Parse a single tmpfs mount entry from the --mount flag func getTmpfsMount(args []string) (spec.Mount, error) { newMount := spec.Mount{ - Type: TypeTmpfs, - Source: TypeTmpfs, + Type: define.TypeTmpfs, + Source: define.TypeTmpfs, } var setDest, setRORW, setSuid, setDev, setExec, setTmpcopyup bool @@ -460,8 +450,8 @@ func getTmpfsMount(args []string) (spec.Mount, error) { // Parse a single devpts mount entry from the --mount flag func getDevptsMount(args []string) (spec.Mount, error) { newMount := spec.Mount{ - Type: TypeDevpts, - Source: TypeDevpts, + Type: define.TypeDevpts, + Source: define.TypeDevpts, } var setDest bool @@ -630,9 +620,9 @@ func getTmpfsMounts(tmpfsFlag []string) (map[string]spec.Mount, error) { mount := spec.Mount{ Destination: filepath.Clean(destPath), - Type: string(TypeTmpfs), + Type: string(define.TypeTmpfs), Options: options, - Source: string(TypeTmpfs), + Source: string(define.TypeTmpfs), } m[destPath] = mount } diff --git a/cmd/podman/containers/cp.go b/cmd/podman/containers/cp.go index 7887e9539..27aacc6e5 100644 --- a/cmd/podman/containers/cp.go +++ b/cmd/podman/containers/cp.go @@ -160,6 +160,25 @@ func copyFromContainer(container string, containerPath string, hostPath string) } } + // If we copy a directory via the "." notation and the host path does + // not exist, we need to make sure that the destination on the host + // gets created; otherwise the contents of the source directory will be + // written to the destination's parent directory. + // + // While we could cut it short on the host and do create the directory + // ourselves, we would run into problems trying to that the other way + // around when copying into a container. Instead, to keep both + // implementations symmetrical, we need to massage the code a bit to + // let Buildah's copier package create the destination. + // + // Hence, whenever "." is the source and the destination does not exist, + // we copy the source's parent and let the copier package create the + // destination via the Rename option. + containerTarget := containerInfo.LinkTarget + if hostInfoErr != nil && containerInfo.IsDir && strings.HasSuffix(containerTarget, ".") { + containerTarget = filepath.Dir(containerTarget) + } + reader, writer := io.Pipe() hostCopy := func() error { defer reader.Close() @@ -189,13 +208,14 @@ func copyFromContainer(container string, containerPath string, hostPath string) } putOptions := buildahCopiah.PutOptions{ - ChownDirs: &idPair, - ChownFiles: &idPair, + ChownDirs: &idPair, + ChownFiles: &idPair, + IgnoreDevices: true, } - if !containerInfo.IsDir && (!hostInfo.IsDir || hostInfoErr != nil) { + if (!containerInfo.IsDir && !hostInfo.IsDir) || hostInfoErr != nil { // If we're having a file-to-file copy, make sure to // rename accordingly. - putOptions.Rename = map[string]string{filepath.Base(containerInfo.LinkTarget): hostBaseName} + putOptions.Rename = map[string]string{filepath.Base(containerTarget): hostBaseName} } dir := hostInfo.LinkTarget if !hostInfo.IsDir { @@ -209,7 +229,7 @@ func copyFromContainer(container string, containerPath string, hostPath string) containerCopy := func() error { defer writer.Close() - copyFunc, err := registry.ContainerEngine().ContainerCopyToArchive(registry.GetContext(), container, containerInfo.LinkTarget, writer) + copyFunc, err := registry.ContainerEngine().ContainerCopyToArchive(registry.GetContext(), container, containerTarget, writer) if err != nil { return err } @@ -277,6 +297,19 @@ func copyToContainer(container string, containerPath string, hostPath string) er containerBaseName = filepath.Base(containerInfo.LinkTarget) } + // If we copy a directory via the "." notation and the container path + // does not exist, we need to make sure that the destination on the + // container gets created; otherwise the contents of the source + // directory will be written to the destination's parent directory. + // + // Hence, whenever "." is the source and the destination does not + // exist, we copy the source's parent and let the copier package create + // the destination via the Rename option. + hostTarget := hostInfo.LinkTarget + if containerInfoErr != nil && hostInfo.IsDir && strings.HasSuffix(hostTarget, ".") { + hostTarget = filepath.Dir(hostTarget) + } + var stdinFile string if isStdin { if !containerInfo.IsDir { @@ -317,15 +350,16 @@ func copyToContainer(container string, containerPath string, hostPath string) er } getOptions := buildahCopiah.GetOptions{ - // Unless the specified points to ".", we want to copy the base directory. - KeepDirectoryNames: hostInfo.IsDir && filepath.Base(hostPath) != ".", + // Unless the specified path points to ".", we want to + // copy the base directory. + KeepDirectoryNames: hostInfo.IsDir && filepath.Base(hostTarget) != ".", } - if !hostInfo.IsDir && (!containerInfo.IsDir || containerInfoErr != nil) { + if (!hostInfo.IsDir && !containerInfo.IsDir) || containerInfoErr != nil { // If we're having a file-to-file copy, make sure to // rename accordingly. - getOptions.Rename = map[string]string{filepath.Base(hostInfo.LinkTarget): containerBaseName} + getOptions.Rename = map[string]string{filepath.Base(hostTarget): containerBaseName} } - if err := buildahCopiah.Get("/", "", getOptions, []string{hostInfo.LinkTarget}, writer); err != nil { + if err := buildahCopiah.Get("/", "", getOptions, []string{hostTarget}, writer); err != nil { return errors.Wrap(err, "error copying from host") } return nil diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go index d7507775f..af9278ce1 100644 --- a/cmd/podman/containers/create.go +++ b/cmd/podman/containers/create.go @@ -166,7 +166,11 @@ func createInit(c *cobra.Command) error { return errors.Errorf("--cpu-quota and --cpus cannot be set together") } - if c.Flag("no-hosts").Changed && c.Flag("add-host").Changed { + noHosts, err := c.Flags().GetBool("no-hosts") + if err != nil { + return err + } + if noHosts && c.Flag("add-host").Changed { return errors.Errorf("--no-hosts and --add-host cannot be set together") } cliVals.UserNS = c.Flag("userns").Value.String() diff --git a/cmd/podman/images/build.go b/cmd/podman/images/build.go index d6bf761db..3b34a6bf6 100644 --- a/cmd/podman/images/build.go +++ b/cmd/podman/images/build.go @@ -2,6 +2,7 @@ package images import ( "io" + "io/ioutil" "os" "path/filepath" "strings" @@ -19,7 +20,6 @@ import ( "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/cmd/podman/utils" "github.com/containers/podman/v3/pkg/domain/entities" - "github.com/docker/go-units" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -170,6 +170,7 @@ func buildFlags(cmd *cobra.Command) { _ = flags.MarkHidden("signature-policy") _ = flags.MarkHidden("tls-verify") _ = flags.MarkHidden("compress") + _ = flags.MarkHidden("volume") } } @@ -265,6 +266,9 @@ func build(cmd *cobra.Command, args []string) error { } report, err := registry.ImageEngine().Build(registry.GetContext(), containerFiles, *apiBuildOpts) + if err != nil { + return err + } if cmd.Flag("iidfile").Changed { f, err := os.Create(buildOpts.Iidfile) @@ -276,7 +280,7 @@ func build(cmd *cobra.Command, args []string) error { } } - return err + return nil } // buildFlagsWrapperToOptions converts the local build flags to the build options used @@ -295,6 +299,11 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *buil } } + commonOpts, err := parse.CommonBuildOptions(c) + if err != nil { + return nil, err + } + pullPolicy := imagebuildah.PullIfMissing if c.Flags().Changed("pull") && flags.Pull { pullPolicy = imagebuildah.PullAlways @@ -314,7 +323,12 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *buil if len(av) > 1 { args[av[0]] = av[1] } else { - delete(args, av[0]) + // check if the env is set in the local environment and use that value if it is + if val, present := os.LookupEnv(av[0]); present { + args[av[0]] = val + } else { + delete(args, av[0]) + } } } } @@ -353,22 +367,6 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *buil reporter = logfile } - var memoryLimit, memorySwap int64 - var err error - if c.Flags().Changed("memory") { - memoryLimit, err = units.RAMInBytes(flags.Memory) - if err != nil { - return nil, err - } - } - - if c.Flags().Changed("memory-swap") { - memorySwap, err = units.RAMInBytes(flags.MemorySwap) - if err != nil { - return nil, err - } - } - nsValues, networkPolicy, err := parse.NamespaceOptions(c) if err != nil { return nil, err @@ -446,29 +444,15 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *buil } opts := imagebuildah.BuildOptions{ - AddCapabilities: flags.CapAdd, - AdditionalTags: tags, - Annotations: flags.Annotation, - Architecture: arch, - Args: args, - BlobDirectory: flags.BlobCache, - CNIConfigDir: flags.CNIConfigDir, - CNIPluginPath: flags.CNIPlugInPath, - CommonBuildOpts: &buildah.CommonBuildOptions{ - AddHost: flags.AddHost, - CPUPeriod: flags.CPUPeriod, - CPUQuota: flags.CPUQuota, - CPUSetCPUs: flags.CPUSetCPUs, - CPUSetMems: flags.CPUSetMems, - CPUShares: flags.CPUShares, - CgroupParent: flags.CgroupParent, - HTTPProxy: flags.HTTPProxy, - Memory: memoryLimit, - MemorySwap: memorySwap, - ShmSize: flags.ShmSize, - Ulimit: flags.Ulimit, - Volumes: flags.Volumes, - }, + AddCapabilities: flags.CapAdd, + AdditionalTags: tags, + Annotations: flags.Annotation, + Architecture: arch, + Args: args, + BlobDirectory: flags.BlobCache, + CNIConfigDir: flags.CNIConfigDir, + CNIPluginPath: flags.CNIPlugInPath, + CommonBuildOpts: commonOpts, Compression: compression, ConfigureNetwork: networkPolicy, ContextDirectory: contextDir, @@ -509,6 +493,19 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *buil TransientMounts: flags.Volumes, } + if flags.IgnoreFile != "" { + excludes, err := parseDockerignore(flags.IgnoreFile) + if err != nil { + return nil, errors.Wrapf(err, "unable to obtain decrypt config") + } + opts.Excludes = excludes + } + + if c.Flag("timestamp").Changed { + timestamp := time.Unix(flags.Timestamp, 0).UTC() + opts.Timestamp = ×tamp + } + return &entities.BuildOptions{BuildOptions: opts}, nil } @@ -526,3 +523,18 @@ func getDecryptConfig(decryptionKeys []string) (*encconfig.DecryptConfig, error) return decConfig, nil } + +func parseDockerignore(ignoreFile string) ([]string, error) { + excludes := []string{} + ignore, err := ioutil.ReadFile(ignoreFile) + if err != nil { + return excludes, err + } + for _, e := range strings.Split(string(ignore), "\n") { + if len(e) == 0 || e[0] == '#' { + continue + } + excludes = append(excludes, e) + } + return excludes, nil +} diff --git a/cmd/podman/root.go b/cmd/podman/root.go index 874573bb9..7722e35dd 100644 --- a/cmd/podman/root.go +++ b/cmd/podman/root.go @@ -17,9 +17,7 @@ import ( "github.com/containers/podman/v3/pkg/domain/entities" "github.com/containers/podman/v3/pkg/parallel" "github.com/containers/podman/v3/pkg/rootless" - "github.com/containers/podman/v3/pkg/tracing" "github.com/containers/podman/v3/version" - "github.com/opentracing/opentracing-go" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -103,7 +101,6 @@ func Execute() { } func persistentPreRunE(cmd *cobra.Command, args []string) error { - // TODO: Remove trace statement in podman V2.1 logrus.Debugf("Called %s.PersistentPreRunE(%s)", cmd.Name(), strings.Join(os.Args, " ")) // Help, completion and commands with subcommands are special cases, no need for more setup @@ -194,16 +191,6 @@ func persistentPreRunE(cmd *cobra.Command, args []string) error { } } - if cmd.Flag("trace").Changed { - tracer, closer := tracing.Init("podman") - opentracing.SetGlobalTracer(tracer) - cfg.SpanCloser = closer - - cfg.Span = tracer.StartSpan("before-context") - cfg.SpanCtx = opentracing.ContextWithSpan(registry.Context(), cfg.Span) - opentracing.StartSpanFromContext(cfg.SpanCtx, cmd.Name()) - } - if cfg.MaxWorks <= 0 { return errors.Errorf("maximum workers must be set to a positive number (got %d)", cfg.MaxWorks) } @@ -226,22 +213,16 @@ func persistentPreRunE(cmd *cobra.Command, args []string) error { } func persistentPostRunE(cmd *cobra.Command, args []string) error { - // TODO: Remove trace statement in podman V2.1 logrus.Debugf("Called %s.PersistentPostRunE(%s)", cmd.Name(), strings.Join(os.Args, " ")) if !requireCleanup { return nil } - cfg := registry.PodmanConfig() if !registry.IsRemote() { if cmd.Flag("cpu-profile").Changed { pprof.StopCPUProfile() } - if cmd.Flag("trace").Changed { - cfg.Span.Finish() - cfg.SpanCloser.Close() - } } registry.ImageEngine().Shutdown(registry.Context()) |