diff options
-rw-r--r-- | docs/source/markdown/podman-image-sign.1.md | 10 | ||||
-rw-r--r-- | libpod/container.go | 25 | ||||
-rw-r--r-- | libpod/container_config.go | 8 | ||||
-rw-r--r-- | libpod/runtime.go | 2 | ||||
-rw-r--r-- | libpod/shutdown/handler.go | 6 | ||||
-rw-r--r-- | libpod/stats.go | 2 | ||||
-rw-r--r-- | pkg/domain/infra/abi/images.go | 61 | ||||
-rw-r--r-- | pkg/specgen/generate/oci.go | 2 | ||||
-rw-r--r-- | pkg/trust/trust.go | 25 | ||||
-rw-r--r-- | test/apiv2/25-containersMore.at | 9 | ||||
-rw-r--r-- | test/e2e/run_memory_test.go | 6 | ||||
-rw-r--r-- | test/e2e/run_test.go | 2 |
12 files changed, 92 insertions, 66 deletions
diff --git a/docs/source/markdown/podman-image-sign.1.md b/docs/source/markdown/podman-image-sign.1.md index 1bd6e5b9d..7a924b80b 100644 --- a/docs/source/markdown/podman-image-sign.1.md +++ b/docs/source/markdown/podman-image-sign.1.md @@ -9,7 +9,9 @@ podman-image-sign - Create a signature for an image ## DESCRIPTION **podman image sign** will create a local signature for one or more local images that have been pulled from a registry. The signature will be written to a directory -derived from the registry configuration files in /etc/containers/registries.d. By default, the signature will be written into /var/lib/containers/sigstore directory. +derived from the registry configuration files in `$HOME/.config/containers/registries.d` if it exists, +otherwise `/etc/containers/registries.d` (unless overridden at compile-time), see **containers-registries.d(5)** for more information. +By default, the signature will be written into `/var/lib/containers/sigstore` for root and `$HOME/.local/share/containers/sigstore` for non-root users ## OPTIONS @@ -38,7 +40,8 @@ Sign the busybox image with the identify of foo@bar.com with a user's keyring an ## RELATED CONFIGURATION The write (and read) location for signatures is defined in YAML-based -configuration files in /etc/containers/registries.d/. When you sign +configuration files in /etc/containers/registries.d/ for root, +or $HOME/.config/containers/registries.d for non-root users. When you sign an image, Podman will use those configuration files to determine where to write the signature based on the the name of the originating registry or a default storage value unless overridden with the --directory @@ -53,5 +56,8 @@ the signature will be written into sub-directories of /var/lib/containers/sigstore/privateregistry.example.com. The use of 'sigstore' also means the signature will be 'read' from that same location on a pull-related function. +## SEE ALSO +containers-registries.d(5) + ## HISTORY November 2018, Originally compiled by Qi Wang (qiwan at redhat dot com) diff --git a/libpod/container.go b/libpod/container.go index 4e0687318..96a21736c 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -921,13 +921,33 @@ func (c *Container) CgroupManager() string { return cgroupManager } -// CGroupPath returns a cgroups "path" for a given container. +// CGroupPath returns a cgroups "path" for the given container. +// Note that the container must be running. Otherwise, an error +// is returned. func (c *Container) CGroupPath() (string, error) { + if !c.batched { + c.lock.Lock() + defer c.lock.Unlock() + if err := c.syncContainer(); err != nil { + return "", errors.Wrapf(err, "error updating container %s state", c.ID()) + } + } + return c.cGroupPath() +} + +// cGroupPath returns a cgroups "path" for the given container. +// Note that the container must be running. Otherwise, an error +// is returned. +// NOTE: only call this when owning the container's lock. +func (c *Container) cGroupPath() (string, error) { if c.config.NoCgroups || c.config.CgroupsMode == "disabled" { return "", errors.Wrapf(define.ErrNoCgroups, "this container is not creating cgroups") } + if c.state.State != define.ContainerStateRunning && c.state.State != define.ContainerStatePaused { + return "", errors.Wrapf(define.ErrCtrStopped, "cannot get cgroup path unless container %s is running", c.ID()) + } - // Read /proc/[PID]/cgroup and find the *longest* cgroup entry. That's + // Read /proc/{PID}/cgroup and find the *longest* cgroup entry. That's // needed to account for hacks in cgroups v1, where each line in the // file could potentially point to a cgroup. The longest one, however, // is the libpod-specific one we're looking for. @@ -952,7 +972,6 @@ func (c *Container) CGroupPath() (string, error) { if len(path) > len(cgroupPath) { cgroupPath = path } - } if len(cgroupPath) == 0 { diff --git a/libpod/container_config.go b/libpod/container_config.go index cc3ad25ea..c95be9b55 100644 --- a/libpod/container_config.go +++ b/libpod/container_config.go @@ -135,7 +135,13 @@ type ContainerRootFSConfig struct { // OverlayVolumes lists the overlay volumes to mount into the container. OverlayVolumes []*ContainerOverlayVolume `json:"overlayVolumes,omitempty"` // ImageVolumes lists the image volumes to mount into the container. - ImageVolumes []*ContainerImageVolume `json:"imageVolumes,omitempty"` + // Please note that this is named ctrImageVolumes in JSON to + // distinguish between these and the old `imageVolumes` field in Podman + // pre-1.8, which was used in very old Podman versions to determine how + // image volumes were handled in Libpod (support for these eventually + // moved out of Libpod into pkg/specgen). + // Please DO NOT re-use the `imageVolumes` name in container JSON again. + ImageVolumes []*ContainerImageVolume `json:"ctrImageVolumes,omitempty"` // CreateWorkingDir indicates that Libpod should create the container's // working directory if it does not exist. Some OCI runtimes do this by // default, but others do not. diff --git a/libpod/runtime.go b/libpod/runtime.go index 72bd34a5e..1004e4fa7 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -190,7 +190,7 @@ func newRuntimeFromConfig(ctx context.Context, conf *config.Config, options ...R if err := shutdown.Register("libpod", func(sig os.Signal) error { os.Exit(1) return nil - }); err != nil { + }); err != nil && errors.Cause(err) != shutdown.ErrHandlerExists { logrus.Errorf("Error registering shutdown handler for libpod: %v", err) } diff --git a/libpod/shutdown/handler.go b/libpod/shutdown/handler.go index 87538dec9..f0f228b19 100644 --- a/libpod/shutdown/handler.go +++ b/libpod/shutdown/handler.go @@ -11,6 +11,10 @@ import ( ) var ( + ErrHandlerExists error = errors.New("handler with given name already exists") +) + +var ( stopped bool sigChan chan os.Signal cancelChan chan bool @@ -98,7 +102,7 @@ func Register(name string, handler func(os.Signal) error) error { } if _, ok := handlers[name]; ok { - return errors.Errorf("handler with name %s already exists", name) + return ErrHandlerExists } handlers[name] = handler diff --git a/libpod/stats.go b/libpod/stats.go index e34739626..09d990017 100644 --- a/libpod/stats.go +++ b/libpod/stats.go @@ -34,7 +34,7 @@ func (c *Container) GetContainerStats(previousStats *define.ContainerStats) (*de return stats, define.ErrCtrStateInvalid } - cgroupPath, err := c.CGroupPath() + cgroupPath, err := c.cGroupPath() if err != nil { return nil, err } diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go index ff2f2e7ae..57a2bc4cf 100644 --- a/pkg/domain/infra/abi/images.go +++ b/pkg/domain/infra/abi/images.go @@ -26,7 +26,6 @@ import ( "github.com/containers/podman/v2/pkg/domain/entities" domainUtils "github.com/containers/podman/v2/pkg/domain/utils" "github.com/containers/podman/v2/pkg/rootless" - "github.com/containers/podman/v2/pkg/trust" "github.com/containers/podman/v2/pkg/util" "github.com/containers/storage" imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" @@ -34,9 +33,6 @@ import ( "github.com/sirupsen/logrus" ) -// SignatureStoreDir defines default directory to store signatures -const SignatureStoreDir = "/var/lib/containers/sigstore" - func (ir *ImageEngine) Exists(_ context.Context, nameOrID string) (*entities.BoolReport, error) { _, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrID) if err != nil { @@ -707,12 +703,6 @@ func (ir *ImageEngine) Sign(ctx context.Context, names []string, options entitie sc := ir.Libpod.SystemContext() sc.DockerCertPath = options.CertDir - systemRegistriesDirPath := trust.RegistriesDirPath(sc) - registryConfigs, err := trust.LoadAndMergeConfig(systemRegistriesDirPath) - if err != nil { - return nil, errors.Wrapf(err, "error reading registry configuration") - } - for _, signimage := range names { err = func() error { srcRef, err := alltransports.ParseImageName(signimage) @@ -738,37 +728,25 @@ func (ir *ImageEngine) Sign(ctx context.Context, names []string, options entitie } var sigStoreDir string if options.Directory != "" { - sigStoreDir = options.Directory - } - if sigStoreDir == "" { - if rootless.IsRootless() { - sigStoreDir = filepath.Join(filepath.Dir(ir.Libpod.StorageConfig().GraphRoot), "sigstore") - } else { - var sigStoreURI string - registryInfo := trust.HaveMatchRegistry(rawSource.Reference().DockerReference().String(), registryConfigs) - if registryInfo != nil { - if sigStoreURI = registryInfo.SigStoreStaging; sigStoreURI == "" { - sigStoreURI = registryInfo.SigStore - } - } - if sigStoreURI == "" { - return errors.Errorf("no signature storage configuration found for %s", rawSource.Reference().DockerReference().String()) - - } - sigStoreDir, err = localPathFromURI(sigStoreURI) - if err != nil { - return errors.Wrapf(err, "invalid signature storage %s", sigStoreURI) - } + repo := reference.Path(dockerReference) + if path.Clean(repo) != repo { // Coverage: This should not be reachable because /./ and /../ components are not valid in docker references + return errors.Errorf("Unexpected path elements in Docker reference %s for signature storage", dockerReference.String()) + } + sigStoreDir = filepath.Join(options.Directory, repo) + } else { + signatureURL, err := docker.SignatureStorageBaseURL(sc, rawSource.Reference(), true) + if err != nil { + return err + } + sigStoreDir, err = localPathFromURI(signatureURL) + if err != nil { + return err } } manifestDigest, err := manifest.Digest(getManifest) if err != nil { return err } - repo := reference.Path(dockerReference) - if path.Clean(repo) != repo { // Coverage: This should not be reachable because /./ and /../ components are not valid in docker references - return errors.Errorf("Unexpected path elements in Docker reference %s for signature storage", dockerReference.String()) - } // create signature newSig, err := signature.SignDockerManifest(getManifest, dockerReference.String(), mech, options.SignBy) @@ -776,7 +754,7 @@ func (ir *ImageEngine) Sign(ctx context.Context, names []string, options entitie return errors.Wrapf(err, "error creating new signature") } // create the signstore file - signatureDir := fmt.Sprintf("%s@%s=%s", filepath.Join(sigStoreDir, repo), manifestDigest.Algorithm(), manifestDigest.Hex()) + signatureDir := fmt.Sprintf("%s@%s=%s", sigStoreDir, manifestDigest.Algorithm(), manifestDigest.Hex()) if err := os.MkdirAll(signatureDir, 0751); err != nil { // The directory is allowed to exist if !os.IsExist(err) { @@ -822,14 +800,9 @@ func getSigFilename(sigStoreDirPath string) (string, error) { } } -func localPathFromURI(sigStoreDir string) (string, error) { - url, err := url.Parse(sigStoreDir) - if err != nil { - return sigStoreDir, errors.Wrapf(err, "invalid directory %s", sigStoreDir) - } +func localPathFromURI(url *url.URL) (string, error) { if url.Scheme != "file" { - return sigStoreDir, errors.Errorf("writing to %s is not supported. Use a supported scheme", sigStoreDir) + return "", errors.Errorf("writing to %s is not supported. Use a supported scheme", url.String()) } - sigStoreDir = url.Path - return sigStoreDir, nil + return url.Path, nil } diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go index 0368ab205..c24dcf4c0 100644 --- a/pkg/specgen/generate/oci.go +++ b/pkg/specgen/generate/oci.go @@ -165,7 +165,7 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt inUserNS = true } } - if inUserNS && s.NetNS.IsHost() { + if inUserNS && s.NetNS.NSMode != specgen.NoNetwork { canMountSys = false } diff --git a/pkg/trust/trust.go b/pkg/trust/trust.go index a61e0ef10..a30611b74 100644 --- a/pkg/trust/trust.go +++ b/pkg/trust/trust.go @@ -12,6 +12,7 @@ import ( "strings" "github.com/containers/image/v5/types" + "github.com/docker/docker/pkg/homedir" "github.com/ghodss/yaml" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -60,6 +61,12 @@ type ShowOutput struct { Sigstore string } +// systemRegistriesDirPath is the path to registries.d. +const systemRegistriesDirPath = "/etc/containers/registries.d" + +// userRegistriesDir is the path to the per user registries.d. +var userRegistriesDir = filepath.FromSlash(".config/containers/registries.d") + // DefaultPolicyPath returns a path to the default policy of the system. func DefaultPolicyPath(sys *types.SystemContext) string { systemDefaultPolicyPath := "/etc/containers/policy.json" @@ -76,15 +83,17 @@ func DefaultPolicyPath(sys *types.SystemContext) string { // RegistriesDirPath returns a path to registries.d func RegistriesDirPath(sys *types.SystemContext) string { - systemRegistriesDirPath := "/etc/containers/registries.d" - if sys != nil { - if sys.RegistriesDirPath != "" { - return sys.RegistriesDirPath - } - if sys.RootForImplicitAbsolutePaths != "" { - return filepath.Join(sys.RootForImplicitAbsolutePaths, systemRegistriesDirPath) - } + if sys != nil && sys.RegistriesDirPath != "" { + return sys.RegistriesDirPath + } + userRegistriesDirPath := filepath.Join(homedir.Get(), userRegistriesDir) + if _, err := os.Stat(userRegistriesDirPath); err == nil { + return userRegistriesDirPath } + if sys != nil && sys.RootForImplicitAbsolutePaths != "" { + return filepath.Join(sys.RootForImplicitAbsolutePaths, systemRegistriesDirPath) + } + return systemRegistriesDirPath } diff --git a/test/apiv2/25-containersMore.at b/test/apiv2/25-containersMore.at index 62b817eb4..b88c798eb 100644 --- a/test/apiv2/25-containersMore.at +++ b/test/apiv2/25-containersMore.at @@ -79,4 +79,13 @@ like "$output" ".*spec:.*" "Check generated kube yaml(service=true) - spec" like "$output" ".*kind:\\sService.*" "Check generated kube yaml(service=true) - kind: Service" t DELETE libpod/containers/$cid 204 + +# Create 3 stopped containers to test containers prune +podman run $IMAGE true +podman run $IMAGE true +podman run $IMAGE true + +t POST libpod/containers/prune '' 200 +t GET libpod/containers/json 200 \ + length=0 # vim: filetype=sh diff --git a/test/e2e/run_memory_test.go b/test/e2e/run_memory_test.go index b3913c1e6..ad3a2b54f 100644 --- a/test/e2e/run_memory_test.go +++ b/test/e2e/run_memory_test.go @@ -38,7 +38,7 @@ var _ = Describe("Podman run memory", func() { var session *PodmanSessionIntegration if CGROUPSV2 { - session = podmanTest.Podman([]string{"run", "--memory=40m", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/memory.max"}) + session = podmanTest.Podman([]string{"run", "--memory=40m", "--net=none", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/memory.max"}) } else { session = podmanTest.Podman([]string{"run", "--memory=40m", ALPINE, "cat", "/sys/fs/cgroup/memory/memory.limit_in_bytes"}) } @@ -55,7 +55,7 @@ var _ = Describe("Podman run memory", func() { var session *PodmanSessionIntegration if CGROUPSV2 { - session = podmanTest.Podman([]string{"run", "--memory-reservation=40m", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/memory.low"}) + session = podmanTest.Podman([]string{"run", "--memory-reservation=40m", "--net=none", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/memory.low"}) } else { session = podmanTest.Podman([]string{"run", "--memory-reservation=40m", ALPINE, "cat", "/sys/fs/cgroup/memory/memory.soft_limit_in_bytes"}) } @@ -81,7 +81,7 @@ var _ = Describe("Podman run memory", func() { var session *PodmanSessionIntegration if CGROUPSV2 { - session = podmanTest.Podman([]string{"run", "--memory-reservation=40m", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/memory.low"}) + session = podmanTest.Podman([]string{"run", "--net=none", "--memory-reservation=40m", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/memory.low"}) } else { session = podmanTest.Podman([]string{"run", "--memory-reservation=40m", ALPINE, "cat", "/sys/fs/cgroup/memory/memory.soft_limit_in_bytes"}) } diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index efc125d2b..58ef9a647 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -1300,7 +1300,7 @@ USER mail` It("podman run verify pids-limit", func() { SkipIfCgroupV1("pids-limit not supported on cgroup V1") limit := "4321" - session := podmanTest.Podman([]string{"run", "--pids-limit", limit, "--rm", ALPINE, "cat", "/sys/fs/cgroup/pids.max"}) + session := podmanTest.Podman([]string{"run", "--pids-limit", limit, "--net=none", "--rm", ALPINE, "cat", "/sys/fs/cgroup/pids.max"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) Expect(session.OutputToString()).To(ContainSubstring(limit)) |