diff options
Diffstat (limited to 'cmd/podman')
29 files changed, 886 insertions, 419 deletions
diff --git a/cmd/podman/attach.go b/cmd/podman/attach.go index 7d32c57af..6f08cc396 100644 --- a/cmd/podman/attach.go +++ b/cmd/podman/attach.go @@ -2,7 +2,6 @@ package main import ( "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -32,10 +31,7 @@ func init() { attachCommand.SetHelpTemplate(HelpTemplate()) attachCommand.SetUsageTemplate(UsageTemplate()) flags := attachCommand.Flags() - flags.StringVar(&attachCommand.DetachKeys, "detach-keys", define.DefaultDetachKeys, "Select the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`") - // Clear the default, the value specified in the config file should have the - // priority - attachCommand.DetachKeys = "" + flags.StringVar(&attachCommand.DetachKeys, "detach-keys", getDefaultDetachKeys(), "Select the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`") flags.BoolVar(&attachCommand.NoStdin, "no-stdin", false, "Do not attach STDIN. The default is false") flags.BoolVar(&attachCommand.SigProxy, "sig-proxy", true, "Proxy received signals to the process") flags.BoolVarP(&attachCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of") diff --git a/cmd/podman/autoupdate.go b/cmd/podman/autoupdate.go new file mode 100644 index 000000000..2cc1ae72e --- /dev/null +++ b/cmd/podman/autoupdate.go @@ -0,0 +1,56 @@ +package main + +import ( + "fmt" + + "github.com/containers/libpod/cmd/podman/cliconfig" + "github.com/containers/libpod/pkg/adapter" + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +var ( + autoUpdateCommand cliconfig.AutoUpdateValues + autoUpdateDescription = `Auto update containers according to their auto-update policy. + +Auto-update policies are specified with the "io.containers.autoupdate" label.` + _autoUpdateCommand = &cobra.Command{ + Use: "auto-update [flags]", + Short: "Auto update containers according to their auto-update policy", + Args: noSubArgs, + Long: autoUpdateDescription, + RunE: func(cmd *cobra.Command, args []string) error { + restartCommand.InputArgs = args + restartCommand.GlobalFlags = MainGlobalOpts + return autoUpdateCmd(&restartCommand) + }, + Example: `podman auto-update`, + } +) + +func init() { + autoUpdateCommand.Command = _autoUpdateCommand + autoUpdateCommand.SetHelpTemplate(HelpTemplate()) + autoUpdateCommand.SetUsageTemplate(UsageTemplate()) +} + +func autoUpdateCmd(c *cliconfig.RestartValues) error { + runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand) + if err != nil { + return errors.Wrapf(err, "error creating libpod runtime") + } + defer runtime.DeferredShutdown(false) + + units, failures := runtime.AutoUpdate() + for _, unit := range units { + fmt.Println(unit) + } + var finalErr error + if len(failures) > 0 { + finalErr = failures[0] + for _, e := range failures[1:] { + finalErr = errors.Errorf("%v\n%v", finalErr, e) + } + } + return finalErr +} diff --git a/cmd/podman/build.go b/cmd/podman/build.go index acd402fdd..04bc56ab0 100644 --- a/cmd/podman/build.go +++ b/cmd/podman/build.go @@ -9,9 +9,9 @@ import ( "github.com/containers/buildah" "github.com/containers/buildah/imagebuildah" buildahcli "github.com/containers/buildah/pkg/cli" - "github.com/containers/image/v5/types" + "github.com/containers/buildah/pkg/parse" + "github.com/containers/common/pkg/config" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/adapter" "github.com/docker/go-units" "github.com/opencontainers/runtime-spec/specs-go" @@ -86,6 +86,7 @@ func initBuild() { fromAndBugFlags, err := buildahcli.GetFromAndBudFlags(&fromAndBudValues, &userNSValues, &namespaceValues) if err != nil { logrus.Errorf("failed to setup podman build flags: %v", err) + os.Exit(1) } flags.AddFlagSet(&budFlags) @@ -267,14 +268,15 @@ func buildCmd(c *cliconfig.BuildValues) error { if err != nil { return err } - if conf != nil && conf.CgroupManager == define.SystemdCgroupsManager { + if conf != nil && conf.Engine.CgroupManager == config.SystemdCgroupsManager { runtimeFlags = append(runtimeFlags, "--systemd-cgroup") } // end from buildah defer runtime.DeferredShutdown(false) - var stdout, stderr, reporter *os.File + var stdin, stdout, stderr, reporter *os.File + stdin = os.Stdin stdout = os.Stdout stderr = os.Stderr reporter = os.Stderr @@ -310,6 +312,17 @@ func buildCmd(c *cliconfig.BuildValues) error { return err } + networkPolicy := buildah.NetworkDefault + for _, ns := range nsValues { + if ns.Name == "none" { + networkPolicy = buildah.NetworkDisabled + break + } else if !filepath.IsAbs(ns.Path) { + networkPolicy = buildah.NetworkEnabled + break + } + } + buildOpts := buildah.CommonBuildOptions{ AddHost: c.AddHost, CgroupParent: c.CgroupParent, @@ -341,21 +354,49 @@ func buildCmd(c *cliconfig.BuildValues) error { layers = false } + compression := imagebuildah.Gzip + if c.DisableCompression { + compression = imagebuildah.Uncompressed + } + + isolation, err := parse.IsolationOption(c.Isolation) + if err != nil { + return errors.Wrapf(err, "error parsing ID mapping options") + } + + usernsOption, idmappingOptions, err := parse.IDMappingOptions(c.PodmanCommand.Command, isolation) + if err != nil { + return errors.Wrapf(err, "error parsing ID mapping options") + } + nsValues = append(nsValues, usernsOption...) + + systemContext, err := parse.SystemContextFromOptions(c.PodmanCommand.Command) + if err != nil { + return errors.Wrapf(err, "error building system context") + } + options := imagebuildah.BuildOptions{ - Architecture: c.Arch, - CommonBuildOpts: &buildOpts, + AddCapabilities: c.CapAdd, AdditionalTags: tags, Annotations: c.Annotation, + Architecture: c.Arch, Args: args, + BlobDirectory: c.BlobCache, CNIConfigDir: c.CNIConfigDir, CNIPluginPath: c.CNIPlugInPath, - Compression: imagebuildah.Gzip, + CommonBuildOpts: &buildOpts, + Compression: compression, + ConfigureNetwork: networkPolicy, ContextDirectory: contextDir, DefaultMountsFilePath: c.GlobalFlags.DefaultMountsFile, + Devices: c.Devices, + DropCapabilities: c.CapDrop, Err: stderr, - In: os.Stdin, ForceRmIntermediateCtrs: c.ForceRm, + IDMappingOptions: idmappingOptions, IIDFile: c.Iidfile, + In: stdin, + Isolation: isolation, Labels: c.Label, Layers: layers, NamespaceOptions: nsValues, @@ -369,13 +410,12 @@ func buildCmd(c *cliconfig.BuildValues) error { RemoveIntermediateCtrs: c.Rm, ReportWriter: reporter, RuntimeArgs: runtimeFlags, + SignBy: c.SignBy, SignaturePolicyPath: c.SignaturePolicy, Squash: c.Squash, - SystemContext: &types.SystemContext{ - OSChoice: c.OverrideOS, - ArchitectureChoice: c.OverrideArch, - }, - Target: c.Target, + SystemContext: systemContext, + Target: c.Target, + TransientMounts: c.Volumes, } _, _, err = runtime.Build(getContext(), c, options, containerfiles) return err diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go index 79917946a..faf292ea0 100644 --- a/cmd/podman/cliconfig/config.go +++ b/cmd/podman/cliconfig/config.go @@ -2,7 +2,10 @@ package cliconfig import ( "net" + "os" + "github.com/containers/common/pkg/config" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -54,6 +57,10 @@ type AttachValues struct { SigProxy bool } +type AutoUpdateValues struct { + PodmanCommand +} + type ImagesValues struct { PodmanCommand All bool @@ -111,6 +118,7 @@ type CommitValues struct { Pause bool Quiet bool IncludeVolumes bool + ImageIDFile string } type ContainersPrune struct { @@ -470,10 +478,11 @@ type RefreshValues struct { type RestartValues struct { PodmanCommand - All bool - Latest bool - Running bool - Timeout uint + All bool + AutoUpdate bool + Latest bool + Running bool + Timeout uint } type RestoreValues struct { @@ -694,3 +703,14 @@ type SystemDfValues struct { type UntagValues struct { PodmanCommand } + +func GetDefaultConfig() *config.Config { + var err error + conf, err := config.NewConfig("") + conf.CheckCgroupsAndAdjustConfig() + if err != nil { + logrus.Errorf("Error loading container config %v\n", err) + os.Exit(1) + } + return conf +} diff --git a/cmd/podman/cliconfig/defaults.go b/cmd/podman/cliconfig/defaults.go index ce695d153..3082207e0 100644 --- a/cmd/podman/cliconfig/defaults.go +++ b/cmd/podman/cliconfig/defaults.go @@ -11,6 +11,4 @@ var ( DefaultHealthCheckTimeout = "30s" // DefaultImageVolume default value DefaultImageVolume = "bind" - // DefaultShmSize default value - DefaultShmSize = "65536k" ) diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go index d6018a6f4..2ee31b643 100644 --- a/cmd/podman/commands.go +++ b/cmd/podman/commands.go @@ -3,6 +3,15 @@ package main import ( + "fmt" + "os" + + "github.com/containers/buildah/pkg/parse" + "github.com/containers/libpod/pkg/apparmor" + "github.com/containers/libpod/pkg/cgroups" + "github.com/containers/libpod/pkg/rootless" + "github.com/containers/libpod/pkg/sysinfo" + "github.com/opencontainers/selinux/go-selinux" "github.com/spf13/cobra" ) @@ -11,6 +20,7 @@ const remoteclient = false // Commands that the local client implements func getMainCommands() []*cobra.Command { rootCommands := []*cobra.Command{ + _autoUpdateCommand, _cpCommand, _playCommand, _loginCommand, @@ -80,3 +90,107 @@ func getSystemSubCommands() []*cobra.Command { return systemCommands } + +func getDefaultSecurityOptions() []string { + securityOpts := []string{} + if defaultContainerConfig.Containers.SeccompProfile != "" && defaultContainerConfig.Containers.SeccompProfile != parse.SeccompDefaultPath { + securityOpts = append(securityOpts, fmt.Sprintf("seccomp=%s", defaultContainerConfig.Containers.SeccompProfile)) + } + if apparmor.IsEnabled() && defaultContainerConfig.Containers.ApparmorProfile != "" { + securityOpts = append(securityOpts, fmt.Sprintf("apparmor=%s", defaultContainerConfig.Containers.ApparmorProfile)) + } + if selinux.GetEnabled() && !defaultContainerConfig.Containers.EnableLabeling { + securityOpts = append(securityOpts, fmt.Sprintf("label=%s", selinux.DisableSecOpt()[0])) + } + return securityOpts +} + +// getDefaultSysctls +func getDefaultSysctls() []string { + return defaultContainerConfig.Containers.DefaultSysctls +} + +func getDefaultVolumes() []string { + return defaultContainerConfig.Containers.Volumes +} + +func getDefaultDevices() []string { + return defaultContainerConfig.Containers.Devices +} + +func getDefaultDNSServers() []string { + return defaultContainerConfig.Containers.DNSServers +} + +func getDefaultDNSSearches() []string { + return defaultContainerConfig.Containers.DNSSearches +} + +func getDefaultDNSOptions() []string { + return defaultContainerConfig.Containers.DNSOptions +} + +func getDefaultEnv() []string { + return defaultContainerConfig.Containers.Env +} + +func getDefaultInitPath() string { + return defaultContainerConfig.Containers.InitPath +} + +func getDefaultIPCNS() string { + return defaultContainerConfig.Containers.IPCNS +} + +func getDefaultPidNS() string { + return defaultContainerConfig.Containers.PidNS +} + +func getDefaultNetNS() string { + if defaultContainerConfig.Containers.NetNS == "private" && rootless.IsRootless() { + return "slirp4netns" + } + return defaultContainerConfig.Containers.NetNS +} + +func getDefaultCgroupNS() string { + return defaultContainerConfig.Containers.CgroupNS +} + +func getDefaultUTSNS() string { + return defaultContainerConfig.Containers.UTSNS +} + +func getDefaultShmSize() string { + return defaultContainerConfig.Containers.ShmSize +} + +func getDefaultUlimits() []string { + return defaultContainerConfig.Containers.DefaultUlimits +} + +func getDefaultUserNS() string { + userns := os.Getenv("PODMAN_USERNS") + if userns != "" { + return userns + } + return defaultContainerConfig.Containers.UserNS +} + +func getDefaultPidsLimit() int64 { + if rootless.IsRootless() { + cgroup2, _ := cgroups.IsCgroup2UnifiedMode() + if cgroup2 { + return defaultContainerConfig.Containers.PidsLimit + } + } + return sysinfo.GetDefaultPidsLimit() +} + +func getDefaultPidsDescription() string { + return "Tune container pids limit (set 0 for unlimited)" +} + +func getDefaultDetachKeys() string { + return defaultContainerConfig.Engine.DetachKeys +} diff --git a/cmd/podman/commands_remoteclient.go b/cmd/podman/commands_remoteclient.go index a278761c1..ef523ffb1 100644 --- a/cmd/podman/commands_remoteclient.go +++ b/cmd/podman/commands_remoteclient.go @@ -47,3 +47,89 @@ func getTrustSubCommands() []*cobra.Command { func getSystemSubCommands() []*cobra.Command { return []*cobra.Command{} } + +func getDefaultSecurityOptions() []string { + return []string{} +} + +// getDefaultSysctls +func getDefaultSysctls() []string { + return []string{} +} + +// getDefaultDevices +func getDefaultDevices() []string { + return []string{} +} + +func getDefaultVolumes() []string { + return []string{} +} + +func getDefaultDNSServers() []string { + return []string{} +} + +func getDefaultDNSSearches() []string { + return []string{} +} + +func getDefaultDNSOptions() []string { + return []string{} +} + +func getDefaultEnv() []string { + return []string{} +} + +func getDefaultInitPath() string { + return "" +} + +func getDefaultIPCNS() string { + return "" +} + +func getDefaultPidNS() string { + return "" +} + +func getDefaultNetNS() string { + return "" +} + +func getDefaultCgroupNS() string { + return "" +} + +func getDefaultUTSNS() string { + return "" +} + +func getDefaultShmSize() string { + return "" +} + +func getDefaultUlimits() []string { + return []string{} +} + +func getDefaultUserNS() string { + return "" +} + +func getDefaultPidsLimit() int64 { + return -1 +} + +func getDefaultPidsDescription() string { + return "Tune container pids limit (set 0 for unlimited, -1 for server defaults)" +} + +func getDefaultShareNetwork() string { + return "" +} + +func getDefaultDetachKeys() string { + return "" +} diff --git a/cmd/podman/commit.go b/cmd/podman/commit.go index 7c35a4832..3ad3bd275 100644 --- a/cmd/podman/commit.go +++ b/cmd/podman/commit.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "io/ioutil" "strings" "github.com/containers/libpod/cmd/podman/cliconfig" @@ -41,6 +42,7 @@ func init() { flags := commitCommand.Flags() flags.StringArrayVarP(&commitCommand.Change, "change", "c", []string{}, fmt.Sprintf("Apply the following possible instructions to the created image (default []): %s", strings.Join(ChangeCmds, " | "))) flags.StringVarP(&commitCommand.Format, "format", "f", "oci", "`Format` of the image manifest and metadata") + flags.StringVarP(&commitCommand.ImageIDFile, "iidfile", "", "", "`file` to write the image ID to") flags.StringVarP(&commitCommand.Message, "message", "m", "", "Set commit message for imported image") flags.StringVarP(&commitCommand.Author, "author", "a", "", "Set the author for the image committed") flags.BoolVarP(&commitCommand.Pause, "pause", "p", false, "Pause container during commit") @@ -70,6 +72,11 @@ func commitCmd(c *cliconfig.CommitValues) error { if err != nil { return err } + if c.ImageIDFile != "" { + if err = ioutil.WriteFile(c.ImageIDFile, []byte(iid), 0644); err != nil { + return errors.Wrapf(err, "failed to write image ID to file %q", c.ImageIDFile) + } + } fmt.Println(iid) return nil } diff --git a/cmd/podman/common.go b/cmd/podman/common.go index 4eeb09d42..9aa9a63fe 100644 --- a/cmd/podman/common.go +++ b/cmd/podman/common.go @@ -3,15 +3,11 @@ package main import ( "context" "fmt" - "os" "strings" "github.com/containers/buildah" buildahcli "github.com/containers/buildah/pkg/cli" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/define" - "github.com/containers/libpod/pkg/rootless" - "github.com/containers/libpod/pkg/sysinfo" "github.com/containers/libpod/pkg/util/camelcase" jsoniter "github.com/json-iterator/go" "github.com/pkg/errors" @@ -110,29 +106,22 @@ func getContext() context.Context { return context.TODO() } -func getDefaultNetwork() string { - if rootless.IsRootless() { - return "slirp4netns" - } - return "bridge" -} - func getNetFlags() *pflag.FlagSet { netFlags := pflag.FlagSet{} netFlags.StringSlice( "add-host", []string{}, - "Add a custom host-to-IP mapping (host:ip) (default [])", + "Add a custom host-to-IP mapping (host:ip)", ) netFlags.StringSlice( - "dns", []string{}, + "dns", getDefaultDNSServers(), "Set custom DNS servers", ) netFlags.StringSlice( - "dns-opt", []string{}, + "dns-opt", getDefaultDNSOptions(), "Set custom DNS options", ) netFlags.StringSlice( - "dns-search", []string{}, + "dns-search", getDefaultDNSSearches(), "Set custom DNS search domains", ) netFlags.String( @@ -144,7 +133,7 @@ func getNetFlags() *pflag.FlagSet { "Container MAC address (e.g. 92:d0:c6:0a:29:33)", ) netFlags.String( - "network", getDefaultNetwork(), + "network", getDefaultNetNS(), "Connect a container to a network", ) netFlags.StringSliceP( @@ -162,11 +151,11 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { createFlags := c.Flags() createFlags.StringSlice( "annotation", []string{}, - "Add annotations to container (key:value) (default [])", + "Add annotations to container (key:value)", ) createFlags.StringSliceP( "attach", "a", []string{}, - "Attach to STDIN, STDOUT or STDERR (default [])", + "Attach to STDIN, STDOUT or STDERR", ) createFlags.String( "authfile", buildahcli.GetDefaultAuthFile(), @@ -189,7 +178,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { "Drop capabilities from the container", ) createFlags.String( - "cgroupns", "", + "cgroupns", getDefaultCgroupNS(), "cgroup namespace to use", ) createFlags.String( @@ -244,17 +233,13 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { "detach", "d", false, "Run container in background and print container ID", ) - detachKeys := createFlags.String( - "detach-keys", define.DefaultDetachKeys, + createFlags.String( + "detach-keys", getDefaultDetachKeys(), "Override the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`", ) - // Clear the default, the value specified in the config file should have the - // priority - *detachKeys = "" - createFlags.StringSlice( - "device", []string{}, - "Add a host device to the container (default [])", + "device", getDefaultDevices(), + fmt.Sprintf("Add a host device to the container"), ) createFlags.StringSlice( "device-cgroup-rule", []string{}, @@ -281,7 +266,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { "Overwrite the default ENTRYPOINT of the image", ) createFlags.StringArrayP( - "env", "e", []string{}, + "env", "e", getDefaultEnv(), "Set environment variables in container", ) createFlags.Bool( @@ -293,7 +278,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { ) createFlags.StringSlice( "expose", []string{}, - "Expose a port or a range of ports (default [])", + "Expose a port or a range of ports", ) createFlags.StringSlice( "gidmap", []string{}, @@ -301,7 +286,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { ) createFlags.StringSlice( "group-add", []string{}, - "Add additional groups to join (default [])", + "Add additional groups to join", ) createFlags.Bool( "help", false, "", @@ -343,16 +328,16 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { "Run an init binary inside the container that forwards signals and reaps processes", ) createFlags.String( - "init-path", "", + "init-path", getDefaultInitPath(), // Do not use the Value field for setting the default value to determine user input (i.e., non-empty string) - fmt.Sprintf("Path to the container-init binary (default: %q)", define.DefaultInitPath), + fmt.Sprintf("Path to the container-init binary"), ) createFlags.BoolP( "interactive", "i", false, "Keep STDIN open even if not attached", ) createFlags.String( - "ipc", "", + "ipc", getDefaultIPCNS(), "IPC namespace to use", ) createFlags.String( @@ -361,11 +346,11 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { ) createFlags.StringArrayP( "label", "l", []string{}, - "Set metadata on container (default [])", + "Set metadata on container", ) createFlags.StringSlice( "label-file", []string{}, - "Read in a line delimited file of labels (default [])", + "Read in a line delimited file of labels", ) createFlags.String( "log-driver", "", @@ -373,7 +358,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { ) createFlags.StringSlice( "log-opt", []string{}, - "Logging driver options (default [])", + "Logging driver options", ) createFlags.StringP( "memory", "m", "", @@ -418,12 +403,12 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { ) markFlagHidden(createFlags, "override-os") createFlags.String( - "pid", "", + "pid", getDefaultPidNS(), "PID namespace to use", ) createFlags.Int64( - "pids-limit", sysinfo.GetDefaultPidsLimit(), - "Tune container pids limit (set 0 for unlimited)", + "pids-limit", getDefaultPidsLimit(), + getDefaultPidsDescription(), ) createFlags.String( "pod", "", @@ -466,11 +451,11 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { "The first argument is not an image but the rootfs to the exploded container", ) createFlags.StringArray( - "security-opt", []string{}, - "Security Options (default [])", + "security-opt", getDefaultSecurityOptions(), + fmt.Sprintf("Security Options"), ) createFlags.String( - "shm-size", cliconfig.DefaultShmSize, + "shm-size", getDefaultShmSize(), "Size of /dev/shm "+sizeWithUnitFormat, ) createFlags.String( @@ -478,12 +463,12 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { "Signal to stop a container. Default is SIGTERM", ) createFlags.Uint( - "stop-timeout", define.CtrRemoveTimeout, + "stop-timeout", defaultContainerConfig.Engine.StopTimeout, "Timeout (in seconds) to stop a container. Default is 10", ) createFlags.StringSlice( "storage-opt", []string{}, - "Storage driver options per container (default [])", + "Storage driver options per container", ) createFlags.String( "subgidname", "", @@ -495,8 +480,8 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { ) createFlags.StringSlice( - "sysctl", []string{}, - "Sysctl options (default [])", + "sysctl", getDefaultSysctls(), + "Sysctl options", ) createFlags.String( "systemd", "true", @@ -504,7 +489,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { ) createFlags.StringArray( "tmpfs", []string{}, - "Mount a temporary filesystem (`tmpfs`) into a container (default [])", + "Mount a temporary filesystem (`tmpfs`) into a container", ) createFlags.BoolP( "tty", "t", false, @@ -515,32 +500,32 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { "UID map to use for the user namespace", ) createFlags.StringSlice( - "ulimit", []string{}, - "Ulimit options (default [])", + "ulimit", getDefaultUlimits(), + "Ulimit options", ) createFlags.StringP( "user", "u", "", "Username or UID (format: <name|uid>[:<group|gid>])", ) createFlags.String( - "userns", os.Getenv("PODMAN_USERNS"), + "userns", getDefaultUserNS(), "User namespace to use", ) createFlags.String( - "uts", "", + "uts", getDefaultUTSNS(), "UTS namespace to use", ) createFlags.StringArray( "mount", []string{}, - "Attach a filesystem mount to the container (default [])", + "Attach a filesystem mount to the container", ) createFlags.StringArrayP( - "volume", "v", []string{}, - "Bind mount a volume into the container (default [])", + "volume", "v", getDefaultVolumes(), + "Bind mount a volume into the container", ) createFlags.StringSlice( "volumes-from", []string{}, - "Mount volumes from the specified container(s) (default [])", + "Mount volumes from the specified container(s)", ) createFlags.StringP( "workdir", "w", "", diff --git a/cmd/podman/create.go b/cmd/podman/create.go index 73d62bddb..03eb1b09f 100644 --- a/cmd/podman/create.go +++ b/cmd/podman/create.go @@ -38,7 +38,6 @@ func init() { createCommand.PodmanCommand.Command = _createCommand createCommand.SetHelpTemplate(HelpTemplate()) createCommand.SetUsageTemplate(UsageTemplate()) - getCreateFlags(&createCommand.PodmanCommand) flags := createCommand.Flags() flags.AddFlagSet(getNetFlags()) diff --git a/cmd/podman/exec.go b/cmd/podman/exec.go index 6e5799396..b341ab496 100644 --- a/cmd/podman/exec.go +++ b/cmd/podman/exec.go @@ -2,7 +2,6 @@ package main import ( "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -35,10 +34,7 @@ func init() { execCommand.SetUsageTemplate(UsageTemplate()) flags := execCommand.Flags() flags.SetInterspersed(false) - flags.StringVar(&execCommand.DetachKeys, "detach-keys", define.DefaultDetachKeys, "Select the key sequence for detaching a container. Format is a single character [a-Z] or ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _") - // Clear the default, the value specified in the config file should have the - // priority - execCommand.DetachKeys = "" + flags.StringVar(&execCommand.DetachKeys, "detach-keys", getDefaultDetachKeys(), "Select the key sequence for detaching a container. Format is a single character [a-Z] or ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _") flags.StringArrayVarP(&execCommand.Env, "env", "e", []string{}, "Set environment variables") flags.StringSliceVar(&execCommand.EnvFile, "env-file", []string{}, "Read in a file of environment variables") flags.BoolVarP(&execCommand.Interactive, "interactive", "i", false, "Keep STDIN open even if not attached") diff --git a/cmd/podman/images.go b/cmd/podman/images.go index 41790a5aa..ed33402ab 100644 --- a/cmd/podman/images.go +++ b/cmd/podman/images.go @@ -13,8 +13,8 @@ import ( "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/pkg/adapter" - "github.com/docker/go-units" - "github.com/opencontainers/go-digest" + units "github.com/docker/go-units" + digest "github.com/opencontainers/go-digest" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -34,14 +34,15 @@ type imagesTemplateParams struct { } type imagesJSONParams struct { - ID string `json:"id"` - Name []string `json:"names"` - Digest digest.Digest `json:"digest"` - Digests []digest.Digest `json:"digests"` - Created time.Time `json:"created"` - Size *uint64 `json:"size"` - ReadOnly bool `json:"readonly"` - History []string `json:"history"` + ID string `json:"ID"` + Name []string `json:"Names"` + Created string `json:"Created"` + Digest digest.Digest `json:"Digest"` + Digests []digest.Digest `json:"Digests"` + CreatedAt time.Time `json:"CreatedAt"` + Size *uint64 `json:"Size"` + ReadOnly bool `json:"ReadOnly"` + History []string `json:"History"` } type imagesOptions struct { @@ -344,14 +345,15 @@ func getImagesJSONOutput(ctx context.Context, images []*adapter.ContainerImage) size = nil } params := imagesJSONParams{ - ID: img.ID(), - Name: img.Names(), - Digest: img.Digest(), - Digests: img.Digests(), - Created: img.Created(), - Size: size, - ReadOnly: img.IsReadOnly(), - History: img.NamesHistory(), + ID: img.ID(), + Name: img.Names(), + Digest: img.Digest(), + Digests: img.Digests(), + Created: units.HumanDuration(time.Since(img.Created())) + " ago", + CreatedAt: img.Created(), + Size: size, + ReadOnly: img.IsReadOnly(), + History: img.NamesHistory(), } imagesOutput = append(imagesOutput, params) } diff --git a/cmd/podman/libpodruntime/runtime.go b/cmd/podman/libpodruntime/runtime.go index e9dc87de1..8dbc4009b 100644 --- a/cmd/podman/libpodruntime/runtime.go +++ b/cmd/podman/libpodruntime/runtime.go @@ -211,8 +211,6 @@ func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, opts *runtimeOp if !opts.withFDS { options = append(options, libpod.WithEnableSDNotify()) } - if c.Flags().Changed("config") { - return libpod.NewRuntimeFromConfig(ctx, c.GlobalFlags.Config, options...) - } + return libpod.NewRuntime(ctx, options...) } diff --git a/cmd/podman/main.go b/cmd/podman/main.go index a2acbbf53..5134448da 100644 --- a/cmd/podman/main.go +++ b/cmd/podman/main.go @@ -6,6 +6,7 @@ import ( "os" "path" + "github.com/containers/common/pkg/config" "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/define" @@ -81,7 +82,10 @@ var rootCmd = &cobra.Command{ SilenceErrors: true, } -var MainGlobalOpts cliconfig.MainFlags +var ( + MainGlobalOpts cliconfig.MainFlags + defaultContainerConfig = getDefaultContainerConfig() +) func initCobra() { cobra.OnInitialize(initConfig) @@ -175,3 +179,12 @@ func main() { CheckForRegistries() os.Exit(exitCode) } + +func getDefaultContainerConfig() *config.Config { + defaultContainerConfig, err := config.Default() + if err != nil { + logrus.Error(err) + os.Exit(1) + } + return defaultContainerConfig +} diff --git a/cmd/podman/main_local.go b/cmd/podman/main_local.go index 79b5e5af7..b03c7de44 100644 --- a/cmd/podman/main_local.go +++ b/cmd/podman/main_local.go @@ -14,9 +14,9 @@ import ( "strings" "syscall" + "github.com/containers/common/pkg/config" "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/cmd/podman/libpodruntime" - "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/cgroups" "github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/tracing" @@ -32,9 +32,11 @@ import ( const remote = false func init() { - cgroupManager := define.SystemdCgroupsManager + cgroupManager := defaultContainerConfig.Engine.CgroupManager cgroupHelp := `Cgroup manager to use ("cgroupfs"|"systemd")` cgroupv2, _ := cgroups.IsCgroup2UnifiedMode() + + defaultContainerConfig = cliconfig.GetDefaultConfig() if rootless.IsRootless() && !cgroupv2 { cgroupManager = "" cgroupHelp = "Cgroup manager is not supported in rootless mode" @@ -42,25 +44,27 @@ func init() { rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.CGroupManager, "cgroup-manager", cgroupManager, cgroupHelp) // -c is deprecated due to conflict with -c on subcommands rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.CpuProfile, "cpu-profile", "", "Path for the cpu profiling results") - rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Config, "config", "", "Path of a libpod config file detailing container server configuration options") rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.ConmonPath, "conmon", "", "Path of the conmon binary") - rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.NetworkCmdPath, "network-cmd-path", "", "Path to the command for configuring the network") - rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.CniConfigDir, "cni-config-dir", "", "Path of the configuration directory for CNI networks") - rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.DefaultMountsFile, "default-mounts-file", "", "Path to default mounts file") + rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.NetworkCmdPath, "network-cmd-path", defaultContainerConfig.Engine.NetworkCmdPath, "Path to the command for configuring the network") + rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.CniConfigDir, "cni-config-dir", getCNIPluginsDir(), "Path of the configuration directory for CNI networks") + rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.DefaultMountsFile, "default-mounts-file", defaultContainerConfig.Containers.DefaultMountsFile, "Path to default mounts file") + if err := rootCmd.PersistentFlags().MarkHidden("cpu-profile"); err != nil { + logrus.Error("unable to mark default-mounts-file flag as hidden") + } if err := rootCmd.PersistentFlags().MarkHidden("default-mounts-file"); err != nil { logrus.Error("unable to mark default-mounts-file flag as hidden") } - rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.EventsBackend, "events-backend", "", `Events backend to use ("file"|"journald"|"none")`) + rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.EventsBackend, "events-backend", defaultContainerConfig.Engine.EventsLogger, `Events backend to use ("file"|"journald"|"none")`) // Override default --help information of `--help` global flag var dummyHelp bool rootCmd.PersistentFlags().BoolVar(&dummyHelp, "help", false, "Help for podman") - rootCmd.PersistentFlags().StringSliceVar(&MainGlobalOpts.HooksDir, "hooks-dir", []string{}, "Set the OCI hooks directory path (may be set multiple times)") + rootCmd.PersistentFlags().StringSliceVar(&MainGlobalOpts.HooksDir, "hooks-dir", defaultContainerConfig.Engine.HooksDir, "Set the OCI hooks directory path (may be set multiple times)") rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.LogLevel, "log-level", "error", `Log messages above specified level ("debug"|"info"|"warn"|"error"|"fatal"|"panic")`) rootCmd.PersistentFlags().IntVar(&MainGlobalOpts.MaxWorks, "max-workers", 0, "The maximum number of workers for parallel operations") if err := rootCmd.PersistentFlags().MarkHidden("max-workers"); err != nil { logrus.Error("unable to mark max-workers flag as hidden") } - rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Namespace, "namespace", "", "Set the libpod namespace, used to create separate views of the containers and pods on the system") + rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Namespace, "namespace", defaultContainerConfig.Engine.Namespace, "Set the libpod namespace, used to create separate views of the containers and pods on the system") rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Root, "root", "", "Path to the root directory in which data, including images, is stored") rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Runroot, "runroot", "", "Path to the 'run directory' where all state information is stored") rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Runtime, "runtime", "", "Path to the OCI-compatible binary used to run containers, default is /usr/bin/runc") @@ -179,7 +183,7 @@ func setupRootless(cmd *cobra.Command, args []string) error { if !ownsCgroup { unitName := fmt.Sprintf("podman-%d.scope", os.Getpid()) if err := utils.RunUnderSystemdScope(os.Getpid(), "user.slice", unitName); err != nil { - if conf.CgroupManager == define.SystemdCgroupsManager { + if conf.Engine.CgroupManager == config.SystemdCgroupsManager { logrus.Warnf("Failed to add podman to systemd sandbox cgroup: %v", err) } else { logrus.Debugf("Failed to add podman to systemd sandbox cgroup: %v", err) @@ -223,7 +227,7 @@ func setupRootless(cmd *cobra.Command, args []string) error { if err != nil { return err } - if conf.CgroupManager == define.SystemdCgroupsManager { + if conf.Engine.CgroupManager == config.SystemdCgroupsManager { logrus.Warnf("Failed to add pause process to systemd sandbox cgroup: %v", err) } else { logrus.Debugf("Failed to add pause process to systemd sandbox cgroup: %v", err) @@ -264,3 +268,10 @@ func setUMask() { func checkInput() error { return nil } +func getCNIPluginsDir() string { + if rootless.IsRootless() { + return "" + } + + return defaultContainerConfig.Network.CNIPluginDirs[0] +} diff --git a/cmd/podman/main_local_unsupported.go b/cmd/podman/main_local_unsupported.go new file mode 100644 index 000000000..75728627e --- /dev/null +++ b/cmd/podman/main_local_unsupported.go @@ -0,0 +1,44 @@ +// +build !remoteclient,!linux + +package main + +// The ONLY purpose of this file is to allow the subpackage to compile. Don’t expect anything +// to work. + +import ( + "syscall" + + "github.com/spf13/cobra" +) + +const remote = false + +func setSyslog() error { + return nil +} + +func profileOn(cmd *cobra.Command) error { + return nil +} + +func profileOff(cmd *cobra.Command) error { + return nil +} + +func setupRootless(cmd *cobra.Command, args []string) error { + return nil +} + +func setRLimits() error { + return nil +} + +func setUMask() { + // Be sure we can create directories with 0755 mode. + syscall.Umask(0022) +} + +// checkInput can be used to verify any of the globalopt values +func checkInput() error { + return nil +} diff --git a/cmd/podman/mount.go b/cmd/podman/mount.go index 526a236fd..99e185589 100644 --- a/cmd/podman/mount.go +++ b/cmd/podman/mount.go @@ -68,11 +68,7 @@ func mountCmd(c *cliconfig.MountValues) error { defer runtime.DeferredShutdown(false) if os.Geteuid() != 0 { - rtc, err := runtime.GetConfig() - if err != nil { - return err - } - if driver := rtc.StorageConfig.GraphDriverName; driver != "vfs" { + if driver := runtime.StorageConfig().GraphDriverName; driver != "vfs" { // Do not allow to mount a graphdriver that is not vfs if we are creating the userns as part // of the mount command. return fmt.Errorf("cannot mount using driver %s in rootless mode", driver) diff --git a/cmd/podman/pod_ps.go b/cmd/podman/pod_ps.go index d7731e983..7acbd6888 100644 --- a/cmd/podman/pod_ps.go +++ b/cmd/podman/pod_ps.go @@ -4,7 +4,6 @@ import ( "fmt" "reflect" "sort" - "strconv" "strings" "time" @@ -13,7 +12,6 @@ import ( "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/adapter" - "github.com/containers/libpod/pkg/util" "github.com/docker/go-units" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -29,8 +27,6 @@ const ( NUM_CTR_INFO = 10 ) -type PodFilter func(*adapter.Pod) bool - var ( bc_opts shared.PsOptions ) @@ -174,29 +170,23 @@ func podPsCmd(c *cliconfig.PodPsValues) error { opts.Format = genPodPsFormat(c) - var filterFuncs []PodFilter - if c.Filter != "" { - filters := strings.Split(c.Filter, ",") - for _, f := range filters { - filterSplit := strings.Split(f, "=") - if len(filterSplit) < 2 { - return errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f) - } - generatedFunc, err := generatePodFilterFuncs(filterSplit[0], filterSplit[1]) - if err != nil { - return errors.Wrapf(err, "invalid filter") - } - filterFuncs = append(filterFuncs, generatedFunc) - } - } - var pods []*adapter.Pod + + // If latest is set true filters are ignored. if c.Latest { pod, err := runtime.GetLatestPod() if err != nil { return err } pods = append(pods, pod) + return generatePodPsOutput(pods, opts) + } + + if c.Filter != "" { + pods, err = runtime.GetPodsWithFilters(c.Filter) + if err != nil { + return err + } } else { pods, err = runtime.GetAllPods() if err != nil { @@ -204,19 +194,7 @@ func podPsCmd(c *cliconfig.PodPsValues) error { } } - podsFiltered := make([]*adapter.Pod, 0, len(pods)) - for _, pod := range pods { - include := true - for _, filter := range filterFuncs { - include = include && filter(pod) - } - - if include { - podsFiltered = append(podsFiltered, pod) - } - } - - return generatePodPsOutput(podsFiltered, opts) + return generatePodPsOutput(pods, opts) } // podPsCheckFlagsPassed checks if mutually exclusive flags are passed together @@ -235,88 +213,6 @@ func podPsCheckFlagsPassed(c *cliconfig.PodPsValues) error { return nil } -func generatePodFilterFuncs(filter, filterValue string) (func(pod *adapter.Pod) bool, error) { - switch filter { - case "ctr-ids": - return func(p *adapter.Pod) bool { - ctrIds, err := p.AllContainersByID() - if err != nil { - return false - } - return util.StringInSlice(filterValue, ctrIds) - }, nil - case "ctr-names": - return func(p *adapter.Pod) bool { - ctrs, err := p.AllContainers() - if err != nil { - return false - } - for _, ctr := range ctrs { - if filterValue == ctr.Name() { - return true - } - } - return false - }, nil - case "ctr-number": - return func(p *adapter.Pod) bool { - ctrIds, err := p.AllContainersByID() - if err != nil { - return false - } - - fVint, err2 := strconv.Atoi(filterValue) - if err2 != nil { - return false - } - return len(ctrIds) == fVint - }, nil - case "ctr-status": - if !util.StringInSlice(filterValue, []string{"created", "restarting", "running", "paused", "exited", "unknown"}) { - return nil, errors.Errorf("%s is not a valid status", filterValue) - } - return func(p *adapter.Pod) bool { - ctr_statuses, err := p.Status() - if err != nil { - return false - } - for _, ctr_status := range ctr_statuses { - state := ctr_status.String() - if ctr_status == define.ContainerStateConfigured { - state = "created" - } - if state == filterValue { - return true - } - } - return false - }, nil - case "id": - return func(p *adapter.Pod) bool { - return strings.Contains(p.ID(), filterValue) - }, nil - case "name": - return func(p *adapter.Pod) bool { - return strings.Contains(p.Name(), filterValue) - }, nil - case "status": - if !util.StringInSlice(filterValue, []string{"stopped", "running", "paused", "exited", "dead", "created"}) { - return nil, errors.Errorf("%s is not a valid pod status", filterValue) - } - return func(p *adapter.Pod) bool { - status, err := p.GetPodStatus() - if err != nil { - return false - } - if strings.ToLower(status) == filterValue { - return true - } - return false - }, nil - } - return nil, errors.Errorf("%s is an invalid filter", filter) -} - // generate the template based on conditions given func genPodPsFormat(c *cliconfig.PodPsValues) string { format := "" diff --git a/cmd/podman/restart.go b/cmd/podman/restart.go index 996a9f7ce..a55f83c67 100644 --- a/cmd/podman/restart.go +++ b/cmd/podman/restart.go @@ -39,9 +39,10 @@ func init() { flags.BoolVarP(&restartCommand.All, "all", "a", false, "Restart all non-running containers") flags.BoolVarP(&restartCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of") flags.BoolVar(&restartCommand.Running, "running", false, "Restart only running containers when --all is used") - flags.UintVarP(&restartCommand.Timeout, "timeout", "t", define.CtrRemoveTimeout, "Seconds to wait for stop before killing the container") - flags.UintVar(&restartCommand.Timeout, "time", define.CtrRemoveTimeout, "Seconds to wait for stop before killing the container") + flags.UintVarP(&restartCommand.Timeout, "time", "t", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container") + flags.UintVar(&restartCommand.Timeout, "timeout", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container") + markFlagHidden(flags, "timeout") markFlagHiddenForRemoteClient("latest", flags) } diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go index 8968f10e8..5fa8d6c0b 100644 --- a/cmd/podman/shared/create.go +++ b/cmd/podman/shared/create.go @@ -18,6 +18,7 @@ import ( "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/image" ann "github.com/containers/libpod/pkg/annotations" + "github.com/containers/libpod/pkg/autoupdate" envLib "github.com/containers/libpod/pkg/env" "github.com/containers/libpod/pkg/errorhandling" "github.com/containers/libpod/pkg/inspect" @@ -25,6 +26,7 @@ import ( "github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/seccomp" cc "github.com/containers/libpod/pkg/spec" + systemdGen "github.com/containers/libpod/pkg/systemd/generate" "github.com/containers/libpod/pkg/util" "github.com/docker/go-connections/nat" "github.com/docker/go-units" @@ -69,6 +71,7 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod. } imageName := "" + rawImageName := "" var imageData *inspect.ImageData = nil // Set the storage if there is no rootfs specified @@ -78,9 +81,8 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod. writer = os.Stderr } - name := "" if len(c.InputArgs) != 0 { - name = c.InputArgs[0] + rawImageName = c.InputArgs[0] } else { return nil, nil, errors.Errorf("error, image name not provided") } @@ -97,7 +99,7 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod. ArchitectureChoice: overrideArch, } - newImage, err := runtime.ImageRuntime().New(ctx, name, rtc.SignaturePolicyPath, c.String("authfile"), writer, &dockerRegistryOptions, image.SigningOptions{}, nil, pullType) + newImage, err := runtime.ImageRuntime().New(ctx, rawImageName, rtc.Engine.SignaturePolicyPath, c.String("authfile"), writer, &dockerRegistryOptions, image.SigningOptions{}, nil, pullType) if err != nil { return nil, nil, err } @@ -174,11 +176,32 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod. } } - createConfig, err := ParseCreateOpts(ctx, c, runtime, imageName, imageData) + createConfig, err := ParseCreateOpts(ctx, c, runtime, imageName, rawImageName, imageData) if err != nil { return nil, nil, err } + // (VR): Ideally we perform the checks _before_ pulling the image but that + // would require some bigger code refactoring of `ParseCreateOpts` and the + // logic here. But as the creation code will be consolidated in the future + // and given auto updates are experimental, we can live with that for now. + // In the end, the user may only need to correct the policy or the raw image + // name. + autoUpdatePolicy, autoUpdatePolicySpecified := createConfig.Labels[autoupdate.Label] + if autoUpdatePolicySpecified { + if _, err := autoupdate.LookupPolicy(autoUpdatePolicy); err != nil { + return nil, nil, err + } + // Now we need to make sure we're having a fully-qualified image reference. + if rootfs != "" { + return nil, nil, errors.Errorf("auto updates do not work with --rootfs") + } + // Make sure the input image is a docker. + if err := autoupdate.ValidateImageReference(rawImageName); err != nil { + return nil, nil, err + } + } + // Because parseCreateOpts does derive anything from the image, we add health check // at this point. The rest is done by WithOptions. createConfig.HealthCheck = healthCheck @@ -270,7 +293,7 @@ func configurePod(c *GenericCLIResults, runtime *libpod.Runtime, namespaces map[ // Parses CLI options related to container creation into a config which can be // parsed into an OCI runtime spec -func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.Runtime, imageName string, data *inspect.ImageData) (*cc.CreateConfig, error) { +func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.Runtime, imageName string, rawImageName string, data *inspect.ImageData) (*cc.CreateConfig, error) { var ( inputCommand, command []string memoryLimit, memoryReservation, memorySwap, memoryKernel int64 @@ -481,12 +504,16 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. "container": "podman", } + // First transform the os env into a map. We need it for the labels later in + // any case. + osEnv, err := envLib.ParseSlice(os.Environ()) + if err != nil { + return nil, errors.Wrap(err, "error parsing host environment variables") + } + // Start with env-host + if c.Bool("env-host") { - osEnv, err := envLib.ParseSlice(os.Environ()) - if err != nil { - return nil, errors.Wrap(err, "error parsing host environment variables") - } env = envLib.Join(env, osEnv) } @@ -534,6 +561,10 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. } } + if systemdUnit, exists := osEnv[systemdGen.EnvVariable]; exists { + labels[systemdGen.EnvVariable] = systemdUnit + } + // ANNOTATIONS annotations := make(map[string]string) @@ -605,7 +636,6 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. if err != nil { return nil, errors.Wrapf(err, "unable to translate --shm-size") } - // Verify the additional hosts are in correct format for _, host := range c.StringSlice("add-host") { if _, err := parse.ValidateExtraHost(host); err != nil { @@ -613,24 +643,35 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. } } - // Check for . and dns-search domains - if util.StringInSlice(".", c.StringSlice("dns-search")) && len(c.StringSlice("dns-search")) > 1 { - return nil, errors.Errorf("cannot pass additional search domains when also specifying '.'") + var ( + dnsSearches []string + dnsServers []string + dnsOptions []string + ) + if c.Changed("dns-search") { + dnsSearches = c.StringSlice("dns-search") + // Check for explicit dns-search domain of '' + if len(dnsSearches) == 0 { + return nil, errors.Errorf("'' is not a valid domain") + } + // Validate domains are good + for _, dom := range dnsSearches { + if dom == "." { + if len(dnsSearches) > 1 { + return nil, errors.Errorf("cannot pass additional search domains when also specifying '.'") + } + continue + } + if _, err := parse.ValidateDomain(dom); err != nil { + return nil, err + } + } } - - // Check for explicit dns-search domain of '' - if c.Changed("dns-search") && len(c.StringSlice("dns-search")) == 0 { - return nil, errors.Errorf("'' is not a valid domain") + if c.IsSet("dns") { + dnsServers = append(dnsServers, c.StringSlice("dns")...) } - - // Validate domains are good - for _, dom := range c.StringSlice("dns-search") { - if dom == "." { - continue - } - if _, err := parse.ValidateDomain(dom); err != nil { - return nil, err - } + if c.IsSet("dns-opt") { + dnsOptions = c.StringSlice("dns-opt") } var ImageVolumes map[string]struct{} @@ -676,7 +717,7 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. pidsLimit := c.Int64("pids-limit") if c.String("cgroups") == "disabled" && !c.Changed("pids-limit") { - pidsLimit = 0 + pidsLimit = -1 } pid := &cc.PidConfig{ @@ -706,11 +747,10 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. HostAdd: c.StringSlice("add-host"), Hostname: c.String("hostname"), } - net := &cc.NetworkConfig{ - DNSOpt: c.StringSlice("dns-opt"), - DNSSearch: c.StringSlice("dns-search"), - DNSServers: c.StringSlice("dns"), + DNSOpt: dnsOptions, + DNSSearch: dnsSearches, + DNSServers: dnsServers, HTTPProxy: c.Bool("http-proxy"), MacAddress: c.String("mac-address"), Network: c.String("network"), @@ -721,9 +761,12 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. PortBindings: portBindings, } - sysctl, err := validateSysctl(c.StringSlice("sysctl")) - if err != nil { - return nil, errors.Wrapf(err, "invalid value for sysctl") + sysctl := map[string]string{} + if c.Changed("sysctl") { + sysctl, err = util.ValidateSysctls(c.StringSlice("sysctl")) + if err != nil { + return nil, errors.Wrapf(err, "invalid value for sysctl") + } } secConfig := &cc.SecurityConfig{ @@ -735,8 +778,10 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. Sysctl: sysctl, } - if err := secConfig.SetSecurityOpts(runtime, c.StringArray("security-opt")); err != nil { - return nil, err + if c.Changed("security-opt") { + if err := secConfig.SetSecurityOpts(runtime, c.StringArray("security-opt")); err != nil { + return nil, err + } } // SECCOMP @@ -750,6 +795,19 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. } else { secConfig.SeccompPolicy = policy } + rtc, err := runtime.GetConfig() + if err != nil { + return nil, err + } + volumes := rtc.Containers.Volumes + if c.Changed("volume") { + volumes = append(volumes, c.StringSlice("volume")...) + } + + devices := rtc.Containers.Devices + if c.Changed("device") { + devices = append(devices, c.StringSlice("device")...) + } config := &cc.CreateConfig{ Annotations: annotations, @@ -760,15 +818,16 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. Command: command, UserCommand: userCommand, Detach: c.Bool("detach"), - Devices: c.StringSlice("device"), + Devices: devices, Entrypoint: entrypoint, Env: env, // ExposedPorts: ports, - Init: c.Bool("init"), - InitPath: c.String("init-path"), - Image: imageName, - ImageID: imageID, - Interactive: c.Bool("interactive"), + Init: c.Bool("init"), + InitPath: c.String("init-path"), + Image: imageName, + RawImageName: rawImageName, + ImageID: imageID, + Interactive: c.Bool("interactive"), // IP6Address: c.String("ipv6"), // Not implemented yet - needs CNI support for static v6 Labels: labels, // LinkLocalIP: c.StringSlice("link-local-ip"), // Not implemented yet @@ -814,7 +873,7 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. Tmpfs: c.StringArray("tmpfs"), Tty: tty, MountsFlag: c.StringArray("mount"), - Volumes: c.StringArray("volume"), + Volumes: volumes, WorkDir: workDir, Rootfs: rootfs, VolumesFrom: c.StringSlice("volumes-from"), diff --git a/cmd/podman/shared/funcs_linux_test.go b/cmd/podman/shared/funcs_linux_test.go new file mode 100644 index 000000000..88571153f --- /dev/null +++ b/cmd/podman/shared/funcs_linux_test.go @@ -0,0 +1,119 @@ +package shared + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGenerateCommand(t *testing.T) { + inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo \"hello world\"" + correctCommand := "/proc/self/exe run -it --name bar -e NAME=bar -e IMAGE=foo foo echo hello world" + newCommand, err := GenerateCommand(inputCommand, "foo", "bar", "") + assert.Nil(t, err) + assert.Equal(t, "hello world", newCommand[11]) + assert.Equal(t, correctCommand, strings.Join(newCommand, " ")) +} + +func TestGenerateCommandCheckSubstitution(t *testing.T) { + type subsTest struct { + input string + expected string + shouldFail bool + } + + absTmpFile, err := ioutil.TempFile("", "podmanRunlabelTestAbsolutePath") + assert.Nil(t, err, "error creating tempfile") + defer os.Remove(absTmpFile.Name()) + + relTmpFile, err := ioutil.TempFile("./", "podmanRunlabelTestRelativePath") + assert.Nil(t, err, "error creating tempfile") + defer os.Remove(relTmpFile.Name()) + relTmpCmd, err := filepath.Abs(relTmpFile.Name()) + assert.Nil(t, err, "error getting absolute path for relative tmpfile") + + // this has a (low) potential of race conditions but no other way + removedTmpFile, err := ioutil.TempFile("", "podmanRunlabelTestRemove") + assert.Nil(t, err, "error creating tempfile") + os.Remove(removedTmpFile.Name()) + + absTmpCmd := fmt.Sprintf("%s --flag1 --flag2 --args=foo", absTmpFile.Name()) + tests := []subsTest{ + { + input: "docker run -it alpine:latest", + expected: "/proc/self/exe run -it alpine:latest", + shouldFail: false, + }, + { + input: "podman run -it alpine:latest", + expected: "/proc/self/exe run -it alpine:latest", + shouldFail: false, + }, + { + input: absTmpCmd, + expected: absTmpCmd, + shouldFail: false, + }, + { + input: "./" + relTmpFile.Name(), + expected: relTmpCmd, + shouldFail: false, + }, + { + input: "ls -la", + expected: "ls -la", + shouldFail: false, + }, + { + input: removedTmpFile.Name(), + expected: "", + shouldFail: true, + }, + } + + for _, test := range tests { + newCommand, err := GenerateCommand(test.input, "foo", "bar", "") + if test.shouldFail { + assert.NotNil(t, err) + } else { + assert.Nil(t, err) + } + assert.Equal(t, test.expected, strings.Join(newCommand, " ")) + } +} + +func TestGenerateCommandPath(t *testing.T) { + inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install" + correctCommand := "/proc/self/exe run -it --name bar -e NAME=bar -e IMAGE=foo foo echo install" + newCommand, _ := GenerateCommand(inputCommand, "foo", "bar", "") + assert.Equal(t, correctCommand, strings.Join(newCommand, " ")) +} + +func TestGenerateCommandNoSetName(t *testing.T) { + inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install" + correctCommand := "/proc/self/exe run -it --name foo -e NAME=foo -e IMAGE=foo foo echo install" + newCommand, err := GenerateCommand(inputCommand, "foo", "", "") + assert.Nil(t, err) + assert.Equal(t, correctCommand, strings.Join(newCommand, " ")) +} + +func TestGenerateCommandNoName(t *testing.T) { + inputCommand := "docker run -it -e IMAGE=IMAGE IMAGE echo install" + correctCommand := "/proc/self/exe run -it -e IMAGE=foo foo echo install" + newCommand, err := GenerateCommand(inputCommand, "foo", "", "") + assert.Nil(t, err) + assert.Equal(t, correctCommand, strings.Join(newCommand, " ")) +} + +func TestGenerateCommandAlreadyPodman(t *testing.T) { + inputCommand := "podman run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install" + correctCommand := "/proc/self/exe run -it --name bar -e NAME=bar -e IMAGE=foo foo echo install" + newCommand, err := GenerateCommand(inputCommand, "foo", "bar", "") + assert.Nil(t, err) + assert.Equal(t, correctCommand, strings.Join(newCommand, " ")) +} diff --git a/cmd/podman/shared/funcs_test.go b/cmd/podman/shared/funcs_test.go index c05348242..dd856166e 100644 --- a/cmd/podman/shared/funcs_test.go +++ b/cmd/podman/shared/funcs_test.go @@ -1,11 +1,6 @@ package shared import ( - "fmt" - "io/ioutil" - "os" - "path/filepath" - "strings" "testing" "github.com/containers/libpod/pkg/util" @@ -17,113 +12,6 @@ var ( imageName = "bar" ) -func TestGenerateCommand(t *testing.T) { - inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo \"hello world\"" - correctCommand := "/proc/self/exe run -it --name bar -e NAME=bar -e IMAGE=foo foo echo hello world" - newCommand, err := GenerateCommand(inputCommand, "foo", "bar", "") - assert.Nil(t, err) - assert.Equal(t, "hello world", newCommand[11]) - assert.Equal(t, correctCommand, strings.Join(newCommand, " ")) -} - -func TestGenerateCommandCheckSubstitution(t *testing.T) { - type subsTest struct { - input string - expected string - shouldFail bool - } - - absTmpFile, err := ioutil.TempFile("", "podmanRunlabelTestAbsolutePath") - assert.Nil(t, err, "error creating tempfile") - defer os.Remove(absTmpFile.Name()) - - relTmpFile, err := ioutil.TempFile("./", "podmanRunlabelTestRelativePath") - assert.Nil(t, err, "error creating tempfile") - defer os.Remove(relTmpFile.Name()) - relTmpCmd, err := filepath.Abs(relTmpFile.Name()) - assert.Nil(t, err, "error getting absolute path for relative tmpfile") - - // this has a (low) potential of race conditions but no other way - removedTmpFile, err := ioutil.TempFile("", "podmanRunlabelTestRemove") - assert.Nil(t, err, "error creating tempfile") - os.Remove(removedTmpFile.Name()) - - absTmpCmd := fmt.Sprintf("%s --flag1 --flag2 --args=foo", absTmpFile.Name()) - tests := []subsTest{ - { - input: "docker run -it alpine:latest", - expected: "/proc/self/exe run -it alpine:latest", - shouldFail: false, - }, - { - input: "podman run -it alpine:latest", - expected: "/proc/self/exe run -it alpine:latest", - shouldFail: false, - }, - { - input: absTmpCmd, - expected: absTmpCmd, - shouldFail: false, - }, - { - input: "./" + relTmpFile.Name(), - expected: relTmpCmd, - shouldFail: false, - }, - { - input: "ls -la", - expected: "ls -la", - shouldFail: false, - }, - { - input: removedTmpFile.Name(), - expected: "", - shouldFail: true, - }, - } - - for _, test := range tests { - newCommand, err := GenerateCommand(test.input, "foo", "bar", "") - if test.shouldFail { - assert.NotNil(t, err) - } else { - assert.Nil(t, err) - } - assert.Equal(t, test.expected, strings.Join(newCommand, " ")) - } -} - -func TestGenerateCommandPath(t *testing.T) { - inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install" - correctCommand := "/proc/self/exe run -it --name bar -e NAME=bar -e IMAGE=foo foo echo install" - newCommand, _ := GenerateCommand(inputCommand, "foo", "bar", "") - assert.Equal(t, correctCommand, strings.Join(newCommand, " ")) -} - -func TestGenerateCommandNoSetName(t *testing.T) { - inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install" - correctCommand := "/proc/self/exe run -it --name foo -e NAME=foo -e IMAGE=foo foo echo install" - newCommand, err := GenerateCommand(inputCommand, "foo", "", "") - assert.Nil(t, err) - assert.Equal(t, correctCommand, strings.Join(newCommand, " ")) -} - -func TestGenerateCommandNoName(t *testing.T) { - inputCommand := "docker run -it -e IMAGE=IMAGE IMAGE echo install" - correctCommand := "/proc/self/exe run -it -e IMAGE=foo foo echo install" - newCommand, err := GenerateCommand(inputCommand, "foo", "", "") - assert.Nil(t, err) - assert.Equal(t, correctCommand, strings.Join(newCommand, " ")) -} - -func TestGenerateCommandAlreadyPodman(t *testing.T) { - inputCommand := "podman run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install" - correctCommand := "/proc/self/exe run -it --name bar -e NAME=bar -e IMAGE=foo foo echo install" - newCommand, err := GenerateCommand(inputCommand, "foo", "bar", "") - assert.Nil(t, err) - assert.Equal(t, correctCommand, strings.Join(newCommand, " ")) -} - func TestGenerateRunEnvironment(t *testing.T) { opts := make(map[string]string) opts["opt1"] = "one" diff --git a/cmd/podman/shared/intermediate_varlink.go b/cmd/podman/shared/intermediate_varlink.go index 691c4f92d..d2b048025 100644 --- a/cmd/podman/shared/intermediate_varlink.go +++ b/cmd/podman/shared/intermediate_varlink.go @@ -316,6 +316,7 @@ func intFromVarlink(v *int64, flagName string, defaultValue *int) CRInt { // structure. func VarlinkCreateToGeneric(opts iopodman.Create) GenericCLIResults { + defaultContainerConfig := cliconfig.GetDefaultConfig() // TODO | WARN // We do not get a default network over varlink. Unlike the other default values for some cli // elements, it seems it gets set to the default anyway. @@ -405,7 +406,7 @@ func VarlinkCreateToGeneric(opts iopodman.Create) GenericCLIResults { m["rm"] = boolFromVarlink(opts.Rm, "rm", false) m["rootfs"] = boolFromVarlink(opts.Rootfs, "rootfs", false) m["security-opt"] = stringArrayFromVarlink(opts.SecurityOpt, "security-opt", nil) - m["shm-size"] = stringFromVarlink(opts.ShmSize, "shm-size", &cliconfig.DefaultShmSize) + m["shm-size"] = stringFromVarlink(opts.ShmSize, "shm-size", &defaultContainerConfig.Containers.ShmSize) m["stop-signal"] = stringFromVarlink(opts.StopSignal, "stop-signal", nil) m["stop-timeout"] = uintFromVarlink(opts.StopTimeout, "stop-timeout", nil) m["storage-opt"] = stringSliceFromVarlink(opts.StorageOpt, "storage-opt", nil) diff --git a/cmd/podman/shared/pod.go b/cmd/podman/shared/pod.go index 7b0b497fc..50bd88e08 100644 --- a/cmd/podman/shared/pod.go +++ b/cmd/podman/shared/pod.go @@ -2,9 +2,11 @@ package shared import ( "strconv" + "strings" "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/define" + "github.com/containers/libpod/pkg/util" "github.com/cri-o/ocicni/pkg/ocicni" "github.com/docker/go-connections/nat" "github.com/pkg/errors" @@ -134,4 +136,144 @@ func CreatePortBindings(ports []string) ([]ocicni.PortMapping, error) { return portBindings, nil } +// GetPodsWithFilters uses the cliconfig to categorize if the latest pod is required. +func GetPodsWithFilters(r *libpod.Runtime, filters string) ([]*libpod.Pod, error) { + filterFuncs, err := GenerateFilterFunction(r, strings.Split(filters, ",")) + if err != nil { + return nil, err + } + return FilterAllPodsWithFilterFunc(r, filterFuncs...) +} + +// FilterAllPodsWithFilterFunc retrieves all pods +// Filters can be provided which will determine which pods are included in the +// output. Multiple filters are handled by ANDing their output, so only pods +// matching all filters are returned +func FilterAllPodsWithFilterFunc(r *libpod.Runtime, filters ...libpod.PodFilter) ([]*libpod.Pod, error) { + pods, err := r.Pods(filters...) + if err != nil { + return nil, err + } + return pods, nil +} + +// GenerateFilterFunction basically gets the filters based on the input by the user +// and filter the pod list based on the criteria. +func GenerateFilterFunction(r *libpod.Runtime, filters []string) ([]libpod.PodFilter, error) { + var filterFuncs []libpod.PodFilter + for _, f := range filters { + filterSplit := strings.SplitN(f, "=", 2) + if len(filterSplit) < 2 { + return nil, errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f) + } + generatedFunc, err := generatePodFilterFuncs(filterSplit[0], filterSplit[1]) + if err != nil { + return nil, errors.Wrapf(err, "invalid filter") + } + filterFuncs = append(filterFuncs, generatedFunc) + } + + return filterFuncs, nil +} +func generatePodFilterFuncs(filter, filterValue string) ( + func(pod *libpod.Pod) bool, error) { + switch filter { + case "ctr-ids": + return func(p *libpod.Pod) bool { + ctrIds, err := p.AllContainersByID() + if err != nil { + return false + } + return util.StringInSlice(filterValue, ctrIds) + }, nil + case "ctr-names": + return func(p *libpod.Pod) bool { + ctrs, err := p.AllContainers() + if err != nil { + return false + } + for _, ctr := range ctrs { + if filterValue == ctr.Name() { + return true + } + } + return false + }, nil + case "ctr-number": + return func(p *libpod.Pod) bool { + ctrIds, err := p.AllContainersByID() + if err != nil { + return false + } + + fVint, err2 := strconv.Atoi(filterValue) + if err2 != nil { + return false + } + return len(ctrIds) == fVint + }, nil + case "ctr-status": + if !util.StringInSlice(filterValue, + []string{"created", "restarting", "running", "paused", + "exited", "unknown"}) { + return nil, errors.Errorf("%s is not a valid status", filterValue) + } + return func(p *libpod.Pod) bool { + ctr_statuses, err := p.Status() + if err != nil { + return false + } + for _, ctr_status := range ctr_statuses { + state := ctr_status.String() + if ctr_status == define.ContainerStateConfigured { + state = "created" + } + if state == filterValue { + return true + } + } + return false + }, nil + case "id": + return func(p *libpod.Pod) bool { + return strings.Contains(p.ID(), filterValue) + }, nil + case "name": + return func(p *libpod.Pod) bool { + return strings.Contains(p.Name(), filterValue) + }, nil + case "status": + if !util.StringInSlice(filterValue, []string{"stopped", "running", "paused", "exited", "dead", "created"}) { + return nil, errors.Errorf("%s is not a valid pod status", filterValue) + } + return func(p *libpod.Pod) bool { + status, err := p.GetPodStatus() + if err != nil { + return false + } + if strings.ToLower(status) == filterValue { + return true + } + return false + }, nil + case "label": + var filterArray = strings.SplitN(filterValue, "=", 2) + var filterKey = filterArray[0] + if len(filterArray) > 1 { + filterValue = filterArray[1] + } else { + filterValue = "" + } + return func(p *libpod.Pod) bool { + for labelKey, labelValue := range p.Labels() { + if labelKey == filterKey && ("" == filterValue || labelValue == filterValue) { + return true + } + } + return false + }, nil + } + return nil, errors.Errorf("%s is an invalid filter", filter) +} + var DefaultKernelNamespaces = "cgroup,ipc,net,uts" diff --git a/cmd/podman/sign.go b/cmd/podman/sign.go index 8ac59b33b..7da3459cf 100644 --- a/cmd/podman/sign.go +++ b/cmd/podman/sign.go @@ -126,19 +126,14 @@ func signCmd(c *cliconfig.SignValues) error { if err != nil { return err } - newImage, err := runtime.ImageRuntime().New(getContext(), signimage, rtc.SignaturePolicyPath, "", os.Stderr, &dockerRegistryOptions, image.SigningOptions{SignBy: signby}, nil, util.PullImageMissing) + newImage, err := runtime.ImageRuntime().New(getContext(), signimage, rtc.Engine.SignaturePolicyPath, "", os.Stderr, &dockerRegistryOptions, image.SigningOptions{SignBy: signby}, nil, util.PullImageMissing) if err != nil { return errors.Wrapf(err, "error pulling image %s", signimage) } if rootless.IsRootless() { if sigStoreDir == "" { - runtimeConfig, err := runtime.GetConfig() - if err != nil { - return err - } - - sigStoreDir = filepath.Join(filepath.Dir(runtimeConfig.StorageConfig.GraphRoot), "sigstore") + sigStoreDir = filepath.Join(filepath.Dir(runtime.StorageConfig().GraphRoot), "sigstore") } } else { registryInfo := trust.HaveMatchRegistry(rawSource.Reference().DockerReference().String(), registryConfigs) diff --git a/cmd/podman/start.go b/cmd/podman/start.go index a070cd18d..ee700032f 100644 --- a/cmd/podman/start.go +++ b/cmd/podman/start.go @@ -35,10 +35,7 @@ func init() { startCommand.SetUsageTemplate(UsageTemplate()) flags := startCommand.Flags() flags.BoolVarP(&startCommand.Attach, "attach", "a", false, "Attach container's STDOUT and STDERR") - // Clear the default, the value specified in the config file should have the - // priority - startCommand.DetachKeys = "" - flags.StringVar(&startCommand.DetachKeys, "detach-keys", define.DefaultDetachKeys, "Select the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`") + flags.StringVar(&startCommand.DetachKeys, "detach-keys", getDefaultDetachKeys(), "Select the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`") flags.BoolVarP(&startCommand.Interactive, "interactive", "i", false, "Keep STDIN open even if not attached") flags.BoolVarP(&startCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of") flags.BoolVar(&startCommand.SigProxy, "sig-proxy", false, "Proxy received signals to the process (default true if attaching, false otherwise)") diff --git a/cmd/podman/stop.go b/cmd/podman/stop.go index c62da80df..383a1f61c 100644 --- a/cmd/podman/stop.go +++ b/cmd/podman/stop.go @@ -2,7 +2,6 @@ package main import ( "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/adapter" "github.com/opentracing/opentracing-go" "github.com/pkg/errors" @@ -29,7 +28,7 @@ var ( }, Example: `podman stop ctrID podman stop --latest - podman stop --timeout 2 mywebserver 6e534f14da9d`, + podman stop --time 2 mywebserver 6e534f14da9d`, } ) @@ -42,8 +41,9 @@ func init() { flags.BoolVarP(&stopCommand.Ignore, "ignore", "i", false, "Ignore errors when a specified container is missing") flags.StringArrayVarP(&stopCommand.CIDFiles, "cidfile", "", nil, "Read the container ID from the file") flags.BoolVarP(&stopCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - flags.UintVar(&stopCommand.Timeout, "time", define.CtrRemoveTimeout, "Seconds to wait for stop before killing the container") - flags.UintVarP(&stopCommand.Timeout, "timeout", "t", define.CtrRemoveTimeout, "Seconds to wait for stop before killing the container") + flags.UintVarP(&stopCommand.Timeout, "time", "t", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container") + flags.UintVar(&stopCommand.Timeout, "timeout", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container") + markFlagHidden(flags, "timeout") markFlagHiddenForRemoteClient("latest", flags) markFlagHiddenForRemoteClient("cidfile", flags) markFlagHiddenForRemoteClient("ignore", flags) diff --git a/cmd/podman/unshare.go b/cmd/podman/unshare.go index 31ce441f4..28d17a319 100644 --- a/cmd/podman/unshare.go +++ b/cmd/podman/unshare.go @@ -66,13 +66,8 @@ func unshareCmd(c *cliconfig.PodmanCommand) error { if err != nil { return err } - runtimeConfig, err := runtime.GetConfig() - if err != nil { - return err - } - cmd := exec.Command(c.InputArgs[0], c.InputArgs[1:]...) - cmd.Env = unshareEnv(runtimeConfig.StorageConfig.GraphRoot, runtimeConfig.StorageConfig.RunRoot) + cmd.Env = unshareEnv(runtime.StorageConfig().GraphRoot, runtime.StorageConfig().RunRoot) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink index e9792fa8f..0cb95ef97 100644 --- a/cmd/podman/varlink/io.podman.varlink +++ b/cmd/podman/varlink/io.podman.varlink @@ -105,6 +105,11 @@ type ImageSearchFilter ( star_count: int ) +type AuthConfig ( + username: string, + password: string +) + type KubePodService ( pod: string, service: string @@ -409,6 +414,8 @@ type BuildOptions ( # BuildInfo is used to describe user input for building images type BuildInfo ( + architecture: string, + addCapabilities: []string, additionalTags: []string, annotations: []string, buildArgs: [string]string, @@ -418,13 +425,16 @@ type BuildInfo ( compression: string, contextDir: string, defaultsMountFilePath: string, + devices: []string, dockerfiles: []string, + dropCapabilities: []string, err: string, forceRmIntermediateCtrs: bool, iidfile: string, label: []string, layers: bool, nocache: bool, + os: string, out: string, output: string, outputFormat: string, @@ -433,7 +443,10 @@ type BuildInfo ( remoteIntermediateCtrs: bool, reportWriter: string, runtimeArgs: []string, - squash: bool + signBy: string, + squash: bool, + target: string, + transientMounts: []string ) # MoreResponse is a struct for when responses from varlink requires longer output @@ -932,7 +945,7 @@ method ExportImage(name: string, destination: string, compress: bool, tags: []st # PullImage pulls an image from a repository to local storage. After a successful pull, the image id and logs # are returned as a [MoreResponse](#MoreResponse). This connection also will handle a WantsMores request to send # status as it occurs. -method PullImage(name: string) -> (reply: MoreResponse) +method PullImage(name: string, creds: AuthConfig) -> (reply: MoreResponse) # CreatePod creates a new empty pod. It uses a [PodCreate](#PodCreate) type for input. # On success, the ID of the newly created pod will be returned. |