diff options
32 files changed, 456 insertions, 274 deletions
diff --git a/cmd/podman/common/create_opts.go b/cmd/podman/common/create_opts.go index 83a25f4ab..f4fecf4b7 100644 --- a/cmd/podman/common/create_opts.go +++ b/cmd/podman/common/create_opts.go @@ -1,6 +1,15 @@ package common -import "github.com/containers/podman/v2/pkg/domain/entities" +import ( + "fmt" + "net" + "strconv" + "strings" + + "github.com/containers/podman/v2/pkg/api/handlers" + "github.com/containers/podman/v2/pkg/domain/entities" + "github.com/containers/podman/v2/pkg/specgen" +) type ContainerCLIOpts struct { Annotation []string @@ -111,3 +120,283 @@ type ContainerCLIOpts struct { CgroupConf []string } + +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) (*ContainerCLIOpts, []string, error) { + var ( + capAdd []string + cappDrop []string + entrypoint string + init bool + specPorts []specgen.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 + } + entrypoint = string(b) + } + } + + // 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=,dest=,opt=val + // TODO options + mounts := make([]string, 0, len(cc.HostConfig.Mounts)) + for _, m := range cc.HostConfig.Mounts { + mount := fmt.Sprintf("type=%s", m.Type) + if len(m.Source) > 0 { + mount += fmt.Sprintf("source=%s", m.Source) + } + if len(m.Target) > 0 { + mount += fmt.Sprintf("dest=%s", m.Target) + } + mounts = append(mounts, mount) + } + + //volumes + volumes := make([]string, 0, len(cc.Config.Volumes)) + for v := range cc.Config.Volumes { + volumes = append(volumes, v) + } + + // 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 { + hostport, err := strconv.Atoi(pb.HostPort) + if err != nil { + return nil, nil, err + } + tmpPort := specgen.PortMapping{ + HostIP: pb.HostIP, + ContainerPort: uint16(port.Int()), + HostPort: uint16(hostport), + Range: 0, + Protocol: port.Proto(), + } + specPorts = append(specPorts, tmpPort) + } + } + + // network names + endpointsConfig := cc.NetworkingConfig.EndpointsConfig + cniNetworks := make([]string, 0, len(endpointsConfig)) + for netName := range endpointsConfig { + cniNetworks = append(cniNetworks, netName) + } + + // netMode + nsmode, _, err := specgen.ParseNetworkNamespace(cc.HostConfig.NetworkMode.NetworkName()) + if err != nil { + return nil, nil, err + } + + netNS := specgen.Namespace{ + NSMode: nsmode.NSMode, + Value: nsmode.Value, + } + + // 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, + CNINetworks: cniNetworks, + DNSOptions: cc.HostConfig.DNSOptions, + DNSSearch: cc.HostConfig.DNSSearch, + DNSServers: dns, + Network: netNS, + PublishPorts: specPorts, + } + + // static IP and MAC + if len(endpointsConfig) == 1 { + for _, ep := range endpointsConfig { + // if IP address is provided + if len(ep.IPAddress) > 0 { + staticIP := net.ParseIP(ep.IPAddress) + netInfo.StaticIP = &staticIP + } + // If MAC address is provided + if len(ep.MacAddress) > 0 { + staticMac, err := net.ParseMAC(ep.MacAddress) + if err != nil { + return nil, nil, err + } + netInfo.StaticMAC = &staticMac + } + break + } + } + + // 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 := ContainerCLIOpts{ + //Attach: nil, // dont need? + Authfile: "", + BlkIOWeight: strconv.Itoa(int(cc.HostConfig.BlkioWeight)), + BlkIOWeightDevice: nil, // TODO + 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, // dont need? + CPUSetCPUs: cc.HostConfig.CpusetCpus, + CPUSetMems: cc.HostConfig.CpusetMems, + //Detach: false, // dont need + //DetachKeys: "", // dont 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), + Memory: strconv.Itoa(int(cc.HostConfig.Memory)), + MemoryReservation: strconv.Itoa(int(cc.HostConfig.MemoryReservation)), + MemorySwap: strconv.Itoa(int(cc.HostConfig.MemorySwap)), + Name: cc.Name, + OOMScoreAdj: cc.HostConfig.OomScoreAdj, + OverrideArch: "", + OverrideOS: "", + OverrideVariant: "", + 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, + ShmSize: strconv.Itoa(int(cc.HostConfig.ShmSize)), + StopSignal: cc.Config.StopSignal, + StoreageOpt: stringMaptoArray(cc.HostConfig.StorageOpt), + Sysctl: stringMaptoArray(cc.HostConfig.Sysctls), + Systemd: "true", // podman default + TmpFS: stringMaptoArray(cc.HostConfig.Tmpfs), + TTY: cc.Config.Tty, + //Ulimit: cc.HostConfig.Ulimits, // ask dan, no documented format + User: cc.Config.User, + UserNS: string(cc.HostConfig.UsernsMode), + UTS: string(cc.HostConfig.UTSMode), + Mount: mounts, + Volume: volumes, + VolumesFrom: cc.HostConfig.VolumesFrom, + Workdir: cc.Config.WorkingDir, + Net: &netInfo, + } + + if cc.Config.StopTimeout != nil { + cliOpts.StopTimeout = uint(*cc.Config.StopTimeout) + } + + if cc.HostConfig.KernelMemory > 0 { + cliOpts.KernelMemory = strconv.Itoa(int(cc.HostConfig.KernelMemory)) + } + 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 { + cliOpts.MemorySwappiness = *cc.HostConfig.MemorySwappiness + } + if cc.HostConfig.OomKillDisable != nil { + cliOpts.OOMKillDisable = *cc.HostConfig.OomKillDisable + } + if cc.Config.Healthcheck != nil { + cliOpts.HealthCmd = strings.Join(cc.Config.Healthcheck.Test, " ") + cliOpts.HealthInterval = cc.Config.Healthcheck.Interval.String() + cliOpts.HealthRetries = uint(cc.Config.Healthcheck.Retries) + cliOpts.HealthStartPeriod = cc.Config.Healthcheck.StartPeriod.String() + cliOpts.HealthTimeout = cc.Config.Healthcheck.Timeout.String() + } + + // specgen assumes the image name is arg[0] + cmd := []string{cc.Image} + cmd = append(cmd, cc.Config.Cmd...) + return &cliOpts, cmd, nil +} diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go index 809162e76..eb96e22b5 100644 --- a/cmd/podman/containers/create.go +++ b/cmd/podman/containers/create.go @@ -63,7 +63,6 @@ func createFlags(flags *pflag.FlagSet) { _ = flags.MarkHidden("signature-policy") if registry.IsRemote() { - _ = flags.MarkHidden("authfile") _ = flags.MarkHidden("http-proxy") } } diff --git a/cmd/podman/containers/run.go b/cmd/podman/containers/run.go index 19c984bbf..cca0e8d1c 100644 --- a/cmd/podman/containers/run.go +++ b/cmd/podman/containers/run.go @@ -66,7 +66,6 @@ func runFlags(flags *pflag.FlagSet) { _ = flags.MarkHidden("signature-policy") if registry.IsRemote() { - _ = flags.MarkHidden("authfile") _ = flags.MarkHidden("http-proxy") _ = flags.MarkHidden("preserve-fds") } diff --git a/cmd/podman/images/pull.go b/cmd/podman/images/pull.go index 448543b4d..595a2165e 100644 --- a/cmd/podman/images/pull.go +++ b/cmd/podman/images/pull.go @@ -84,11 +84,11 @@ func pullFlags(flags *pflag.FlagSet) { flags.Bool("disable-content-trust", false, "This is a Docker specific option and is a NOOP") flags.BoolVarP(&pullOptions.Quiet, "quiet", "q", false, "Suppress output information when pulling images") flags.StringVar(&pullOptions.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)") + flags.BoolVar(&pullOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries") + flags.StringVar(&pullOptions.Authfile, "authfile", auth.GetDefaultAuthFile(), "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override") if !registry.IsRemote() { - flags.StringVar(&pullOptions.Authfile, "authfile", auth.GetDefaultAuthFile(), "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override") flags.StringVar(&pullOptions.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys") - flags.BoolVar(&pullOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries") } _ = flags.MarkHidden("signature-policy") } diff --git a/cmd/podman/images/push.go b/cmd/podman/images/push.go index 2943cccc9..24192eccd 100644 --- a/cmd/podman/images/push.go +++ b/cmd/podman/images/push.go @@ -88,11 +88,9 @@ func pushFlags(flags *pflag.FlagSet) { flags.BoolVar(&pushOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries") if registry.IsRemote() { - _ = flags.MarkHidden("authfile") _ = flags.MarkHidden("cert-dir") _ = flags.MarkHidden("compress") _ = flags.MarkHidden("quiet") - _ = flags.MarkHidden("tls-verify") } _ = flags.MarkHidden("signature-policy") } diff --git a/cmd/podman/manifest/add.go b/cmd/podman/manifest/add.go index 128bf66a7..544d99c11 100644 --- a/cmd/podman/manifest/add.go +++ b/cmd/podman/manifest/add.go @@ -56,9 +56,7 @@ func init() { flags.StringVar(&manifestAddOpts.Variant, "variant", "", "override the `Variant` of the specified image") if registry.IsRemote() { - _ = flags.MarkHidden("authfile") _ = flags.MarkHidden("cert-dir") - _ = flags.MarkHidden("tls-verify") } } diff --git a/cmd/podman/manifest/push.go b/cmd/podman/manifest/push.go index b43e4531a..fd3d51f37 100644 --- a/cmd/podman/manifest/push.go +++ b/cmd/podman/manifest/push.go @@ -51,9 +51,7 @@ func init() { flags.BoolVarP(&manifestPushOpts.Quiet, "quiet", "q", false, "don't output progress information when pushing lists") if registry.IsRemote() { - _ = flags.MarkHidden("authfile") _ = flags.MarkHidden("cert-dir") - _ = flags.MarkHidden("tls-verify") } } diff --git a/cmd/podman/play/kube.go b/cmd/podman/play/kube.go index 976d720ee..1235f75a8 100644 --- a/cmd/podman/play/kube.go +++ b/cmd/podman/play/kube.go @@ -54,10 +54,10 @@ func init() { flags.StringVar(&kubeOptions.CredentialsCLI, "creds", "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry") flags.StringVar(&kubeOptions.Network, "network", "", "Connect pod to CNI network(s)") flags.BoolVarP(&kubeOptions.Quiet, "quiet", "q", false, "Suppress output information when pulling images") + flags.BoolVar(&kubeOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries") + flags.StringVar(&kubeOptions.Authfile, "authfile", auth.GetDefaultAuthFile(), "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override") if !registry.IsRemote() { - flags.StringVar(&kubeOptions.Authfile, "authfile", auth.GetDefaultAuthFile(), "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override") flags.StringVar(&kubeOptions.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys") - flags.BoolVar(&kubeOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries") flags.StringVar(&kubeOptions.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)") flags.StringVar(&kubeOptions.SeccompProfileRoot, "seccomp-profile-root", defaultSeccompRoot, "Directory path for seccomp profiles") flags.StringSliceVar(&kubeOptions.ConfigMaps, "configmap", []string{}, "`Pathname` of a YAML file containing a kubernetes configmap") diff --git a/docs/source/markdown/podman-auto-update.1.md b/docs/source/markdown/podman-auto-update.1.md index b6941362a..3ab097388 100644 --- a/docs/source/markdown/podman-auto-update.1.md +++ b/docs/source/markdown/podman-auto-update.1.md @@ -31,7 +31,7 @@ Systemd units that start and stop a container cannot run a new image. **--authfile**=*path* Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`. -If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. (Not available for remote commands) +If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE environment variable. `export REGISTRY_AUTH_FILE=path` diff --git a/docs/source/markdown/podman-build.1.md b/docs/source/markdown/podman-build.1.md index 7d0aa5001..821324f84 100644 --- a/docs/source/markdown/podman-build.1.md +++ b/docs/source/markdown/podman-build.1.md @@ -46,7 +46,7 @@ Set the ARCH of the image to the provided value instead of the architecture of t **--authfile**=*path* Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`. -If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. (Not available for remote commands) +If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE environment variable. `export REGISTRY_AUTH_FILE=path` @@ -470,7 +470,7 @@ When --timestamp is set, the created timestamp is always set to the time specifi **--tls-verify**=*true|false* -Require HTTPS and verify certificates when talking to container registries (defaults to true). (Not available for remote commands) +Require HTTPS and verify certificates when talking to container registries (defaults to true). **--ulimit**=*type*=*soft-limit*[:*hard-limit*] diff --git a/docs/source/markdown/podman-container-runlabel.1.md b/docs/source/markdown/podman-container-runlabel.1.md index f56fc7d7b..676ad12d0 100644 --- a/docs/source/markdown/podman-container-runlabel.1.md +++ b/docs/source/markdown/podman-container-runlabel.1.md @@ -44,7 +44,7 @@ Any additional arguments will be appended to the command. **--authfile**=*path* Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`. -If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. (Not available for remote commands) +If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE environment variable. `export REGISTRY_AUTH_FILE=path` @@ -85,7 +85,7 @@ created from this image. Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true, then TLS verification will be used. If set to false, then TLS verification will not be used. If not specified, -TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf (Not available for remote commands) +TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf. ## EXAMPLES diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index 3303ae572..f9a23d314 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -47,7 +47,7 @@ each of stdin, stdout, and stderr. Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE -environment variable. `export REGISTRY_AUTH_FILE=path` (Not available for remote commands) +environment variable. `export REGISTRY_AUTH_FILE=path` **--blkio-weight**=*weight* diff --git a/docs/source/markdown/podman-login.1.md b/docs/source/markdown/podman-login.1.md index 9b4ff74ed..7c09d99fe 100644 --- a/docs/source/markdown/podman-login.1.md +++ b/docs/source/markdown/podman-login.1.md @@ -42,7 +42,7 @@ Username for registry **--authfile**=*path* -Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json (Not available for remote commands) +Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json. Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE environment variable. `export REGISTRY_AUTH_FILE=path` @@ -60,7 +60,7 @@ Default certificates directory is _/etc/containers/certs.d_. (Not available for Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true, then TLS verification will be used. If set to false, then TLS verification will not be used. If not specified, -TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf. (Not available for remote commands) +TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf. **--help**, **-h** diff --git a/docs/source/markdown/podman-logout.1.md b/docs/source/markdown/podman-logout.1.md index 0ff954d43..25f6d97b1 100644 --- a/docs/source/markdown/podman-logout.1.md +++ b/docs/source/markdown/podman-logout.1.md @@ -23,7 +23,7 @@ All the cached credentials can be removed by setting the **all** flag. **--authfile**=*path* -Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json (Not available for remote commands) +Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json. Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE environment variable. `export REGISTRY_AUTH_FILE=path` diff --git a/docs/source/markdown/podman-manifest-add.1.md b/docs/source/markdown/podman-manifest-add.1.md index c4d4417c4..4c0bad2ae 100644 --- a/docs/source/markdown/podman-manifest-add.1.md +++ b/docs/source/markdown/podman-manifest-add.1.md @@ -36,7 +36,7 @@ retrieved from the image's configuration information. **--authfile**=*path* Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`. -If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. (Not available for remote commands) +If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE environment variable. `export REGISTRY_AUTH_FILE=path` @@ -71,7 +71,7 @@ image. This option is rarely used. **--tls-verify** -Require HTTPS and verify certificates when talking to container registries (defaults to true). (Not available for remote commands) +Require HTTPS and verify certificates when talking to container registries (defaults to true). **--variant** diff --git a/docs/source/markdown/podman-manifest-push.1.md b/docs/source/markdown/podman-manifest-push.1.md index 33b2a24c5..9cf0b159c 100644 --- a/docs/source/markdown/podman-manifest-push.1.md +++ b/docs/source/markdown/podman-manifest-push.1.md @@ -22,7 +22,7 @@ the list or index itself. **--authfile**=*path* Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`. -If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. (Not available for remote commands) +If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE environment variable. `export REGISTRY_AUTH_FILE=path` @@ -64,7 +64,7 @@ Sign the pushed images using the GPG key that matches the specified fingerprint. **--tls-verify** -Require HTTPS and verify certificates when talking to container registries (defaults to true) (Not available for remote commands) +Require HTTPS and verify certificates when talking to container registries. (defaults to true) ## EXAMPLE diff --git a/docs/source/markdown/podman-play-kube.1.md b/docs/source/markdown/podman-play-kube.1.md index 00ee7c1df..97b0dc09a 100644 --- a/docs/source/markdown/podman-play-kube.1.md +++ b/docs/source/markdown/podman-play-kube.1.md @@ -20,7 +20,7 @@ Note: HostPath volume types created by play kube will be given an SELinux privat **--authfile**=*path* Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`. -If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. (Not available for remote commands) +If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE environment variable. `export REGISTRY_AUTH_FILE=path` @@ -58,7 +58,7 @@ Directory path for seccomp profiles (default: "/var/lib/kubelet/seccomp"). (Not Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true, then TLS verification will be used. If set to false, then TLS verification will not be used. If not specified, -TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf. (Not available for remote commands) +TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf. **--help**, **-h** diff --git a/docs/source/markdown/podman-pull.1.md b/docs/source/markdown/podman-pull.1.md index c75cb18b4..46beb4c42 100644 --- a/docs/source/markdown/podman-pull.1.md +++ b/docs/source/markdown/podman-pull.1.md @@ -57,7 +57,7 @@ Note: When using the all-tags flag, Podman will not iterate over the search regi **--authfile**=*path* Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`. -If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. (Not available for remote commands) +If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE environment variable. `export REGISTRY_AUTH_FILE=path` @@ -97,7 +97,7 @@ Suppress output information when pulling images Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true, then TLS verification will be used. If set to false, then TLS verification will not be used. If not specified, -TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf. (Not available for remote commands) +TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf. **--help**, **-h** diff --git a/docs/source/markdown/podman-push.1.md b/docs/source/markdown/podman-push.1.md index fffd76801..e9b63dc43 100644 --- a/docs/source/markdown/podman-push.1.md +++ b/docs/source/markdown/podman-push.1.md @@ -46,7 +46,7 @@ Images are pushed from those stored in local image storage. **--authfile**=*path* Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`. -If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. (Not available for remote commands) +If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE environment variable. `export REGISTRY_AUTH_FILE=path` @@ -98,7 +98,7 @@ Add a signature at the destination using the specified key Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true, then TLS verification will be used. If set to false, then TLS verification will not be used. If not specified, -TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf. (Not available for remote commands) +TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf. ## EXAMPLE diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index 9ebf6649b..2c8aa3a26 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -57,7 +57,7 @@ each of **stdin**, **stdout**, and **stderr**. **--authfile**[=*path*] -Path to the authentication file. Default is *${XDG_RUNTIME_DIR}/containers/auth.json*. (Not available for remote commands) +Path to the authentication file. Default is *${XDG_RUNTIME_DIR}/containers/auth.json*. Note: You can also override the default path of the authentication file by setting the **REGISTRY_AUTH_FILE** environment variable. diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index eff390e46..ffb2f5b73 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -1541,11 +1541,31 @@ func (c *Container) getHosts() string { } } - if c.config.NetMode.IsSlirp4netns() { - // When using slirp4netns, the interface gets a static IP - hosts += fmt.Sprintf("# used by slirp4netns\n%s\t%s %s\n", "10.0.2.100", c.Hostname(), c.Config().Name) - } hosts += c.cniHosts() + + // If not making a network namespace, add our own hostname. + if c.Hostname() != "" { + if c.config.NetMode.IsSlirp4netns() { + // When using slirp4netns, the interface gets a static IP + hosts += fmt.Sprintf("# used by slirp4netns\n%s\t%s %s\n", "10.0.2.100", c.Hostname(), c.config.Name) + } else { + hasNetNS := false + for _, ns := range c.config.Spec.Linux.Namespaces { + if ns.Type == spec.NetworkNamespace { + hasNetNS = true + break + } + } + if !hasNetNS { + // 127.0.1.1 and host's hostname to match Docker + osHostname, err := os.Hostname() + if err != nil { + osHostname = c.Hostname() + } + hosts += fmt.Sprintf("127.0.1.1 %s\n", osHostname) + } + } + } return hosts } diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index f87c311ce..df0ff6c32 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -823,6 +823,20 @@ func getContainerNetIO(ctr *Container) (*netlink.LinkStatistics, error) { // Produce an InspectNetworkSettings containing information on the container // network. func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, error) { + if c.config.NetNsCtr != "" { + netNsCtr, err := c.runtime.GetContainer(c.config.NetNsCtr) + if err != nil { + return nil, err + } + // Have to sync to ensure that state is populated + if err := netNsCtr.syncContainer(); err != nil { + return nil, err + } + logrus.Debugf("Container %s shares network namespace, retrieving network info of container %s", c.ID(), c.config.NetNsCtr) + + return netNsCtr.getContainerNetworkInfo() + } + settings := new(define.InspectNetworkSettings) settings.Ports = makeInspectPortBindings(c.config.PortMappings) diff --git a/pkg/api/handlers/compat/containers_create.go b/pkg/api/handlers/compat/containers_create.go index 8a0b3c922..87c95a24c 100644 --- a/pkg/api/handlers/compat/containers_create.go +++ b/pkg/api/handlers/compat/containers_create.go @@ -1,27 +1,19 @@ package compat import ( - "context" "encoding/json" - "fmt" "net/http" - "strings" - "github.com/containers/common/pkg/config" + "github.com/containers/podman/v2/cmd/podman/common" "github.com/containers/podman/v2/libpod" "github.com/containers/podman/v2/libpod/define" - image2 "github.com/containers/podman/v2/libpod/image" "github.com/containers/podman/v2/pkg/api/handlers" "github.com/containers/podman/v2/pkg/api/handlers/utils" - "github.com/containers/podman/v2/pkg/namespaces" - "github.com/containers/podman/v2/pkg/rootless" - "github.com/containers/podman/v2/pkg/signal" - createconfig "github.com/containers/podman/v2/pkg/spec" + "github.com/containers/podman/v2/pkg/domain/entities" + "github.com/containers/podman/v2/pkg/domain/infra/abi" "github.com/containers/podman/v2/pkg/specgen" - "github.com/containers/storage" "github.com/gorilla/schema" "github.com/pkg/errors" - "golang.org/x/sys/unix" ) func CreateContainer(w http.ResponseWriter, r *http.Request) { @@ -56,220 +48,27 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "NewFromLocal()")) return } - containerConfig, err := runtime.GetConfig() + + // Take input structure and convert to cliopts + cliOpts, args, err := common.ContainerCreateToContainerCLIOpts(input) if err != nil { - utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "GetConfig()")) + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "make cli opts()")) return } - cc, err := makeCreateConfig(r.Context(), containerConfig, input, newImage) - if err != nil { - utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "makeCreatConfig()")) + sg := specgen.NewSpecGenerator(newImage.ID(), cliOpts.RootFS) + if err := common.FillOutSpecGen(sg, cliOpts, args); err != nil { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "fill out specgen")) return } - cc.Name = query.Name - utils.CreateContainer(r.Context(), w, runtime, &cc) -} - -func makeCreateConfig(ctx context.Context, containerConfig *config.Config, input handlers.CreateContainerConfig, newImage *image2.Image) (createconfig.CreateConfig, error) { - var ( - err error - init bool - ) - env := make(map[string]string) - stopSignal := unix.SIGTERM - if len(input.StopSignal) > 0 { - stopSignal, err = signal.ParseSignal(input.StopSignal) - if err != nil { - return createconfig.CreateConfig{}, err - } - } - - workDir, err := newImage.WorkingDir(ctx) + ic := abi.ContainerEngine{Libpod: runtime} + report, err := ic.ContainerCreate(r.Context(), sg) if err != nil { - return createconfig.CreateConfig{}, err - } - if workDir == "" { - workDir = "/" - } - if len(input.WorkingDir) > 0 { - workDir = input.WorkingDir - } - - // Only use image's Cmd when the user does not set the entrypoint - if input.Entrypoint == nil && len(input.Cmd) == 0 { - cmdSlice, err := newImage.Cmd(ctx) - if err != nil { - return createconfig.CreateConfig{}, err - } - input.Cmd = cmdSlice - } - - if input.Entrypoint == nil { - entrypointSlice, err := newImage.Entrypoint(ctx) - if err != nil { - return createconfig.CreateConfig{}, err - } - input.Entrypoint = entrypointSlice - } - - stopTimeout := containerConfig.Engine.StopTimeout - if input.StopTimeout != nil { - stopTimeout = uint(*input.StopTimeout) - } - c := createconfig.CgroupConfig{ - Cgroups: "", // podman - Cgroupns: "", // podman - CgroupParent: "", // podman - CgroupMode: "", // podman - } - security := createconfig.SecurityConfig{ - CapAdd: input.HostConfig.CapAdd, - CapDrop: input.HostConfig.CapDrop, - LabelOpts: nil, // podman - NoNewPrivs: false, // podman - ApparmorProfile: "", // podman - SeccompProfilePath: "", - SecurityOpts: input.HostConfig.SecurityOpt, - Privileged: input.HostConfig.Privileged, - ReadOnlyRootfs: input.HostConfig.ReadonlyRootfs, - ReadOnlyTmpfs: false, // podman-only - Sysctl: input.HostConfig.Sysctls, - } - - var netmode namespaces.NetworkMode - if rootless.IsRootless() { - netmode = namespaces.NetworkMode(specgen.Slirp) - } - - network := createconfig.NetworkConfig{ - DNSOpt: input.HostConfig.DNSOptions, - DNSSearch: input.HostConfig.DNSSearch, - DNSServers: input.HostConfig.DNS, - ExposedPorts: input.ExposedPorts, - HTTPProxy: false, // podman - IP6Address: "", - IPAddress: "", - LinkLocalIP: nil, // docker-only - MacAddress: input.MacAddress, - NetMode: netmode, - Network: input.HostConfig.NetworkMode.NetworkName(), - NetworkAlias: nil, // docker-only now - PortBindings: input.HostConfig.PortBindings, - Publish: nil, // podmanseccompPath - PublishAll: input.HostConfig.PublishAllPorts, - } - - uts := createconfig.UtsConfig{ - UtsMode: namespaces.UTSMode(input.HostConfig.UTSMode), - NoHosts: false, //podman - HostAdd: input.HostConfig.ExtraHosts, - Hostname: input.Hostname, - } - - z := createconfig.UserConfig{ - GroupAdd: input.HostConfig.GroupAdd, - IDMappings: &storage.IDMappingOptions{}, // podman //TODO <--- fix this, - UsernsMode: namespaces.UsernsMode(input.HostConfig.UsernsMode), - User: input.User, - } - pidConfig := createconfig.PidConfig{PidMode: namespaces.PidMode(input.HostConfig.PidMode)} - // TODO: We should check that these binds are all listed in the `Volumes` - // key since it doesn't make sense to define a `Binds` element for a - // container path which isn't defined as a volume - volumes := input.HostConfig.Binds - - // Docker is more flexible about its input where podman throws - // away incorrectly formatted variables so we cannot reuse the - // parsing of the env input - // [Foo Other=one Blank=] - imgEnv, err := newImage.Env(ctx) - if err != nil { - return createconfig.CreateConfig{}, err - } - input.Env = append(imgEnv, input.Env...) - for _, e := range input.Env { - splitEnv := strings.Split(e, "=") - switch len(splitEnv) { - case 0: - continue - case 1: - env[splitEnv[0]] = "" - default: - env[splitEnv[0]] = strings.Join(splitEnv[1:], "=") - } - } - - // format the tmpfs mounts into a []string from map - tmpfs := make([]string, 0, len(input.HostConfig.Tmpfs)) - for k, v := range input.HostConfig.Tmpfs { - tmpfs = append(tmpfs, fmt.Sprintf("%s:%s", k, v)) - } - - if input.HostConfig.Init != nil && *input.HostConfig.Init { - init = true - } - - m := createconfig.CreateConfig{ - Annotations: nil, // podman - Args: nil, - Cgroup: c, - CidFile: "", - ConmonPidFile: "", // podman - Command: input.Cmd, - UserCommand: input.Cmd, // podman - Detach: false, // - // Devices: input.HostConfig.Devices, - Entrypoint: input.Entrypoint, - Env: env, - HealthCheck: nil, // - Init: init, - InitPath: "", // tbd - Image: input.Image, - ImageID: newImage.ID(), - BuiltinImgVolumes: nil, // podman - ImageVolumeType: "", // podman - Interactive: input.OpenStdin, - // IpcMode: input.HostConfig.IpcMode, - Labels: input.Labels, - LogDriver: input.HostConfig.LogConfig.Type, // is this correct - // LogDriverOpt: input.HostConfig.LogConfig.Config, - Name: input.Name, - Network: network, - Pod: "", // podman - PodmanPath: "", // podman - Quiet: false, // front-end only - Resources: createconfig.CreateResourceConfig{MemorySwappiness: -1}, - RestartPolicy: input.HostConfig.RestartPolicy.Name, - Rm: input.HostConfig.AutoRemove, - StopSignal: stopSignal, - StopTimeout: stopTimeout, - Systemd: false, // podman - Tmpfs: tmpfs, - User: z, - Uts: uts, - Tty: input.Tty, - Mounts: nil, // we populate - // MountsFlag: input.HostConfig.Mounts, - NamedVolumes: nil, // we populate - Volumes: volumes, - VolumesFrom: input.HostConfig.VolumesFrom, - WorkDir: workDir, - Rootfs: "", // podman - Security: security, - Syslog: false, // podman - - Pid: pidConfig, + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "container create")) + return } - - fullCmd := append(input.Entrypoint, input.Cmd...) - if len(fullCmd) > 0 { - m.PodmanPath = fullCmd[0] - if len(fullCmd) == 1 { - m.Args = fullCmd - } else { - m.Args = fullCmd[1:] - } + createResponse := entities.ContainerCreateResponse{ + ID: report.Id, + Warnings: []string{}, } - - return m, nil + utils.WriteResponse(w, http.StatusCreated, createResponse) } diff --git a/pkg/api/handlers/compat/images_search.go b/pkg/api/handlers/compat/images_search.go index 131fab69f..b3ceae3ee 100644 --- a/pkg/api/handlers/compat/images_search.go +++ b/pkg/api/handlers/compat/images_search.go @@ -7,6 +7,7 @@ import ( "github.com/containers/image/v5/types" "github.com/containers/podman/v2/libpod/image" "github.com/containers/podman/v2/pkg/api/handlers/utils" + "github.com/containers/podman/v2/pkg/auth" "github.com/gorilla/schema" "github.com/pkg/errors" ) @@ -14,9 +15,10 @@ import ( func SearchImages(w http.ResponseWriter, r *http.Request) { decoder := r.Context().Value("decoder").(*schema.Decoder) query := struct { - Term string `json:"term"` - Limit int `json:"limit"` - Filters map[string][]string `json:"filters"` + Term string `json:"term"` + Limit int `json:"limit"` + Filters map[string][]string `json:"filters"` + TLSVerify bool `json:"tlsVerify"` }{ // This is where you can override the golang default value for one of fields } @@ -58,6 +60,18 @@ func SearchImages(w http.ResponseWriter, r *http.Request) { Limit: query.Limit, } + if _, found := r.URL.Query()["tlsVerify"]; found { + options.InsecureSkipTLSVerify = types.NewOptionalBool(!query.TLSVerify) + } + + _, authfile, key, err := auth.GetCredentials(r) + if err != nil { + utils.Error(w, "failed to retrieve repository credentials", http.StatusBadRequest, errors.Wrapf(err, "failed to parse %q header for %s", key, r.URL.String())) + return + } + defer auth.RemoveAuthfile(authfile) + options.Authfile = authfile + results, err := image.SearchImages(query.Term, options) if err != nil { utils.BadRequest(w, "term", query.Term, err) diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go index 1292090fb..3fb5d23c8 100644 --- a/pkg/api/handlers/libpod/images.go +++ b/pkg/api/handlers/libpod/images.go @@ -636,6 +636,14 @@ func SearchImages(w http.ResponseWriter, r *http.Request) { options.Filter = *filter } + _, authfile, key, err := auth.GetCredentials(r) + if err != nil { + utils.Error(w, "failed to retrieve repository credentials", http.StatusBadRequest, errors.Wrapf(err, "failed to parse %q header for %s", key, r.URL.String())) + return + } + defer auth.RemoveAuthfile(authfile) + options.Authfile = authfile + searchResults, err := image.SearchImages(query.Term, options) if err != nil { utils.BadRequest(w, "term", query.Term, err) diff --git a/pkg/specgen/generate/namespaces.go b/pkg/specgen/generate/namespaces.go index 7adb8be6a..7e4f09dc4 100644 --- a/pkg/specgen/generate/namespaces.go +++ b/pkg/specgen/generate/namespaces.go @@ -342,7 +342,7 @@ func specConfigureNamespaces(s *specgen.SpecGenerator, g *generate.Generator, rt return errors.Wrapf(err, "error looking up container to share uts namespace with") } hostname = utsCtr.Hostname() - case s.NetNS.NSMode == specgen.Host || s.UtsNS.NSMode == specgen.Host: + case (s.NetNS.NSMode == specgen.Host && hostname == "") || s.UtsNS.NSMode == specgen.Host: tmpHostname, err := os.Hostname() if err != nil { return errors.Wrap(err, "unable to retrieve hostname of the host") diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go index f02432f5b..8454458a8 100644 --- a/pkg/specgen/generate/oci.go +++ b/pkg/specgen/generate/oci.go @@ -110,7 +110,7 @@ func makeCommand(ctx context.Context, s *specgen.SpecGenerator, img *image.Image // Only use image command if the user did not manually set an // entrypoint. command := s.Command - if command == nil && img != nil && s.Entrypoint == nil { + if (command == nil || len(command) == 0) && img != nil && (s.Entrypoint == nil || len(s.Entrypoint) == 0) { newCmd, err := img.Cmd(ctx) if err != nil { return nil, err diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at index 7fbcd2e9c..c7055dfc4 100644 --- a/test/apiv2/20-containers.at +++ b/test/apiv2/20-containers.at @@ -206,16 +206,6 @@ t POST containers/${cid_top}/stop "" 204 t DELETE containers/$cid 204 t DELETE containers/$cid_top 204 -# test the apiv2 create, shouldn't ignore the ENV and WORKDIR from the image -t POST containers/create '"Image":"'$ENV_WORKDIR_IMG'","Env":["testKey1"]' 201 \ - .Id~[0-9a-f]\\{64\\} -cid=$(jq -r '.Id' <<<"$output") -t GET containers/$cid/json 200 \ - .Config.Env~.*REDIS_VERSION= \ - .Config.Env~.*testKey1= \ - .Config.WorkingDir="/data" # default is /data -t DELETE containers/$cid 204 - # test the WORKDIR and StopSignal t POST containers/create '"Image":"'$ENV_WORKDIR_IMG'","WorkingDir":"/dataDir","StopSignal":"9"' 201 \ .Id~[0-9a-f]\\{64\\} diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go index 226b71627..206c66f9f 100644 --- a/test/e2e/common_test.go +++ b/test/e2e/common_test.go @@ -666,3 +666,9 @@ func (p *PodmanTestIntegration) PodmanAsUser(args []string, uid, gid uint32, cwd podmanSession := p.PodmanAsUserBase(args, uid, gid, cwd, env, false, false, nil) return &PodmanSessionIntegration{podmanSession} } + +// We don't support running Varlink when local +func (p *PodmanTestIntegration) RestartRemoteService() { + p.StopRemoteService() + p.StartRemoteService() +} diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go index f69b6ca7b..83a66d2b9 100644 --- a/test/e2e/pod_create_test.go +++ b/test/e2e/pod_create_test.go @@ -245,6 +245,24 @@ var _ = Describe("Podman pod create", func() { } }) + It("podman container in pod with IP address shares IP address", func() { + SkipIfRootless("Rootless does not support --ip") + podName := "test" + ctrName := "testCtr" + ip := GetRandomIPAddress() + podCreate := podmanTest.Podman([]string{"pod", "create", "--ip", ip, "--name", podName}) + podCreate.WaitWithDefaultTimeout() + Expect(podCreate.ExitCode()).To(Equal(0)) + podCtr := podmanTest.Podman([]string{"run", "--name", ctrName, "--pod", podName, "-d", "-t", ALPINE, "top"}) + podCtr.WaitWithDefaultTimeout() + Expect(podCtr.ExitCode()).To(Equal(0)) + ctrInspect := podmanTest.Podman([]string{"inspect", ctrName}) + ctrInspect.WaitWithDefaultTimeout() + Expect(ctrInspect.ExitCode()).To(Equal(0)) + ctrJSON := ctrInspect.InspectContainerToJSON() + Expect(ctrJSON[0].NetworkSettings.IPAddress).To(Equal(ip)) + }) + It("podman create pod with IP address and no infra should fail", func() { name := "test" ip := GetRandomIPAddress() diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go index e14482db7..540ac5409 100644 --- a/test/e2e/run_networking_test.go +++ b/test/e2e/run_networking_test.go @@ -571,4 +571,19 @@ var _ = Describe("Podman run networking", func() { podrm.WaitWithDefaultTimeout() Expect(podrm.ExitCode()).To(BeZero()) }) + + It("podman run net=host adds entry to /etc/hosts", func() { + run := podmanTest.Podman([]string{"run", "--net=host", ALPINE, "cat", "/etc/hosts"}) + run.WaitWithDefaultTimeout() + Expect(run.ExitCode()).To(BeZero()) + Expect(strings.Contains(run.OutputToString(), "127.0.1.1")).To(BeTrue()) + }) + + It("podman run with --net=host and --hostname sets correct hostname", func() { + hostname := "testctr" + run := podmanTest.Podman([]string{"run", "--net=host", "--hostname", hostname, ALPINE, "hostname"}) + run.WaitWithDefaultTimeout() + Expect(run.ExitCode()).To(BeZero()) + Expect(strings.Contains(run.OutputToString(), "testctr")).To(BeTrue()) + }) }) diff --git a/test/e2e/search_test.go b/test/e2e/search_test.go index 0cf005529..4f2751099 100644 --- a/test/e2e/search_test.go +++ b/test/e2e/search_test.go @@ -237,7 +237,6 @@ registries = ['{{.Host}}:{{.Port}}']` }) It("podman search attempts HTTP if registry is in registries.insecure and force secure is false", func() { - SkipIfRemote("--tls-verify is not supported on podman-remote search") if podmanTest.Host.Arch == "ppc64le" { Skip("No registry image for ppc64le") } @@ -264,6 +263,10 @@ registries = ['{{.Host}}:{{.Port}}']` registryFileTmpl.Execute(&buffer, registryEndpoints[4]) podmanTest.setRegistriesConfigEnv(buffer.Bytes()) ioutil.WriteFile(fmt.Sprintf("%s/registry4.conf", tempdir), buffer.Bytes(), 0644) + if IsRemote() { + podmanTest.RestartRemoteService() + defer podmanTest.RestartRemoteService() + } search := podmanTest.PodmanNoCache([]string{"search", image}) search.WaitWithDefaultTimeout() @@ -278,7 +281,7 @@ registries = ['{{.Host}}:{{.Port}}']` }) It("podman search doesn't attempt HTTP if force secure is true", func() { - SkipIfRemote("--tls-verify is not supported on podman-remote search") + SkipIfRemote("FIXME This should work on podman-remote") if podmanTest.Host.Arch == "ppc64le" { Skip("No registry image for ppc64le") } @@ -303,6 +306,10 @@ registries = ['{{.Host}}:{{.Port}}']` registryFileTmpl.Execute(&buffer, registryEndpoints[5]) podmanTest.setRegistriesConfigEnv(buffer.Bytes()) ioutil.WriteFile(fmt.Sprintf("%s/registry5.conf", tempdir), buffer.Bytes(), 0644) + if IsRemote() { + podmanTest.RestartRemoteService() + defer podmanTest.RestartRemoteService() + } search := podmanTest.PodmanNoCache([]string{"search", image, "--tls-verify=true"}) search.WaitWithDefaultTimeout() @@ -317,7 +324,7 @@ registries = ['{{.Host}}:{{.Port}}']` }) It("podman search doesn't attempt HTTP if registry is not listed as insecure", func() { - SkipIfRemote("--tls-verify is not supported on podman-remote search") + SkipIfRemote("FIXME This should work on podman-remote") if podmanTest.Host.Arch == "ppc64le" { Skip("No registry image for ppc64le") } @@ -343,6 +350,11 @@ registries = ['{{.Host}}:{{.Port}}']` podmanTest.setRegistriesConfigEnv(buffer.Bytes()) ioutil.WriteFile(fmt.Sprintf("%s/registry6.conf", tempdir), buffer.Bytes(), 0644) + if IsRemote() { + podmanTest.RestartRemoteService() + defer podmanTest.RestartRemoteService() + } + search := podmanTest.PodmanNoCache([]string{"search", image}) search.WaitWithDefaultTimeout() @@ -393,6 +405,11 @@ registries = ['{{.Host}}:{{.Port}}']` podmanTest.setRegistriesConfigEnv(buffer.Bytes()) ioutil.WriteFile(fmt.Sprintf("%s/registry8.conf", tempdir), buffer.Bytes(), 0644) + if IsRemote() { + podmanTest.RestartRemoteService() + defer podmanTest.RestartRemoteService() + } + search := podmanTest.PodmanNoCache([]string{"search", "my-alpine"}) search.WaitWithDefaultTimeout() |