aboutsummaryrefslogtreecommitdiff
path: root/cmd/podman/common
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podman/common')
-rw-r--r--cmd/podman/common/completion.go70
-rw-r--r--cmd/podman/common/completion_test.go2
-rw-r--r--cmd/podman/common/create.go61
-rw-r--r--cmd/podman/common/create_opts.go491
-rw-r--r--cmd/podman/common/diffChanges.go3
-rw-r--r--cmd/podman/common/netflags.go27
6 files changed, 117 insertions, 537 deletions
diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go
index 5eef5f982..89e53c180 100644
--- a/cmd/podman/common/completion.go
+++ b/cmd/podman/common/completion.go
@@ -71,7 +71,7 @@ func setupImageEngine(cmd *cobra.Command) (entities.ImageEngine, error) {
return nil, err
}
// we also need to set up the container engine since this
- // is required to setup the rootless namespace
+ // is required to set up the rootless namespace
if _, err = setupContainerEngine(cmd); err != nil {
return nil, err
}
@@ -284,7 +284,16 @@ func getNetworks(cmd *cobra.Command, toComplete string, cType completeType) ([]s
return suggestions, cobra.ShellCompDirectiveNoFileComp
}
-func getPathCompletion(root string, toComplete string) []string {
+func fdIsNotDir(f *os.File) bool {
+ stat, err := f.Stat()
+ if err != nil {
+ cobra.CompErrorln(err.Error())
+ return true
+ }
+ return !stat.IsDir()
+}
+
+func getPathCompletion(root string, toComplete string) ([]string, cobra.ShellCompDirective) {
if toComplete == "" {
toComplete = "/"
}
@@ -292,41 +301,61 @@ func getPathCompletion(root string, toComplete string) []string {
userpath, err := securejoin.SecureJoin(root, toComplete)
if err != nil {
cobra.CompErrorln(err.Error())
- return nil
+ return nil, cobra.ShellCompDirectiveDefault
}
var base string
f, err := os.Open(userpath)
- if err != nil {
+ // when error or file is not dir get the parent path to stat
+ if err != nil || fdIsNotDir(f) {
// Do not use path.Dir() since this cleans the paths which
// then no longer matches the user input.
userpath, base = path.Split(userpath)
toComplete, _ = path.Split(toComplete)
f, err = os.Open(userpath)
if err != nil {
- return nil
+ return nil, cobra.ShellCompDirectiveDefault
}
}
- stat, err := f.Stat()
- if err != nil {
- cobra.CompErrorln(err.Error())
- return nil
- }
- if !stat.IsDir() {
+
+ if fdIsNotDir(f) {
// nothing to complete since it is no dir
- return nil
+ return nil, cobra.ShellCompDirectiveDefault
}
+
entries, err := f.ReadDir(-1)
if err != nil {
cobra.CompErrorln(err.Error())
- return nil
+ return nil, cobra.ShellCompDirectiveDefault
+ }
+ if len(entries) == 0 {
+ // path is empty dir, just add the trailing slash and no space
+ if !strings.HasSuffix(toComplete, "/") {
+ toComplete += "/"
+ }
+ return []string{toComplete}, cobra.ShellCompDirectiveDefault | cobra.ShellCompDirectiveNoSpace
}
completions := make([]string, 0, len(entries))
+ count := 0
for _, e := range entries {
if strings.HasPrefix(e.Name(), base) {
- completions = append(completions, simplePathJoinUnix(toComplete, e.Name()))
+ suf := ""
+ // When the entry is an directory we add the "/" as suffix and do not want to add space
+ // to match normal shell completion behavior.
+ // Just inc counter again to fake more than one entry in this case and thus get no space.
+ if e.IsDir() {
+ suf = "/"
+ count++
+ }
+ completions = append(completions, simplePathJoinUnix(toComplete, e.Name()+suf))
+ count++
}
}
- return completions
+ directive := cobra.ShellCompDirectiveDefault
+ if count > 1 {
+ // when we have more than one match we do not want to add a space after the completion
+ directive |= cobra.ShellCompDirectiveNoSpace
+ }
+ return completions, directive
}
// simplePathJoinUnix joins to path components by adding a slash only if p1 doesn't end with one.
@@ -605,7 +634,7 @@ func AutocompleteCreateRun(cmd *cobra.Command, args []string, toComplete string)
// So this uses ShellCompDirectiveDefault to also still provide normal shell
// completion in case no path matches. This is useful if someone tries to get
// completion for paths that are not available in the image, e.g. /proc/...
- return getPathCompletion(resp[0].Path, toComplete), cobra.ShellCompDirectiveDefault | cobra.ShellCompDirectiveNoSpace
+ return getPathCompletion(resp[0].Path, toComplete)
}
// AutocompleteRegistries - Autocomplete registries.
@@ -676,7 +705,8 @@ func AutocompleteCpCommand(cmd *cobra.Command, args []string, toComplete string)
if len(resp) != 1 {
return nil, cobra.ShellCompDirectiveDefault
}
- return prefixSlice(toComplete[:i+1], getPathCompletion(resp[0].Path, toComplete[i+1:])), cobra.ShellCompDirectiveDefault | cobra.ShellCompDirectiveNoSpace
+ comps, directive := getPathCompletion(resp[0].Path, toComplete[i+1:])
+ return prefixSlice(toComplete[:i+1], comps), directive
}
// Suggest containers when they match the input otherwise normal shell completion is used
containers, _ := getContainers(cmd, toComplete, completeDefault)
@@ -1577,8 +1607,14 @@ func AutocompleteClone(cmd *cobra.Command, args []string, toComplete string) ([]
}
switch len(args) {
case 0:
+ if cmd.Parent().Name() == "pod" { // needs to be " pod " to exclude 'podman'
+ return getPods(cmd, toComplete, completeDefault)
+ }
return getContainers(cmd, toComplete, completeDefault)
case 2:
+ if cmd.Parent().Name() == "pod" {
+ return nil, cobra.ShellCompDirectiveNoFileComp
+ }
return getImages(cmd, toComplete)
}
return nil, cobra.ShellCompDirectiveNoFileComp
diff --git a/cmd/podman/common/completion_test.go b/cmd/podman/common/completion_test.go
index ae23b02e2..d8be48ad7 100644
--- a/cmd/podman/common/completion_test.go
+++ b/cmd/podman/common/completion_test.go
@@ -50,7 +50,7 @@ func (c *Car) Color() string {
}
// This is for reflect testing required.
-// nolint:unused
+//nolint:unused
func (c Car) internal() int {
return 0
}
diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go
index f89035be3..f05549a8d 100644
--- a/cmd/podman/common/create.go
+++ b/cmd/podman/common/create.go
@@ -98,7 +98,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
cgroupsFlagName := "cgroups"
createFlags.StringVar(
&cf.CgroupsMode,
- cgroupsFlagName, cgroupConfig(),
+ cgroupsFlagName, cf.CgroupsMode,
`control container cgroup configuration ("enabled"|"disabled"|"no-conmon"|"split")`,
)
_ = cmd.RegisterFlagCompletionFunc(cgroupsFlagName, AutocompleteCgroupMode)
@@ -150,7 +150,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
envFlagName := "env"
createFlags.StringArrayP(
- envFlagName, "e", env(),
+ envFlagName, "e", Env(),
"Set environment variables in container",
)
_ = cmd.RegisterFlagCompletionFunc(envFlagName, completion.AutocompleteNone)
@@ -256,7 +256,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
imageVolumeFlagName := "image-volume"
createFlags.String(
- imageVolumeFlagName, containerConfig.Engine.ImageVolumeMode,
+ imageVolumeFlagName, cf.ImageVolume,
`Tells podman how to handle the builtin image volumes ("bind"|"tmpfs"|"ignore")`,
)
_ = cmd.RegisterFlagCompletionFunc(imageVolumeFlagName, AutocompleteImageVolume)
@@ -298,7 +298,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
logDriverFlagName := "log-driver"
createFlags.StringVar(
&cf.LogDriver,
- logDriverFlagName, LogDriver(),
+ logDriverFlagName, cf.LogDriver,
"Logging driver for the container",
)
_ = cmd.RegisterFlagCompletionFunc(logDriverFlagName, AutocompleteLogDriver)
@@ -389,7 +389,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
pullFlagName := "pull"
createFlags.StringVar(
&cf.Pull,
- pullFlagName, policy(),
+ pullFlagName, cf.Pull,
`Pull image before creating ("always"|"missing"|"never")`,
)
_ = cmd.RegisterFlagCompletionFunc(pullFlagName, AutocompletePullOption)
@@ -406,7 +406,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
)
createFlags.BoolVar(
&cf.ReadOnlyTmpFS,
- "read-only-tmpfs", true,
+ "read-only-tmpfs", cf.ReadOnlyTmpFS,
"When running containers in read-only mode mount a read-write tmpfs on /run, /tmp and /var/tmp",
)
requiresFlagName := "requires"
@@ -439,7 +439,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
sdnotifyFlagName := "sdnotify"
createFlags.StringVar(
&cf.SdNotifyMode,
- sdnotifyFlagName, define.SdNotifyModeContainer,
+ sdnotifyFlagName, cf.SdNotifyMode,
`control sd-notify behavior ("container"|"conmon"|"ignore")`,
)
_ = cmd.RegisterFlagCompletionFunc(sdnotifyFlagName, AutocompleteSDNotify)
@@ -452,13 +452,6 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
)
_ = cmd.RegisterFlagCompletionFunc(secretFlagName, AutocompleteSecrets)
- shmSizeFlagName := "shm-size"
- createFlags.String(
- shmSizeFlagName, shmSize(),
- "Size of /dev/shm "+sizeWithUnitFormat,
- )
- _ = cmd.RegisterFlagCompletionFunc(shmSizeFlagName, completion.AutocompleteNone)
-
stopSignalFlagName := "stop-signal"
createFlags.StringVar(
&cf.StopSignal,
@@ -470,7 +463,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
stopTimeoutFlagName := "stop-timeout"
createFlags.UintVar(
&cf.StopTimeout,
- stopTimeoutFlagName, containerConfig.Engine.StopTimeout,
+ stopTimeoutFlagName, cf.StopTimeout,
"Timeout (in seconds) that containers stopped by user command have to exit. If exceeded, the container will be forcibly stopped via SIGKILL.",
)
_ = cmd.RegisterFlagCompletionFunc(stopTimeoutFlagName, completion.AutocompleteNone)
@@ -478,7 +471,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
systemdFlagName := "systemd"
createFlags.StringVar(
&cf.Systemd,
- systemdFlagName, "true",
+ systemdFlagName, cf.Systemd,
`Run container in systemd mode ("true"|"false"|"always")`,
)
_ = cmd.RegisterFlagCompletionFunc(systemdFlagName, AutocompleteSystemdFlag)
@@ -522,7 +515,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
timezoneFlagName := "tz"
createFlags.StringVar(
&cf.Timezone,
- timezoneFlagName, containerConfig.TZ(),
+ timezoneFlagName, cf.Timezone,
"Set timezone in container",
)
_ = cmd.RegisterFlagCompletionFunc(timezoneFlagName, completion.AutocompleteNone) //TODO: add timezone completion
@@ -530,7 +523,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
umaskFlagName := "umask"
createFlags.StringVar(
&cf.Umask,
- umaskFlagName, containerConfig.Umask(),
+ umaskFlagName, cf.Umask,
"Set umask in container",
)
_ = cmd.RegisterFlagCompletionFunc(umaskFlagName, completion.AutocompleteNone)
@@ -538,7 +531,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
ulimitFlagName := "ulimit"
createFlags.StringSliceVar(
&cf.Ulimit,
- ulimitFlagName, ulimits(),
+ ulimitFlagName, cf.Ulimit,
"Ulimit options",
)
_ = cmd.RegisterFlagCompletionFunc(ulimitFlagName, completion.AutocompleteNone)
@@ -577,7 +570,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
seccompPolicyFlagName := "seccomp-policy"
createFlags.StringVar(
&cf.SeccompPolicy,
- seccompPolicyFlagName, "default",
+ seccompPolicyFlagName, cf.SeccompPolicy,
"Policy for selecting a seccomp profile (experimental)",
)
_ = cmd.RegisterFlagCompletionFunc(seccompPolicyFlagName, completion.AutocompleteDefault)
@@ -628,6 +621,13 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
)
}
if isInfra || (!clone && !isInfra) { // infra container flags, create should also pick these up
+ shmSizeFlagName := "shm-size"
+ createFlags.String(
+ shmSizeFlagName, shmSize(),
+ "Size of /dev/shm "+sizeWithUnitFormat,
+ )
+ _ = cmd.RegisterFlagCompletionFunc(shmSizeFlagName, completion.AutocompleteNone)
+
sysctlFlagName := "sysctl"
createFlags.StringSliceVar(
&cf.Sysctl,
@@ -769,7 +769,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
volumeFlagName := "volume"
createFlags.StringArrayVarP(
&cf.Volume,
- volumeFlagName, "v", volumes(),
+ volumeFlagName, "v", cf.Volume,
volumeDesciption,
)
_ = cmd.RegisterFlagCompletionFunc(volumeFlagName, AutocompleteVolumeFlag)
@@ -863,14 +863,6 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
)
_ = cmd.RegisterFlagCompletionFunc(cpusetMemsFlagName, completion.AutocompleteNone)
- memoryFlagName := "memory"
- createFlags.StringVarP(
- &cf.Memory,
- memoryFlagName, "m", "",
- "Memory limit "+sizeWithUnitFormat,
- )
- _ = cmd.RegisterFlagCompletionFunc(memoryFlagName, completion.AutocompleteNone)
-
memoryReservationFlagName := "memory-reservation"
createFlags.StringVar(
&cf.MemoryReservation,
@@ -890,12 +882,13 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
memorySwappinessFlagName := "memory-swappiness"
createFlags.Int64Var(
&cf.MemorySwappiness,
- memorySwappinessFlagName, -1,
+ memorySwappinessFlagName, cf.MemorySwappiness,
"Tune container memory swappiness (0 to 100, or -1 for system default)",
)
_ = cmd.RegisterFlagCompletionFunc(memorySwappinessFlagName, completion.AutocompleteNone)
}
// anyone can use these
+
cpusFlagName := "cpus"
createFlags.Float64Var(
&cf.CPUS,
@@ -911,4 +904,12 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
"CPUs in which to allow execution (0-3, 0,1)",
)
_ = cmd.RegisterFlagCompletionFunc(cpusetCpusFlagName, completion.AutocompleteNone)
+
+ memoryFlagName := "memory"
+ createFlags.StringVarP(
+ &cf.Memory,
+ memoryFlagName, "m", "",
+ "Memory limit "+sizeWithUnitFormat,
+ )
+ _ = cmd.RegisterFlagCompletionFunc(memoryFlagName, completion.AutocompleteNone)
}
diff --git a/cmd/podman/common/create_opts.go b/cmd/podman/common/create_opts.go
index c40d1ea51..fb5af8f59 100644
--- a/cmd/podman/common/create_opts.go
+++ b/cmd/podman/common/create_opts.go
@@ -1,472 +1,11 @@
package common
import (
- "fmt"
- "net"
- "os"
- "path/filepath"
- "strconv"
- "strings"
-
- "github.com/containers/common/libnetwork/types"
- "github.com/containers/common/pkg/cgroups"
- "github.com/containers/common/pkg/config"
"github.com/containers/podman/v4/cmd/podman/registry"
"github.com/containers/podman/v4/libpod/define"
- "github.com/containers/podman/v4/pkg/api/handlers"
"github.com/containers/podman/v4/pkg/domain/entities"
- "github.com/containers/podman/v4/pkg/rootless"
- "github.com/containers/podman/v4/pkg/specgen"
- "github.com/docker/docker/api/types/mount"
- "github.com/pkg/errors"
)
-func stringMaptoArray(m map[string]string) []string {
- a := make([]string, 0, len(m))
- for k, v := range m {
- a = append(a, fmt.Sprintf("%s=%s", k, v))
- }
- return a
-}
-
-// ContainerCreateToContainerCLIOpts converts a compat input struct to cliopts so it can be converted to
-// a specgen spec.
-func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, rtc *config.Config) (*entities.ContainerCreateOptions, []string, error) {
- var (
- capAdd []string
- cappDrop []string
- entrypoint *string
- init bool
- specPorts []types.PortMapping
- )
-
- if cc.HostConfig.Init != nil {
- init = *cc.HostConfig.Init
- }
-
- // Iterate devices and convert back to string
- devices := make([]string, 0, len(cc.HostConfig.Devices))
- for _, dev := range cc.HostConfig.Devices {
- devices = append(devices, fmt.Sprintf("%s:%s:%s", dev.PathOnHost, dev.PathInContainer, dev.CgroupPermissions))
- }
-
- // iterate blkreaddevicebps
- readBps := make([]string, 0, len(cc.HostConfig.BlkioDeviceReadBps))
- for _, dev := range cc.HostConfig.BlkioDeviceReadBps {
- readBps = append(readBps, dev.String())
- }
-
- // iterate blkreaddeviceiops
- readIops := make([]string, 0, len(cc.HostConfig.BlkioDeviceReadIOps))
- for _, dev := range cc.HostConfig.BlkioDeviceReadIOps {
- readIops = append(readIops, dev.String())
- }
-
- // iterate blkwritedevicebps
- writeBps := make([]string, 0, len(cc.HostConfig.BlkioDeviceWriteBps))
- for _, dev := range cc.HostConfig.BlkioDeviceWriteBps {
- writeBps = append(writeBps, dev.String())
- }
-
- // iterate blkwritedeviceiops
- writeIops := make([]string, 0, len(cc.HostConfig.BlkioDeviceWriteIOps))
- for _, dev := range cc.HostConfig.BlkioDeviceWriteIOps {
- writeIops = append(writeIops, dev.String())
- }
-
- // entrypoint
- // can be a string or slice. if it is a slice, we need to
- // marshall it to json; otherwise it should just be the string
- // value
- if len(cc.Config.Entrypoint) > 0 {
- entrypoint = &cc.Config.Entrypoint[0]
- if len(cc.Config.Entrypoint) > 1 {
- b, err := json.Marshal(cc.Config.Entrypoint)
- if err != nil {
- return nil, nil, err
- }
- var jsonString = string(b)
- entrypoint = &jsonString
- }
- }
-
- // expose ports
- expose := make([]string, 0, len(cc.Config.ExposedPorts))
- for p := range cc.Config.ExposedPorts {
- expose = append(expose, fmt.Sprintf("%s/%s", p.Port(), p.Proto()))
- }
-
- // mounts type=tmpfs/bind,source=...,target=...=,opt=val
- volSources := make(map[string]bool)
- volDestinations := make(map[string]bool)
- mounts := make([]string, 0, len(cc.HostConfig.Mounts))
- var builder strings.Builder
- for _, m := range cc.HostConfig.Mounts {
- addField(&builder, "type", string(m.Type))
- addField(&builder, "source", m.Source)
- addField(&builder, "target", m.Target)
-
- // Store source/dest so we don't add duplicates if a volume is
- // also mentioned in cc.Volumes.
- // Which Docker Compose v2.0 does, for unclear reasons...
- volSources[m.Source] = true
- volDestinations[m.Target] = true
-
- if m.ReadOnly {
- addField(&builder, "ro", "true")
- }
- addField(&builder, "consistency", string(m.Consistency))
- // Map any specialized mount options that intersect between *Options and cli options
- switch m.Type {
- case mount.TypeBind:
- if m.BindOptions != nil {
- addField(&builder, "bind-propagation", string(m.BindOptions.Propagation))
- addField(&builder, "bind-nonrecursive", strconv.FormatBool(m.BindOptions.NonRecursive))
- }
- case mount.TypeTmpfs:
- if m.TmpfsOptions != nil {
- addField(&builder, "tmpfs-size", strconv.FormatInt(m.TmpfsOptions.SizeBytes, 10))
- addField(&builder, "tmpfs-mode", strconv.FormatUint(uint64(m.TmpfsOptions.Mode), 8))
- }
- case mount.TypeVolume:
- // All current VolumeOpts are handled above
- // See vendor/github.com/containers/common/pkg/parse/parse.go:ValidateVolumeOpts()
- }
- mounts = append(mounts, builder.String())
- builder.Reset()
- }
-
- // dns
- dns := make([]net.IP, 0, len(cc.HostConfig.DNS))
- for _, d := range cc.HostConfig.DNS {
- dns = append(dns, net.ParseIP(d))
- }
-
- // publish
- for port, pbs := range cc.HostConfig.PortBindings {
- for _, pb := range pbs {
- var hostport int
- var err error
- if pb.HostPort != "" {
- hostport, err = strconv.Atoi(pb.HostPort)
- }
- if err != nil {
- return nil, nil, err
- }
- tmpPort := types.PortMapping{
- HostIP: pb.HostIP,
- ContainerPort: uint16(port.Int()),
- HostPort: uint16(hostport),
- Range: 0,
- Protocol: port.Proto(),
- }
- specPorts = append(specPorts, tmpPort)
- }
- }
-
- // special case for NetworkMode, the podman default is slirp4netns for
- // rootless but for better docker compat we want bridge.
- netmode := string(cc.HostConfig.NetworkMode)
- if netmode == "" || netmode == "default" {
- netmode = "bridge"
- }
- nsmode, networks, netOpts, err := specgen.ParseNetworkFlag([]string{netmode})
- if err != nil {
- return nil, nil, err
- }
-
- // network
- // Note: we cannot emulate compat exactly here. we only allow specifics of networks to be
- // defined when there is only one network.
- netInfo := entities.NetOptions{
- AddHosts: cc.HostConfig.ExtraHosts,
- DNSOptions: cc.HostConfig.DNSOptions,
- DNSSearch: cc.HostConfig.DNSSearch,
- DNSServers: dns,
- Network: nsmode,
- PublishPorts: specPorts,
- NetworkOptions: netOpts,
- NoHosts: rtc.Containers.NoHosts,
- }
-
- // network names
- switch {
- case len(cc.NetworkingConfig.EndpointsConfig) > 0:
- endpointsConfig := cc.NetworkingConfig.EndpointsConfig
- networks := make(map[string]types.PerNetworkOptions, len(endpointsConfig))
- for netName, endpoint := range endpointsConfig {
- netOpts := types.PerNetworkOptions{}
- if endpoint != nil {
- netOpts.Aliases = endpoint.Aliases
-
- // if IP address is provided
- if len(endpoint.IPAddress) > 0 {
- staticIP := net.ParseIP(endpoint.IPAddress)
- if staticIP == nil {
- return nil, nil, errors.Errorf("failed to parse the ip address %q", endpoint.IPAddress)
- }
- netOpts.StaticIPs = append(netOpts.StaticIPs, staticIP)
- }
-
- if endpoint.IPAMConfig != nil {
- // if IPAMConfig.IPv4Address is provided
- if len(endpoint.IPAMConfig.IPv4Address) > 0 {
- staticIP := net.ParseIP(endpoint.IPAMConfig.IPv4Address)
- if staticIP == nil {
- return nil, nil, errors.Errorf("failed to parse the ipv4 address %q", endpoint.IPAMConfig.IPv4Address)
- }
- netOpts.StaticIPs = append(netOpts.StaticIPs, staticIP)
- }
- // if IPAMConfig.IPv6Address is provided
- if len(endpoint.IPAMConfig.IPv6Address) > 0 {
- staticIP := net.ParseIP(endpoint.IPAMConfig.IPv6Address)
- if staticIP == nil {
- return nil, nil, errors.Errorf("failed to parse the ipv6 address %q", endpoint.IPAMConfig.IPv6Address)
- }
- netOpts.StaticIPs = append(netOpts.StaticIPs, staticIP)
- }
- }
- // If MAC address is provided
- if len(endpoint.MacAddress) > 0 {
- staticMac, err := net.ParseMAC(endpoint.MacAddress)
- if err != nil {
- return nil, nil, errors.Errorf("failed to parse the mac address %q", endpoint.MacAddress)
- }
- netOpts.StaticMAC = types.HardwareAddr(staticMac)
- }
- }
-
- networks[netName] = netOpts
- }
-
- netInfo.Networks = networks
- case len(cc.HostConfig.NetworkMode) > 0:
- netInfo.Networks = networks
- }
-
- 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
- cliOpts := entities.ContainerCreateOptions{
- // Attach: nil, // don't need?
- Authfile: "",
- CapAdd: append(capAdd, cc.HostConfig.CapAdd...),
- CapDrop: append(cappDrop, cc.HostConfig.CapDrop...),
- CgroupParent: cc.HostConfig.CgroupParent,
- CIDFile: cc.HostConfig.ContainerIDFile,
- CPUPeriod: uint64(cc.HostConfig.CPUPeriod),
- CPUQuota: cc.HostConfig.CPUQuota,
- CPURTPeriod: uint64(cc.HostConfig.CPURealtimePeriod),
- CPURTRuntime: cc.HostConfig.CPURealtimeRuntime,
- CPUShares: uint64(cc.HostConfig.CPUShares),
- // CPUS: 0, // don't need?
- CPUSetCPUs: cc.HostConfig.CpusetCpus,
- CPUSetMems: cc.HostConfig.CpusetMems,
- // Detach: false, // don't need
- // DetachKeys: "", // don't need
- Devices: devices,
- DeviceCgroupRule: nil,
- DeviceReadBPs: readBps,
- DeviceReadIOPs: readIops,
- DeviceWriteBPs: writeBps,
- DeviceWriteIOPs: writeIops,
- Entrypoint: entrypoint,
- Env: cc.Config.Env,
- Expose: expose,
- GroupAdd: cc.HostConfig.GroupAdd,
- Hostname: cc.Config.Hostname,
- ImageVolume: "bind",
- Init: init,
- Interactive: cc.Config.OpenStdin,
- IPC: string(cc.HostConfig.IpcMode),
- Label: stringMaptoArray(cc.Config.Labels),
- LogDriver: cc.HostConfig.LogConfig.Type,
- LogOptions: stringMaptoArray(cc.HostConfig.LogConfig.Config),
- Name: cc.Name,
- OOMScoreAdj: &cc.HostConfig.OomScoreAdj,
- Arch: "",
- OS: "",
- Variant: "",
- PID: string(cc.HostConfig.PidMode),
- PIDsLimit: cc.HostConfig.PidsLimit,
- Privileged: cc.HostConfig.Privileged,
- PublishAll: cc.HostConfig.PublishAllPorts,
- Quiet: false,
- ReadOnly: cc.HostConfig.ReadonlyRootfs,
- ReadOnlyTmpFS: true, // podman default
- Rm: cc.HostConfig.AutoRemove,
- SecurityOpt: cc.HostConfig.SecurityOpt,
- StopSignal: cc.Config.StopSignal,
- StorageOpts: stringMaptoArray(cc.HostConfig.StorageOpt),
- Sysctl: stringMaptoArray(cc.HostConfig.Sysctls),
- Systemd: "true", // podman default
- TmpFS: parsedTmp,
- TTY: cc.Config.Tty,
- UnsetEnv: cc.UnsetEnv,
- UnsetEnvAll: cc.UnsetEnvAll,
- User: cc.Config.User,
- UserNS: string(cc.HostConfig.UsernsMode),
- UTS: string(cc.HostConfig.UTSMode),
- Mount: mounts,
- VolumesFrom: cc.HostConfig.VolumesFrom,
- Workdir: cc.Config.WorkingDir,
- Net: &netInfo,
- HealthInterval: define.DefaultHealthCheckInterval,
- HealthRetries: define.DefaultHealthCheckRetries,
- HealthTimeout: define.DefaultHealthCheckTimeout,
- HealthStartPeriod: define.DefaultHealthCheckStartPeriod,
- }
- if !rootless.IsRootless() {
- var ulimits []string
- if len(cc.HostConfig.Ulimits) > 0 {
- for _, ul := range cc.HostConfig.Ulimits {
- ulimits = append(ulimits, ul.String())
- }
- 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
- for _, vol := range cc.HostConfig.Binds {
- cliOpts.Volume = append(cliOpts.Volume, vol)
- // Extract the destination so we don't add duplicate mounts in
- // the volumes phase.
- splitVol := specgen.SplitVolumeString(vol)
- switch len(splitVol) {
- case 1:
- volDestinations[vol] = true
- default:
- volSources[splitVol[0]] = true
- volDestinations[splitVol[1]] = true
- }
- }
- // Anonymous volumes are added differently from other volumes, in their
- // own special field, for reasons known only to Docker. Still use the
- // format of `-v` so we can just append them in there.
- // Unfortunately, these may be duplicates of existing mounts in Binds.
- // So... We need to catch that.
- // This also handles volumes duplicated between cc.HostConfig.Mounts and
- // cc.Volumes, as seen in compose v2.0.
- for vol := range cc.Volumes {
- if _, ok := volDestinations[filepath.Clean(vol)]; ok {
- continue
- }
- 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 {
- devices = append(devices, d.String())
- }
- cliOpts.BlkIOWeightDevice = devices
- }
- if cc.HostConfig.BlkioWeight > 0 {
- cliOpts.BlkIOWeight = strconv.Itoa(int(cc.HostConfig.BlkioWeight))
- }
-
- if cc.HostConfig.Memory > 0 {
- cliOpts.Memory = strconv.Itoa(int(cc.HostConfig.Memory))
- }
-
- if cc.HostConfig.MemoryReservation > 0 {
- cliOpts.MemoryReservation = strconv.Itoa(int(cc.HostConfig.MemoryReservation))
- }
-
- cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
- if err != nil {
- return nil, nil, err
- }
- if cc.HostConfig.MemorySwap > 0 && (!rootless.IsRootless() || (rootless.IsRootless() && cgroupsv2)) {
- cliOpts.MemorySwap = strconv.Itoa(int(cc.HostConfig.MemorySwap))
- }
-
- if cc.Config.StopTimeout != nil {
- cliOpts.StopTimeout = uint(*cc.Config.StopTimeout)
- }
-
- if cc.HostConfig.ShmSize > 0 {
- cliOpts.ShmSize = strconv.Itoa(int(cc.HostConfig.ShmSize))
- }
-
- if len(cc.HostConfig.RestartPolicy.Name) > 0 {
- policy := cc.HostConfig.RestartPolicy.Name
- // only add restart count on failure
- if cc.HostConfig.RestartPolicy.IsOnFailure() {
- policy += fmt.Sprintf(":%d", cc.HostConfig.RestartPolicy.MaximumRetryCount)
- }
- cliOpts.Restart = policy
- }
-
- if cc.HostConfig.MemorySwappiness != nil && (!rootless.IsRootless() || rootless.IsRootless() && cgroupsv2 && rtc.Engine.CgroupManager == "systemd") {
- cliOpts.MemorySwappiness = *cc.HostConfig.MemorySwappiness
- } else {
- cliOpts.MemorySwappiness = -1
- }
- if cc.HostConfig.OomKillDisable != nil {
- cliOpts.OOMKillDisable = *cc.HostConfig.OomKillDisable
- }
- if cc.Config.Healthcheck != nil {
- finCmd := ""
- for _, str := range cc.Config.Healthcheck.Test {
- finCmd = finCmd + str + " "
- }
- if len(finCmd) > 1 {
- finCmd = finCmd[:len(finCmd)-1]
- }
- cliOpts.HealthCmd = finCmd
- if cc.Config.Healthcheck.Interval > 0 {
- cliOpts.HealthInterval = cc.Config.Healthcheck.Interval.String()
- }
- if cc.Config.Healthcheck.Retries > 0 {
- cliOpts.HealthRetries = uint(cc.Config.Healthcheck.Retries)
- }
- if cc.Config.Healthcheck.StartPeriod > 0 {
- cliOpts.HealthStartPeriod = cc.Config.Healthcheck.StartPeriod.String()
- }
- if cc.Config.Healthcheck.Timeout > 0 {
- cliOpts.HealthTimeout = cc.Config.Healthcheck.Timeout.String()
- }
- }
-
- // specgen assumes the image name is arg[0]
- cmd := []string{cc.Config.Image}
- cmd = append(cmd, cc.Config.Cmd...)
- return &cliOpts, cmd, nil
-}
-
func ulimits() []string {
if !registry.IsRemote() {
return containerConfig.Ulimits()
@@ -488,7 +27,7 @@ func devices() []string {
return nil
}
-func env() []string {
+func Env() []string {
if !registry.IsRemote() {
return containerConfig.Env()
}
@@ -537,16 +76,20 @@ func LogDriver() string {
return ""
}
-// addField is a helper function to populate mount options
-func addField(b *strings.Builder, name string, value string) {
- if value == "" {
- return
- }
-
- if b.Len() > 0 {
- b.WriteRune(',')
- }
- b.WriteString(name)
- b.WriteRune('=')
- b.WriteString(value)
+// DefineCreateDefault is used to initialize ctr create options before flag initialization
+func DefineCreateDefaults(opts *entities.ContainerCreateOptions) {
+ opts.LogDriver = LogDriver()
+ opts.CgroupsMode = cgroupConfig()
+ opts.MemorySwappiness = -1
+ opts.ImageVolume = containerConfig.Engine.ImageVolumeMode
+ opts.Pull = policy()
+ opts.ReadOnlyTmpFS = true
+ opts.SdNotifyMode = define.SdNotifyModeContainer
+ opts.StopTimeout = containerConfig.Engine.StopTimeout
+ opts.Systemd = "true"
+ opts.Timezone = containerConfig.TZ()
+ opts.Umask = containerConfig.Umask()
+ opts.Ulimit = ulimits()
+ opts.SeccompPolicy = "default"
+ opts.Volume = volumes()
}
diff --git a/cmd/podman/common/diffChanges.go b/cmd/podman/common/diffChanges.go
index 99b5f1dcd..6d4c7154a 100644
--- a/cmd/podman/common/diffChanges.go
+++ b/cmd/podman/common/diffChanges.go
@@ -6,7 +6,6 @@ import (
"github.com/containers/podman/v4/pkg/domain/entities"
"github.com/containers/storage/pkg/archive"
- "github.com/pkg/errors"
)
type ChangesReportJSON struct {
@@ -26,7 +25,7 @@ func ChangesToJSON(diffs *entities.DiffReport) error {
case archive.ChangeModify:
body.Changed = append(body.Changed, row.Path)
default:
- return errors.Errorf("output kind %q not recognized", row.Kind)
+ return fmt.Errorf("output kind %q not recognized", row.Kind)
}
}
diff --git a/cmd/podman/common/netflags.go b/cmd/podman/common/netflags.go
index 9dfe81d62..e7aa265d1 100644
--- a/cmd/podman/common/netflags.go
+++ b/cmd/podman/common/netflags.go
@@ -1,6 +1,8 @@
package common
import (
+ "errors"
+ "fmt"
"net"
"github.com/containers/common/libnetwork/types"
@@ -10,7 +12,6 @@ import (
"github.com/containers/podman/v4/pkg/domain/entities"
"github.com/containers/podman/v4/pkg/specgen"
"github.com/containers/podman/v4/pkg/specgenutil"
- "github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
@@ -125,13 +126,13 @@ func NetFlagsToNetOptions(opts *entities.NetOptions, flags pflag.FlagSet) (*enti
if d == "none" {
opts.UseImageResolvConf = true
if len(servers) > 1 {
- return nil, errors.Errorf("%s is not allowed to be specified with other DNS ip addresses", d)
+ return nil, fmt.Errorf("%s is not allowed to be specified with other DNS ip addresses", d)
}
break
}
dns := net.ParseIP(d)
if dns == nil {
- return nil, errors.Errorf("%s is not an ip address", d)
+ return nil, fmt.Errorf("%s is not an ip address", d)
}
opts.DNSServers = append(opts.DNSServers, dns)
}
@@ -154,7 +155,7 @@ func NetFlagsToNetOptions(opts *entities.NetOptions, flags pflag.FlagSet) (*enti
for _, dom := range dnsSearches {
if dom == "." {
if len(dnsSearches) > 1 {
- return nil, errors.Errorf("cannot pass additional search domains when also specifying '.'")
+ return nil, errors.New("cannot pass additional search domains when also specifying '.'")
}
continue
}
@@ -218,18 +219,18 @@ func NetFlagsToNetOptions(opts *entities.NetOptions, flags pflag.FlagSet) (*enti
if ip != "" {
// if pod create --infra=false
if infra, err := flags.GetBool("infra"); err == nil && !infra {
- return nil, errors.Wrapf(define.ErrInvalidArg, "cannot set --%s without infra container", ipFlagName)
+ return nil, fmt.Errorf("cannot set --%s without infra container: %w", ipFlagName, define.ErrInvalidArg)
}
staticIP := net.ParseIP(ip)
if staticIP == nil {
- return nil, errors.Errorf("%q is not an ip address", ip)
+ return nil, fmt.Errorf("%q is not an ip address", ip)
}
if !opts.Network.IsBridge() && !opts.Network.IsDefault() {
- return nil, errors.Wrapf(define.ErrInvalidArg, "--%s can only be set when the network mode is bridge", ipFlagName)
+ return nil, fmt.Errorf("--%s can only be set when the network mode is bridge: %w", ipFlagName, define.ErrInvalidArg)
}
if len(opts.Networks) != 1 {
- return nil, errors.Wrapf(define.ErrInvalidArg, "--%s can only be set for a single network", ipFlagName)
+ return nil, fmt.Errorf("--%s can only be set for a single network: %w", ipFlagName, define.ErrInvalidArg)
}
for name, netOpts := range opts.Networks {
netOpts.StaticIPs = append(netOpts.StaticIPs, staticIP)
@@ -245,17 +246,17 @@ func NetFlagsToNetOptions(opts *entities.NetOptions, flags pflag.FlagSet) (*enti
if len(m) > 0 {
// if pod create --infra=false
if infra, err := flags.GetBool("infra"); err == nil && !infra {
- return nil, errors.Wrap(define.ErrInvalidArg, "cannot set --mac without infra container")
+ return nil, fmt.Errorf("cannot set --mac without infra container: %w", define.ErrInvalidArg)
}
mac, err := net.ParseMAC(m)
if err != nil {
return nil, err
}
if !opts.Network.IsBridge() && !opts.Network.IsDefault() {
- return nil, errors.Wrap(define.ErrInvalidArg, "--mac-address can only be set when the network mode is bridge")
+ return nil, fmt.Errorf("--mac-address can only be set when the network mode is bridge: %w", define.ErrInvalidArg)
}
if len(opts.Networks) != 1 {
- return nil, errors.Wrap(define.ErrInvalidArg, "--mac-address can only be set for a single network")
+ return nil, fmt.Errorf("--mac-address can only be set for a single network: %w", define.ErrInvalidArg)
}
for name, netOpts := range opts.Networks {
netOpts.StaticMAC = types.HardwareAddr(mac)
@@ -270,10 +271,10 @@ func NetFlagsToNetOptions(opts *entities.NetOptions, flags pflag.FlagSet) (*enti
if len(aliases) > 0 {
// if pod create --infra=false
if infra, err := flags.GetBool("infra"); err == nil && !infra {
- return nil, errors.Wrap(define.ErrInvalidArg, "cannot set --network-alias without infra container")
+ return nil, fmt.Errorf("cannot set --network-alias without infra container: %w", define.ErrInvalidArg)
}
if !opts.Network.IsBridge() && !opts.Network.IsDefault() {
- return nil, errors.Wrap(define.ErrInvalidArg, "--network-alias can only be set when the network mode is bridge")
+ return nil, fmt.Errorf("--network-alias can only be set when the network mode is bridge: %w", define.ErrInvalidArg)
}
for name, netOpts := range opts.Networks {
netOpts.Aliases = aliases