diff options
38 files changed, 366 insertions, 83 deletions
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/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh index 1b992711f..3135a5e65 100755 --- a/contrib/cirrus/setup_environment.sh +++ b/contrib/cirrus/setup_environment.sh @@ -52,7 +52,7 @@ case "$CG_FS_TYPE" in if [[ "$OS_RELEASE_ID" == "ubuntu" ]]; then echo "export OCI_RUNTIME=/usr/lib/cri-o-runc/sbin/runc" >> /etc/environment else - echo "export OCI_RUNTIME=/usr/bin/runc" >> /etc/environment + echo "export OCI_RUNTIME=runc" >> /etc/environment fi fi ;; @@ -61,7 +61,7 @@ case "$CG_FS_TYPE" in # This is necessary since we've built/installed from source, # which uses runc as the default. warn "Forcing testing with crun instead of runc" - echo "export OCI_RUNTIME=/usr/bin/crun" >> /etc/environment + echo "export OCI_RUNTIME=crun" >> /etc/environment fi ;; *) die_unknown CG_FS_TYPE 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/boltdb_state_internal.go b/libpod/boltdb_state_internal.go index 9be753d26..e195ca314 100644 --- a/libpod/boltdb_state_internal.go +++ b/libpod/boltdb_state_internal.go @@ -2,7 +2,7 @@ package libpod import ( "bytes" - "path/filepath" + "os" "runtime" "strings" @@ -400,14 +400,30 @@ func (s *BoltState) getContainerFromDB(id []byte, ctr *Container, ctrsBkt *bolt. // Handle legacy containers which might use a literal path for // their OCI runtime name. runtimeName := ctr.config.OCIRuntime - if strings.HasPrefix(runtimeName, "/") { - runtimeName = filepath.Base(runtimeName) - } - ociRuntime, ok := s.runtime.ociRuntimes[runtimeName] if !ok { - // Use a MissingRuntime implementation - ociRuntime = getMissingRuntime(runtimeName, s.runtime) + runtimeSet := false + + // If the path starts with a / and exists, make a new + // OCI runtime for it using the full path. + if strings.HasPrefix(runtimeName, "/") { + if stat, err := os.Stat(runtimeName); err == nil && !stat.IsDir() { + newOCIRuntime, err := newConmonOCIRuntime(runtimeName, []string{runtimeName}, s.runtime.conmonPath, s.runtime.runtimeFlags, s.runtime.config) + if err == nil { + // The runtime lock should + // protect against concurrent + // modification of the map. + ociRuntime = newOCIRuntime + s.runtime.ociRuntimes[runtimeName] = ociRuntime + runtimeSet = true + } + } + } + + if !runtimeSet { + // Use a MissingRuntime implementation + ociRuntime = getMissingRuntime(runtimeName, s.runtime) + } } ctr.ociRuntime = ociRuntime } 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/libpod/runtime.go b/libpod/runtime.go index 7da8b181f..792492db6 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -17,6 +17,7 @@ import ( "github.com/containers/podman/v2/libpod/events" "github.com/containers/podman/v2/libpod/image" "github.com/containers/podman/v2/libpod/lock" + "github.com/containers/podman/v2/libpod/shutdown" "github.com/containers/podman/v2/pkg/cgroups" "github.com/containers/podman/v2/pkg/registries" "github.com/containers/podman/v2/pkg/rootless" @@ -174,9 +175,21 @@ func newRuntimeFromConfig(ctx context.Context, conf *config.Config, options ...R } } + if err := shutdown.Start(); err != nil { + return nil, errors.Wrapf(err, "error starting shutdown signal handler") + } + if err := makeRuntime(ctx, runtime); err != nil { return nil, err } + + if err := shutdown.Register("libpod", func(sig os.Signal) error { + os.Exit(1) + return nil + }); err != nil { + logrus.Errorf("Error registering shutdown handler for libpod: %v", err) + } + return runtime, nil } @@ -383,14 +396,12 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) { // If the string starts with / it's a path to a runtime // executable. if strings.HasPrefix(runtime.config.Engine.OCIRuntime, "/") { - name := filepath.Base(runtime.config.Engine.OCIRuntime) - - ociRuntime, err := newConmonOCIRuntime(name, []string{runtime.config.Engine.OCIRuntime}, runtime.conmonPath, runtime.runtimeFlags, runtime.config) + ociRuntime, err := newConmonOCIRuntime(runtime.config.Engine.OCIRuntime, []string{runtime.config.Engine.OCIRuntime}, runtime.conmonPath, runtime.runtimeFlags, runtime.config) if err != nil { return err } - runtime.ociRuntimes[name] = ociRuntime + runtime.ociRuntimes[runtime.config.Engine.OCIRuntime] = ociRuntime runtime.defaultOCIRuntime = ociRuntime } else { ociRuntime, ok := runtime.ociRuntimes[runtime.config.Engine.OCIRuntime] diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index 51b4c5f03..de73a9ff3 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -12,6 +12,7 @@ import ( "github.com/containers/common/pkg/config" "github.com/containers/podman/v2/libpod/define" "github.com/containers/podman/v2/libpod/events" + "github.com/containers/podman/v2/libpod/shutdown" "github.com/containers/podman/v2/pkg/cgroups" "github.com/containers/podman/v2/pkg/rootless" "github.com/containers/storage" @@ -149,6 +150,10 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai return nil, err } + // Inhibit shutdown until creation succeeds + shutdown.Inhibit() + defer shutdown.Uninhibit() + // Allocate a lock for the container lock, err := r.lockManager.AllocateLock() if err != nil { diff --git a/libpod/shutdown/handler.go b/libpod/shutdown/handler.go new file mode 100644 index 000000000..87538dec9 --- /dev/null +++ b/libpod/shutdown/handler.go @@ -0,0 +1,131 @@ +package shutdown + +import ( + "os" + "os/signal" + "sync" + "syscall" + + "github.com/pkg/errors" + "github.com/sirupsen/logrus" +) + +var ( + stopped bool + sigChan chan os.Signal + cancelChan chan bool + // Definitions of all on-shutdown handlers + handlers map[string]func(os.Signal) error + // Ordering that on-shutdown handlers will be invoked. + handlerOrder []string + shutdownInhibit sync.RWMutex +) + +// Start begins handling SIGTERM and SIGINT and will run the given on-signal +// handlers when one is called. This can be cancelled by calling Stop(). +func Start() error { + if sigChan != nil { + // Already running, do nothing. + return nil + } + + sigChan = make(chan os.Signal, 1) + cancelChan = make(chan bool, 1) + stopped = false + + signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) + + go func() { + select { + case <-cancelChan: + signal.Stop(sigChan) + close(sigChan) + close(cancelChan) + stopped = true + return + case sig := <-sigChan: + logrus.Infof("Received shutdown signal %v, terminating!", sig) + shutdownInhibit.Lock() + for _, name := range handlerOrder { + handler, ok := handlers[name] + if !ok { + logrus.Errorf("Shutdown handler %s definition not found!", name) + continue + } + logrus.Infof("Invoking shutdown handler %s", name) + if err := handler(sig); err != nil { + logrus.Errorf("Error running shutdown handler %s: %v", name, err) + } + } + shutdownInhibit.Unlock() + return + } + }() + + return nil +} + +// Stop the shutdown signal handler. +func Stop() error { + if cancelChan == nil { + return errors.New("shutdown signal handler has not yet been started") + } + if stopped { + return nil + } + + cancelChan <- true + + return nil +} + +// Temporarily inhibit signals from shutting down Libpod. +func Inhibit() { + shutdownInhibit.RLock() +} + +// Stop inhibiting signals from shutting down Libpod. +func Uninhibit() { + shutdownInhibit.RUnlock() +} + +// Register registers a function that will be executed when Podman is terminated +// by a signal. Handlers are invoked LIFO - the last handler registered is the +// first run. +func Register(name string, handler func(os.Signal) error) error { + if handlers == nil { + handlers = make(map[string]func(os.Signal) error) + } + + if _, ok := handlers[name]; ok { + return errors.Errorf("handler with name %s already exists", name) + } + + handlers[name] = handler + handlerOrder = append([]string{name}, handlerOrder...) + + return nil +} + +// Unregister un-registers a given shutdown handler. +func Unregister(name string) error { + if handlers == nil { + return nil + } + + if _, ok := handlers[name]; !ok { + return nil + } + + delete(handlers, name) + + newOrder := []string{} + for _, checkName := range handlerOrder { + if checkName != name { + newOrder = append(newOrder, checkName) + } + } + handlerOrder = newOrder + + return nil +} 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/api/server/server.go b/pkg/api/server/server.go index 355a46fb7..64008767b 100644 --- a/pkg/api/server/server.go +++ b/pkg/api/server/server.go @@ -7,7 +7,6 @@ import ( "net" "net/http" "os" - "os/signal" goRuntime "runtime" "strings" "sync" @@ -15,6 +14,7 @@ import ( "time" "github.com/containers/podman/v2/libpod" + "github.com/containers/podman/v2/libpod/shutdown" "github.com/containers/podman/v2/pkg/api/handlers" "github.com/containers/podman/v2/pkg/api/server/idle" "github.com/coreos/go-systemd/v22/activation" @@ -180,8 +180,17 @@ func setupSystemd() { // Serve starts responding to HTTP requests. func (s *APIServer) Serve() error { setupSystemd() - sigChan := make(chan os.Signal, 1) - signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) + + // Start the shutdown signal handler. + if err := shutdown.Start(); err != nil { + return err + } + if err := shutdown.Register("server", func(sig os.Signal) error { + return s.Shutdown() + }); err != nil { + return err + } + errChan := make(chan error, 1) go func() { @@ -217,14 +226,7 @@ func (s *APIServer) Serve() error { errChan <- nil }() - select { - case err := <-errChan: - return err - case sig := <-sigChan: - logrus.Infof("APIServer terminated by signal %v", sig) - } - - return nil + return <-errChan } // Shutdown is a clean shutdown waiting on existing clients diff --git a/pkg/domain/infra/abi/terminal/sigproxy_linux.go b/pkg/domain/infra/abi/terminal/sigproxy_linux.go index f484e926c..0c586cf5c 100644 --- a/pkg/domain/infra/abi/terminal/sigproxy_linux.go +++ b/pkg/domain/infra/abi/terminal/sigproxy_linux.go @@ -5,12 +5,17 @@ import ( "syscall" "github.com/containers/podman/v2/libpod" + "github.com/containers/podman/v2/libpod/shutdown" "github.com/containers/podman/v2/pkg/signal" "github.com/sirupsen/logrus" ) // ProxySignals ... func ProxySignals(ctr *libpod.Container) { + // Stop catching the shutdown signals (SIGINT, SIGTERM) - they're going + // to the container now. + shutdown.Stop() + sigBuffer := make(chan os.Signal, 128) signal.CatchAll(sigBuffer) 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/test/e2e/common_test.go b/test/e2e/common_test.go index e36c86690..206c66f9f 100644 --- a/test/e2e/common_test.go +++ b/test/e2e/common_test.go @@ -235,14 +235,7 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration { ociRuntime := os.Getenv("OCI_RUNTIME") if ociRuntime == "" { - var err error - ociRuntime, err = exec.LookPath("crun") - // If we cannot find the crun binary, setting to something static as we have no way - // to return an error. The tests will fail and point out that the runc binary could - // not be found nicely. - if err != nil { - ociRuntime = "/usr/bin/runc" - } + ociRuntime = "crun" } os.Setenv("DISABLE_HC_SYSTEMD", "true") CNIConfigDir := "/etc/cni/net.d" @@ -673,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() diff --git a/test/endpoint/setup.go b/test/endpoint/setup.go index 56cab06b0..6bbc8d2bc 100644 --- a/test/endpoint/setup.go +++ b/test/endpoint/setup.go @@ -51,14 +51,7 @@ func Setup(tempDir string) *EndpointTestIntegration { ociRuntime := os.Getenv("OCI_RUNTIME") if ociRuntime == "" { - var err error - ociRuntime, err = exec.LookPath("runc") - // If we cannot find the runc binary, setting to something static as we have no way - // to return an error. The tests will fail and point out that the runc binary could - // not be found nicely. - if err != nil { - ociRuntime = "/usr/bin/runc" - } + ociRuntime = "runc" } os.Setenv("DISABLE_HC_SYSTEMD", "true") CNIConfigDir := "/etc/cni/net.d" diff --git a/test/system/030-run.bats b/test/system/030-run.bats index 28dc7c7a7..9f4037730 100644 --- a/test/system/030-run.bats +++ b/test/system/030-run.bats @@ -460,4 +460,17 @@ json-file | f is "$output" "$expect" "podman run with --tz=local, matches host" } +# run with --runtime should preserve the named runtime +@test "podman run : full path to --runtime is preserved" { + skip_if_cgroupsv1 + skip_if_remote + run_podman run -d --runtime '/usr/bin/crun' $IMAGE sleep 60 + cid="$output" + + run_podman inspect --format '{{.OCIRuntime}}' $cid + is "$output" "/usr/bin/crun" + + run_podman kill $cid +} + # vim: filetype=sh diff --git a/test/system/helpers.bash b/test/system/helpers.bash index 73cf1e5b2..2cced10c2 100644 --- a/test/system/helpers.bash +++ b/test/system/helpers.bash @@ -253,6 +253,7 @@ function is_cgroupsv1() { ! is_cgroupsv2 } +# True if cgroups v2 are enabled function is_cgroupsv2() { cgroup_type=$(stat -f -c %T /sys/fs/cgroup) test "$cgroup_type" = "cgroup2fs" @@ -305,6 +306,15 @@ function skip_if_no_selinux() { fi } +####################### +# skip_if_cgroupsv1 # ...with an optional message +####################### +function skip_if_cgroupsv1() { + if ! is_cgroupsv2; then + skip "${1:-test requires cgroupsv2}" + fi +} + ######### # die # Abort with helpful message ######### |