diff options
Diffstat (limited to 'pkg/domain')
-rw-r--r-- | pkg/domain/entities/containers.go | 10 | ||||
-rw-r--r-- | pkg/domain/entities/engine_container.go | 4 | ||||
-rw-r--r-- | pkg/domain/entities/images.go | 22 | ||||
-rw-r--r-- | pkg/domain/infra/abi/cp.go | 439 | ||||
-rw-r--r-- | pkg/domain/infra/abi/generate.go | 54 | ||||
-rw-r--r-- | pkg/domain/infra/abi/images.go | 154 | ||||
-rw-r--r-- | pkg/domain/infra/abi/images_list.go | 13 | ||||
-rw-r--r-- | pkg/domain/infra/abi/system.go | 17 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/containers.go | 4 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/generate.go | 4 |
10 files changed, 183 insertions, 538 deletions
diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go index 3fd7c79f4..39d679eaf 100644 --- a/pkg/domain/entities/containers.go +++ b/pkg/domain/entities/containers.go @@ -403,16 +403,14 @@ type ContainerPortReport struct { Ports []ocicni.PortMapping } -// ContainerCpOptions describes input options for cp +// ContainerCpOptions describes input options for cp. type ContainerCpOptions struct { - Pause bool + // Pause the container while copying. + Pause bool + // Extract the tarfile into the destination directory. Extract bool } -// ContainerCpReport describes the output from a cp operation -type ContainerCpReport struct { -} - // ContainerStatsOptions describes input options for getting // stats on containers type ContainerStatsOptions struct { diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go index a4f6c08e9..5ad475133 100644 --- a/pkg/domain/entities/engine_container.go +++ b/pkg/domain/entities/engine_container.go @@ -16,7 +16,7 @@ type ContainerEngine interface { ContainerCheckpoint(ctx context.Context, namesOrIds []string, options CheckpointOptions) ([]*CheckpointReport, error) ContainerCleanup(ctx context.Context, namesOrIds []string, options ContainerCleanupOptions) ([]*ContainerCleanupReport, error) ContainerCommit(ctx context.Context, nameOrID string, options CommitOptions) (*CommitReport, error) - ContainerCp(ctx context.Context, source, dest string, options ContainerCpOptions) (*ContainerCpReport, error) + ContainerCp(ctx context.Context, source, dest string, options ContainerCpOptions) error ContainerCreate(ctx context.Context, s *specgen.SpecGenerator) (*ContainerCreateReport, error) ContainerDiff(ctx context.Context, nameOrID string, options DiffOptions) (*DiffReport, error) ContainerExec(ctx context.Context, nameOrID string, options ExecOptions, streams define.AttachStreams) (int, error) @@ -46,7 +46,7 @@ type ContainerEngine interface { ContainerWait(ctx context.Context, namesOrIds []string, options WaitOptions) ([]WaitReport, error) Events(ctx context.Context, opts EventsOptions) error GenerateSystemd(ctx context.Context, nameOrID string, opts GenerateSystemdOptions) (*GenerateSystemdReport, error) - GenerateKube(ctx context.Context, nameOrID string, opts GenerateKubeOptions) (*GenerateKubeReport, error) + GenerateKube(ctx context.Context, nameOrIDs []string, opts GenerateKubeOptions) (*GenerateKubeReport, error) SystemPrune(ctx context.Context, options SystemPruneOptions) (*SystemPruneReport, error) HealthCheckRun(ctx context.Context, nameOrID string, options HealthCheckOptions) (*define.HealthCheckResults, error) Info(ctx context.Context) (*define.Info, error) diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go index ab545d882..81f12bff7 100644 --- a/pkg/domain/entities/images.go +++ b/pkg/domain/entities/images.go @@ -51,22 +51,22 @@ func (i *Image) Id() string { // nolint } type ImageSummary struct { - ID string `json:"Id"` - ParentId string // nolint - RepoTags []string `json:",omitempty"` + ID string `json:"Id"` + ParentId string // nolint + RepoTags []string + RepoDigests []string Created int64 - Size int64 `json:",omitempty"` - SharedSize int `json:",omitempty"` - VirtualSize int64 `json:",omitempty"` - Labels map[string]string `json:",omitempty"` - Containers int `json:",omitempty"` - ReadOnly bool `json:",omitempty"` - Dangling bool `json:",omitempty"` + Size int64 + SharedSize int + VirtualSize int64 + Labels map[string]string + Containers int + ReadOnly bool `json:",omitempty"` + Dangling bool `json:",omitempty"` // Podman extensions Names []string `json:",omitempty"` Digest string `json:",omitempty"` - Digests []string `json:",omitempty"` ConfigDigest string `json:",omitempty"` History []string `json:",omitempty"` } diff --git a/pkg/domain/infra/abi/cp.go b/pkg/domain/infra/abi/cp.go index 8f4f5d3d7..9409df743 100644 --- a/pkg/domain/infra/abi/cp.go +++ b/pkg/domain/infra/abi/cp.go @@ -1,195 +1,70 @@ package abi import ( - "archive/tar" "context" - "fmt" - "io" - "os" - "path/filepath" "strings" - "github.com/containers/buildah/pkg/chrootuser" - "github.com/containers/buildah/util" "github.com/containers/podman/v2/libpod" - "github.com/containers/podman/v2/libpod/define" + "github.com/containers/podman/v2/pkg/copy" "github.com/containers/podman/v2/pkg/domain/entities" - "github.com/containers/storage" - "github.com/containers/storage/pkg/chrootarchive" - "github.com/containers/storage/pkg/idtools" - securejoin "github.com/cyphar/filepath-securejoin" - "github.com/docker/docker/pkg/archive" - "github.com/opencontainers/go-digest" - "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" - "github.com/sirupsen/logrus" ) -func (ic *ContainerEngine) ContainerCp(ctx context.Context, source, dest string, options entities.ContainerCpOptions) (*entities.ContainerCpReport, error) { - extract := options.Extract - +func (ic *ContainerEngine) ContainerCp(ctx context.Context, source, dest string, options entities.ContainerCpOptions) error { srcCtr, srcPath := parsePath(ic.Libpod, source) destCtr, destPath := parsePath(ic.Libpod, dest) - if (srcCtr == nil && destCtr == nil) || (srcCtr != nil && destCtr != nil) { - return nil, errors.Errorf("invalid arguments %s, %s you must use just one container", source, dest) + if srcCtr != nil && destCtr != nil { + return errors.Errorf("invalid arguments %q, %q: you must use just one container", source, dest) } - - if len(srcPath) == 0 || len(destPath) == 0 { - return nil, errors.Errorf("invalid arguments %s, %s you must specify paths", source, dest) + if srcCtr == nil && destCtr == nil { + return errors.Errorf("invalid arguments %q, %q: you must specify one container", source, dest) } - ctr := srcCtr - isFromHostToCtr := ctr == nil - if isFromHostToCtr { - ctr = destCtr + if len(srcPath) == 0 || len(destPath) == 0 { + return errors.Errorf("invalid arguments %q, %q: you must specify paths", source, dest) } - mountPoint, err := ctr.Mount() - if err != nil { - return nil, err - } - defer func() { - if err := ctr.Unmount(false); err != nil { - logrus.Errorf("unable to umount container '%s': %q", ctr.ID(), err) + var sourceItem, destinationItem copy.CopyItem + var err error + // Copy from the container to the host. + if srcCtr != nil { + sourceItem, err = copy.CopyItemForContainer(srcCtr, srcPath, options.Pause, true) + defer sourceItem.CleanUp() + if err != nil { + return err } - }() - - if options.Pause { - if err := ctr.Pause(); err != nil { - // An invalid state error is fine. - // The container isn't running or is already paused. - // TODO: We can potentially start the container while - // the copy is running, which still allows a race where - // malicious code could mess with the symlink. - if errors.Cause(err) != define.ErrCtrStateInvalid { - return nil, err - } - } else { - // Only add the defer if we actually paused - defer func() { - if err := ctr.Unpause(); err != nil { - logrus.Errorf("Error unpausing container after copying: %v", err) - } - }() + } else { + sourceItem, err = copy.CopyItemForHost(srcPath, true) + if err != nil { + return err } } - user, err := getUser(mountPoint, ctr.User()) - if err != nil { - return nil, err - } - idMappingOpts, err := ctr.IDMappings() - if err != nil { - return nil, errors.Wrapf(err, "error getting IDMappingOptions") - } - destOwner := idtools.IDPair{UID: int(user.UID), GID: int(user.GID)} - hostUID, hostGID, err := util.GetHostIDs(convertIDMap(idMappingOpts.UIDMap), convertIDMap(idMappingOpts.GIDMap), user.UID, user.GID) - if err != nil { - return nil, err - } - - hostOwner := idtools.IDPair{UID: int(hostUID), GID: int(hostGID)} - - if isFromHostToCtr { - if isVol, volDestName, volName := isVolumeDestName(destPath, ctr); isVol { //nolint(gocritic) - path, err := pathWithVolumeMount(ic.Libpod, volDestName, volName, destPath) - if err != nil { - return nil, errors.Wrapf(err, "error getting destination path from volume %s", volDestName) - } - destPath = path - } else if isBindMount, mount := isBindMountDestName(destPath, ctr); isBindMount { //nolint(gocritic) - path, err := pathWithBindMountSource(mount, destPath) - if err != nil { - return nil, errors.Wrapf(err, "error getting destination path from bind mount %s", mount.Destination) - } - destPath = path - } else if filepath.IsAbs(destPath) { //nolint(gocritic) - cleanedPath, err := securejoin.SecureJoin(mountPoint, destPath) - if err != nil { - return nil, err - } - destPath = cleanedPath - } else { //nolint(gocritic) - ctrWorkDir, err := securejoin.SecureJoin(mountPoint, ctr.WorkingDir()) - if err != nil { - return nil, err - } - if err = idtools.MkdirAllAndChownNew(ctrWorkDir, 0755, hostOwner); err != nil { - return nil, err - } - cleanedPath, err := securejoin.SecureJoin(mountPoint, filepath.Join(ctr.WorkingDir(), destPath)) - if err != nil { - return nil, err - } - destPath = cleanedPath + if destCtr != nil { + destinationItem, err = copy.CopyItemForContainer(destCtr, destPath, options.Pause, false) + defer destinationItem.CleanUp() + if err != nil { + return err } } else { - destOwner = idtools.IDPair{UID: os.Getuid(), GID: os.Getgid()} - if isVol, volDestName, volName := isVolumeDestName(srcPath, ctr); isVol { //nolint(gocritic) - path, err := pathWithVolumeMount(ic.Libpod, volDestName, volName, srcPath) - if err != nil { - return nil, errors.Wrapf(err, "error getting source path from volume %s", volDestName) - } - srcPath = path - } else if isBindMount, mount := isBindMountDestName(srcPath, ctr); isBindMount { //nolint(gocritic) - path, err := pathWithBindMountSource(mount, srcPath) - if err != nil { - return nil, errors.Wrapf(err, "error getting source path from bind mount %s", mount.Destination) - } - srcPath = path - } else if filepath.IsAbs(srcPath) { //nolint(gocritic) - cleanedPath, err := securejoin.SecureJoin(mountPoint, srcPath) - if err != nil { - return nil, err - } - srcPath = cleanedPath - } else { //nolint(gocritic) - cleanedPath, err := securejoin.SecureJoin(mountPoint, filepath.Join(ctr.WorkingDir(), srcPath)) - if err != nil { - return nil, err - } - srcPath = cleanedPath - } - } - - if !filepath.IsAbs(destPath) { - dir, err := os.Getwd() + destinationItem, err = copy.CopyItemForHost(destPath, false) + defer destinationItem.CleanUp() if err != nil { - return nil, errors.Wrapf(err, "err getting current working directory") + return err } - destPath = filepath.Join(dir, destPath) } - if source == "-" { - srcPath = os.Stdin.Name() - extract = true - } - err = containerCopy(srcPath, destPath, source, dest, idMappingOpts, &destOwner, extract, isFromHostToCtr) - return &entities.ContainerCpReport{}, err + // Copy from the host to the container. + return copy.Copy(&sourceItem, &destinationItem, options.Extract) } -func getUser(mountPoint string, userspec string) (specs.User, error) { - uid, gid, _, err := chrootuser.GetUser(mountPoint, userspec) - u := specs.User{ - UID: uid, - GID: gid, - Username: userspec, +func parsePath(runtime *libpod.Runtime, path string) (*libpod.Container, string) { + if len(path) == 0 { + return nil, "" } - if !strings.Contains(userspec, ":") { - groups, err2 := chrootuser.GetAdditionalGroupsForUser(mountPoint, uint64(u.UID)) - if err2 != nil { - if errors.Cause(err2) != chrootuser.ErrNoSuchUser && err == nil { - err = err2 - } - } else { - u.AdditionalGids = groups - } - + if path[0] == '.' || path[0] == '/' { // A path cannot point to a container. + return nil, path } - return u, err -} - -func parsePath(runtime *libpod.Runtime, path string) (*libpod.Container, string) { pathArr := strings.SplitN(path, ":", 2) if len(pathArr) == 2 { ctr, err := runtime.LookupContainer(pathArr[0]) @@ -199,247 +74,3 @@ func parsePath(runtime *libpod.Runtime, path string) (*libpod.Container, string) } return nil, path } - -func evalSymlinks(path string) (string, error) { - if path == os.Stdin.Name() { - return path, nil - } - return filepath.EvalSymlinks(path) -} - -func getPathInfo(path string) (string, os.FileInfo, error) { - path, err := evalSymlinks(path) - if err != nil { - return "", nil, errors.Wrapf(err, "error evaluating symlinks %q", path) - } - srcfi, err := os.Stat(path) - if err != nil { - return "", nil, err - } - return path, srcfi, nil -} - -func containerCopy(srcPath, destPath, src, dest string, idMappingOpts storage.IDMappingOptions, chownOpts *idtools.IDPair, extract, isFromHostToCtr bool) error { - srcPath, err := evalSymlinks(srcPath) - if err != nil { - return errors.Wrapf(err, "error evaluating symlinks %q", srcPath) - } - - srcPath, srcfi, err := getPathInfo(srcPath) - if err != nil { - return err - } - - filename := filepath.Base(destPath) - if filename == "-" && !isFromHostToCtr { - err := streamFileToStdout(srcPath, srcfi) - if err != nil { - return errors.Wrapf(err, "error streaming source file %s to Stdout", srcPath) - } - return nil - } - - destdir := destPath - if !srcfi.IsDir() { - destdir = filepath.Dir(destPath) - } - _, err = os.Stat(destdir) - if err != nil && !os.IsNotExist(err) { - return err - } - destDirIsExist := err == nil - if err = os.MkdirAll(destdir, 0755); err != nil { - return err - } - - // return functions for copying items - copyFileWithTar := chrootarchive.CopyFileWithTarAndChown(chownOpts, digest.Canonical.Digester().Hash(), idMappingOpts.UIDMap, idMappingOpts.GIDMap) - copyWithTar := chrootarchive.CopyWithTarAndChown(chownOpts, digest.Canonical.Digester().Hash(), idMappingOpts.UIDMap, idMappingOpts.GIDMap) - untarPath := chrootarchive.UntarPathAndChown(chownOpts, digest.Canonical.Digester().Hash(), idMappingOpts.UIDMap, idMappingOpts.GIDMap) - - if srcfi.IsDir() { - logrus.Debugf("copying %q to %q", srcPath+string(os.PathSeparator)+"*", dest+string(os.PathSeparator)+"*") - if destDirIsExist && !strings.HasSuffix(src, fmt.Sprintf("%s.", string(os.PathSeparator))) { - srcPathBase := filepath.Base(srcPath) - if !isFromHostToCtr { - pathArr := strings.SplitN(src, ":", 2) - if len(pathArr) != 2 { - return errors.Errorf("invalid arguments %s, you must specify source path", src) - } - if pathArr[1] == "/" { - // If `srcPath` is the root directory of the container, - // `srcPath` will be `.../${sha256_ID}/merged/`, so do not join it - srcPathBase = "" - } - } - destPath = filepath.Join(destPath, srcPathBase) - } - if err = copyWithTar(srcPath, destPath); err != nil { - return errors.Wrapf(err, "error copying %q to %q", srcPath, dest) - } - return nil - } - - if extract { - // We're extracting an archive into the destination directory. - logrus.Debugf("extracting contents of %q into %q", srcPath, destPath) - if err = untarPath(srcPath, destPath); err != nil { - return errors.Wrapf(err, "error extracting %q into %q", srcPath, destPath) - } - return nil - } - - destfi, err := os.Stat(destPath) - if err != nil { - if !os.IsNotExist(err) || strings.HasSuffix(dest, string(os.PathSeparator)) { - return err - } - } - if destfi != nil && destfi.IsDir() { - destPath = filepath.Join(destPath, filepath.Base(srcPath)) - } - - // Copy the file, preserving attributes. - logrus.Debugf("copying %q to %q", srcPath, destPath) - if err = copyFileWithTar(srcPath, destPath); err != nil { - return errors.Wrapf(err, "error copying %q to %q", srcPath, destPath) - } - return nil -} - -func convertIDMap(idMaps []idtools.IDMap) (convertedIDMap []specs.LinuxIDMapping) { - for _, idmap := range idMaps { - tempIDMap := specs.LinuxIDMapping{ - ContainerID: uint32(idmap.ContainerID), - HostID: uint32(idmap.HostID), - Size: uint32(idmap.Size), - } - convertedIDMap = append(convertedIDMap, tempIDMap) - } - return convertedIDMap -} - -func streamFileToStdout(srcPath string, srcfi os.FileInfo) error { - if srcfi.IsDir() { - tw := tar.NewWriter(os.Stdout) - err := filepath.Walk(srcPath, func(path string, info os.FileInfo, err error) error { - if err != nil || !info.Mode().IsRegular() || path == srcPath { - return err - } - hdr, err := tar.FileInfoHeader(info, "") - if err != nil { - return err - } - - if err = tw.WriteHeader(hdr); err != nil { - return err - } - fh, err := os.Open(path) - if err != nil { - return err - } - defer fh.Close() - - _, err = io.Copy(tw, fh) - return err - }) - if err != nil { - return errors.Wrapf(err, "error streaming directory %s to Stdout", srcPath) - } - return nil - } - - file, err := os.Open(srcPath) - if err != nil { - return err - } - defer file.Close() - if !archive.IsArchivePath(srcPath) { - tw := tar.NewWriter(os.Stdout) - hdr, err := tar.FileInfoHeader(srcfi, "") - if err != nil { - return err - } - err = tw.WriteHeader(hdr) - if err != nil { - return err - } - _, err = io.Copy(tw, file) - if err != nil { - return errors.Wrapf(err, "error streaming archive %s to Stdout", srcPath) - } - return nil - } - - _, err = io.Copy(os.Stdout, file) - if err != nil { - return errors.Wrapf(err, "error streaming file to Stdout") - } - return nil -} - -func isVolumeDestName(path string, ctr *libpod.Container) (bool, string, string) { - separator := string(os.PathSeparator) - if filepath.IsAbs(path) { - path = strings.TrimPrefix(path, separator) - } - if path == "" { - return false, "", "" - } - for _, vol := range ctr.Config().NamedVolumes { - volNamePath := strings.TrimPrefix(vol.Dest, separator) - if matchVolumePath(path, volNamePath) { - return true, vol.Dest, vol.Name - } - } - return false, "", "" -} - -// if SRCPATH or DESTPATH is from volume mount's destination -v or --mount type=volume, generates the path with volume mount point -func pathWithVolumeMount(runtime *libpod.Runtime, volDestName, volName, path string) (string, error) { - destVolume, err := runtime.GetVolume(volName) - if err != nil { - return "", errors.Wrapf(err, "error getting volume destination %s", volName) - } - if !filepath.IsAbs(path) { - path = filepath.Join(string(os.PathSeparator), path) - } - path, err = securejoin.SecureJoin(destVolume.MountPoint(), strings.TrimPrefix(path, volDestName)) - return path, err -} - -func isBindMountDestName(path string, ctr *libpod.Container) (bool, specs.Mount) { - separator := string(os.PathSeparator) - if filepath.IsAbs(path) { - path = strings.TrimPrefix(path, string(os.PathSeparator)) - } - if path == "" { - return false, specs.Mount{} - } - for _, m := range ctr.Config().Spec.Mounts { - if m.Type != "bind" { - continue - } - mDest := strings.TrimPrefix(m.Destination, separator) - if matchVolumePath(path, mDest) { - return true, m - } - } - return false, specs.Mount{} -} - -func matchVolumePath(path, target string) bool { - pathStr := filepath.Clean(path) - target = filepath.Clean(target) - for len(pathStr) > len(target) && strings.Contains(pathStr, string(os.PathSeparator)) { - pathStr = pathStr[:strings.LastIndex(pathStr, string(os.PathSeparator))] - } - return pathStr == target -} - -func pathWithBindMountSource(m specs.Mount, path string) (string, error) { - if !filepath.IsAbs(path) { - path = filepath.Join(string(os.PathSeparator), path) - } - return securejoin.SecureJoin(m.Source, strings.TrimPrefix(path, m.Destination)) -} diff --git a/pkg/domain/infra/abi/generate.go b/pkg/domain/infra/abi/generate.go index 79bf2291e..79f55e2bd 100644 --- a/pkg/domain/infra/abi/generate.go +++ b/pkg/domain/infra/abi/generate.go @@ -41,28 +41,48 @@ func (ic *ContainerEngine) GenerateSystemd(ctx context.Context, nameOrID string, return &entities.GenerateSystemdReport{Units: units}, nil } -func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrID string, options entities.GenerateKubeOptions) (*entities.GenerateKubeReport, error) { +func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string, options entities.GenerateKubeOptions) (*entities.GenerateKubeReport, error) { var ( - pod *libpod.Pod + pods []*libpod.Pod podYAML *k8sAPI.Pod err error - ctr *libpod.Container + ctrs []*libpod.Container servicePorts []k8sAPI.ServicePort serviceYAML k8sAPI.Service ) - // Get the container in question. - ctr, err = ic.Libpod.LookupContainer(nameOrID) - if err != nil { - pod, err = ic.Libpod.LookupPod(nameOrID) + for _, nameOrID := range nameOrIDs { + // Get the container in question + ctr, err := ic.Libpod.LookupContainer(nameOrID) if err != nil { - return nil, err + pod, err := ic.Libpod.LookupPod(nameOrID) + if err != nil { + return nil, err + } + pods = append(pods, pod) + if len(pods) > 1 { + return nil, errors.New("can only generate single pod at a time") + } + } else { + if len(ctr.Dependencies()) > 0 { + return nil, errors.Wrapf(define.ErrNotImplemented, "containers with dependencies") + } + // we cannot deal with ctrs already in a pod + if len(ctr.PodID()) > 0 { + return nil, errors.Errorf("container %s is associated with pod %s: use generate on the pod itself", ctr.ID(), ctr.PodID()) + } + ctrs = append(ctrs, ctr) } - podYAML, servicePorts, err = pod.GenerateForKube() + } + + // check our inputs + if len(pods) > 0 && len(ctrs) > 0 { + return nil, errors.New("cannot generate pods and containers at the same time") + } + + if len(pods) == 1 { + podYAML, servicePorts, err = pods[0].GenerateForKube() } else { - if len(ctr.Dependencies()) > 0 { - return nil, errors.Wrapf(define.ErrNotImplemented, "containers with dependencies") - } - podYAML, err = ctr.GenerateForKube() + podYAML, err = libpod.GenerateForKube(ctrs) } if err != nil { return nil, err @@ -72,7 +92,7 @@ func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrID string, op serviceYAML = libpod.GenerateKubeServiceFromV1Pod(podYAML, servicePorts) } - content, err := generateKubeOutput(podYAML, &serviceYAML) + content, err := generateKubeOutput(podYAML, &serviceYAML, options.Service) if err != nil { return nil, err } @@ -80,7 +100,7 @@ func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrID string, op return &entities.GenerateKubeReport{Reader: bytes.NewReader(content)}, nil } -func generateKubeOutput(podYAML *k8sAPI.Pod, serviceYAML *k8sAPI.Service) ([]byte, error) { +func generateKubeOutput(podYAML *k8sAPI.Pod, serviceYAML *k8sAPI.Service, hasService bool) ([]byte, error) { var ( output []byte marshalledPod []byte @@ -93,7 +113,7 @@ func generateKubeOutput(podYAML *k8sAPI.Pod, serviceYAML *k8sAPI.Service) ([]byt return nil, err } - if serviceYAML != nil { + if hasService { marshalledService, err = yaml.Marshal(serviceYAML) if err != nil { return nil, err @@ -114,7 +134,7 @@ func generateKubeOutput(podYAML *k8sAPI.Pod, serviceYAML *k8sAPI.Service) ([]byt output = append(output, []byte(fmt.Sprintf(header, podmanVersion.Version))...) output = append(output, marshalledPod...) - if serviceYAML != nil { + if hasService { output = append(output, []byte("---\n")...) output = append(output, marshalledService...) } diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go index 1b523f06a..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,90 +703,79 @@ 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 { - srcRef, err := alltransports.ParseImageName(signimage) - if err != nil { - return nil, errors.Wrapf(err, "error parsing image name") - } - rawSource, err := srcRef.NewImageSource(ctx, sc) - if err != nil { - return nil, errors.Wrapf(err, "error getting image source") - } - err = rawSource.Close() - if err != nil { - logrus.Errorf("unable to close new image source %q", err) - } - getManifest, _, err := rawSource.GetManifest(ctx, nil) - if err != nil { - return nil, errors.Wrapf(err, "error getting getManifest") - } - dockerReference := rawSource.Reference().DockerReference() - if dockerReference == nil { - return nil, errors.Errorf("cannot determine canonical Docker reference for destination %s", transports.ImageName(rawSource.Reference())) - } - 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 - } + err = func() error { + srcRef, err := alltransports.ParseImageName(signimage) + if err != nil { + return errors.Wrapf(err, "error parsing image name") + } + rawSource, err := srcRef.NewImageSource(ctx, sc) + if err != nil { + return errors.Wrapf(err, "error getting image source") + } + defer func() { + if err = rawSource.Close(); err != nil { + logrus.Errorf("unable to close %s image source %q", srcRef.DockerReference().Name(), err) } - if sigStoreURI == "" { - return nil, errors.Errorf("no signature storage configuration found for %s", rawSource.Reference().DockerReference().String()) - + }() + getManifest, _, err := rawSource.GetManifest(ctx, nil) + if err != nil { + return errors.Wrapf(err, "error getting getManifest") + } + dockerReference := rawSource.Reference().DockerReference() + if dockerReference == nil { + return errors.Errorf("cannot determine canonical Docker reference for destination %s", transports.ImageName(rawSource.Reference())) + } + var sigStoreDir string + if options.Directory != "" { + 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(sigStoreURI) + sigStoreDir, err = localPathFromURI(signatureURL) if err != nil { - return nil, errors.Wrapf(err, "invalid signature storage %s", sigStoreURI) + return err } } - } - manifestDigest, err := manifest.Digest(getManifest) - if err != nil { - return nil, 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 nil, errors.Errorf("Unexpected path elements in Docker reference %s for signature storage", dockerReference.String()) - } + manifestDigest, err := manifest.Digest(getManifest) + if err != nil { + return err + } - // create signature - newSig, err := signature.SignDockerManifest(getManifest, dockerReference.String(), mech, options.SignBy) - if err != nil { - return nil, 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()) - if err := os.MkdirAll(signatureDir, 0751); err != nil { - // The directory is allowed to exist - if !os.IsExist(err) { - logrus.Error(err) - continue + // create signature + newSig, err := signature.SignDockerManifest(getManifest, dockerReference.String(), mech, options.SignBy) + if err != nil { + return errors.Wrapf(err, "error creating new signature") } - } - sigFilename, err := getSigFilename(signatureDir) - if err != nil { - logrus.Errorf("error creating sigstore file: %v", err) - continue - } - err = ioutil.WriteFile(filepath.Join(signatureDir, sigFilename), newSig, 0644) + // create the signstore file + 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) { + logrus.Error(err) + return nil + } + } + sigFilename, err := getSigFilename(signatureDir) + if err != nil { + logrus.Errorf("error creating sigstore file: %v", err) + return nil + } + err = ioutil.WriteFile(filepath.Join(signatureDir, sigFilename), newSig, 0644) + if err != nil { + logrus.Errorf("error storing signature for %s", rawSource.Reference().DockerReference().String()) + return nil + } + return nil + }() if err != nil { - logrus.Errorf("error storing signature for %s", rawSource.Reference().DockerReference().String()) - continue + return nil, err } } return nil, nil @@ -815,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/domain/infra/abi/images_list.go b/pkg/domain/infra/abi/images_list.go index 281b04294..c4b0b7712 100644 --- a/pkg/domain/infra/abi/images_list.go +++ b/pkg/domain/infra/abi/images_list.go @@ -35,13 +35,11 @@ func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions) Created: img.Created().Unix(), Dangling: img.Dangling(), Digest: string(img.Digest()), - Digests: digests, + RepoDigests: digests, History: img.NamesHistory(), Names: img.Names(), - ParentId: img.Parent, ReadOnly: img.IsReadOnly(), SharedSize: 0, - VirtualSize: img.VirtualSize, RepoTags: img.Names(), // may include tags and digests } e.Labels, err = img.Labels(ctx) @@ -60,6 +58,15 @@ func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions) return nil, errors.Wrapf(err, "error retrieving size of image %q: you may need to remove the image to resolve the error", img.ID()) } e.Size = int64(*sz) + // This is good enough for now, but has to be + // replaced later with correct calculation logic + e.VirtualSize = int64(*sz) + + parent, err := img.ParentID(ctx) + if err != nil { + return nil, errors.Wrapf(err, "error retrieving parent of image %q: you may need to remove the image to resolve the error", img.ID()) + } + e.ParentId = parent summaries = append(summaries, &e) } diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go index 72fd98ac1..ec2532bea 100644 --- a/pkg/domain/infra/abi/system.go +++ b/pkg/domain/infra/abi/system.go @@ -11,6 +11,7 @@ import ( "strings" "github.com/containers/common/pkg/config" + "github.com/containers/podman/v2/libpod" "github.com/containers/podman/v2/libpod/define" "github.com/containers/podman/v2/pkg/cgroups" "github.com/containers/podman/v2/pkg/domain/entities" @@ -86,7 +87,11 @@ func (ic *ContainerEngine) SetupRootless(_ context.Context, cmd *cobra.Command) return nil } - pausePidPath, err := util.GetRootlessPauseProcessPidPath() + tmpDir, err := ic.Libpod.TmpDir() + if err != nil { + return err + } + pausePidPath, err := util.GetRootlessPauseProcessPidPathGivenDir(tmpDir) if err != nil { return errors.Wrapf(err, "could not get pause process pid file path") } @@ -112,7 +117,7 @@ func (ic *ContainerEngine) SetupRootless(_ context.Context, cmd *cobra.Command) } became, ret, err = rootless.TryJoinFromFilePaths(pausePidPath, true, paths) - if err := movePauseProcessToScope(); err != nil { + if err := movePauseProcessToScope(ic.Libpod); err != nil { conf, err := ic.Config(context.Background()) if err != nil { return err @@ -133,8 +138,12 @@ func (ic *ContainerEngine) SetupRootless(_ context.Context, cmd *cobra.Command) return nil } -func movePauseProcessToScope() error { - pausePidPath, err := util.GetRootlessPauseProcessPidPath() +func movePauseProcessToScope(r *libpod.Runtime) error { + tmpDir, err := r.TmpDir() + if err != nil { + return err + } + pausePidPath, err := util.GetRootlessPauseProcessPidPathGivenDir(tmpDir) if err != nil { return errors.Wrapf(err, "could not get pause process pid file path") } diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index 63677719b..3584668c7 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -731,8 +731,8 @@ func (ic *ContainerEngine) ContainerPort(ctx context.Context, nameOrID string, o return reports, nil } -func (ic *ContainerEngine) ContainerCp(ctx context.Context, source, dest string, options entities.ContainerCpOptions) (*entities.ContainerCpReport, error) { - return nil, errors.New("not implemented") +func (ic *ContainerEngine) ContainerCp(ctx context.Context, source, dest string, options entities.ContainerCpOptions) error { + return errors.New("not implemented") } // Shutdown Libpod engine diff --git a/pkg/domain/infra/tunnel/generate.go b/pkg/domain/infra/tunnel/generate.go index 966f707b1..ebbfa143f 100644 --- a/pkg/domain/infra/tunnel/generate.go +++ b/pkg/domain/infra/tunnel/generate.go @@ -11,6 +11,6 @@ func (ic *ContainerEngine) GenerateSystemd(ctx context.Context, nameOrID string, return generate.Systemd(ic.ClientCxt, nameOrID, options) } -func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrID string, options entities.GenerateKubeOptions) (*entities.GenerateKubeReport, error) { - return generate.Kube(ic.ClientCxt, nameOrID, options) +func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string, options entities.GenerateKubeOptions) (*entities.GenerateKubeReport, error) { + return generate.Kube(ic.ClientCxt, nameOrIDs, options) } |