diff options
Diffstat (limited to 'pkg/domain/infra')
-rw-r--r-- | pkg/domain/infra/abi/containers.go | 30 | ||||
-rw-r--r-- | pkg/domain/infra/abi/cp.go | 433 | ||||
-rw-r--r-- | pkg/domain/infra/abi/events.go | 2 | ||||
-rw-r--r-- | pkg/domain/infra/abi/healthcheck.go | 2 | ||||
-rw-r--r-- | pkg/domain/infra/abi/images.go | 205 | ||||
-rw-r--r-- | pkg/domain/infra/abi/images_list.go | 2 | ||||
-rw-r--r-- | pkg/domain/infra/abi/pods.go | 2 | ||||
-rw-r--r-- | pkg/domain/infra/abi/runtime.go | 2 | ||||
-rw-r--r-- | pkg/domain/infra/abi/system.go | 41 | ||||
-rw-r--r-- | pkg/domain/infra/abi/terminal/sigproxy_linux.go | 2 | ||||
-rw-r--r-- | pkg/domain/infra/abi/terminal/terminal.go | 2 | ||||
-rw-r--r-- | pkg/domain/infra/abi/terminal/terminal_linux.go | 2 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/containers.go | 8 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/events.go | 5 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/images.go | 21 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/system.go | 4 |
16 files changed, 606 insertions, 157 deletions
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index 50003dbe2..73a0d8ec3 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -1,5 +1,3 @@ -// +build ABISupport - package abi import ( @@ -931,3 +929,31 @@ func (ic *ContainerEngine) ContainerUnmount(ctx context.Context, nameOrIds []str func (ic *ContainerEngine) Config(_ context.Context) (*config.Config, error) { return ic.Libpod.GetConfig() } + +func (ic *ContainerEngine) ContainerPort(ctx context.Context, nameOrId string, options entities.ContainerPortOptions) ([]*entities.ContainerPortReport, error) { + var reports []*entities.ContainerPortReport + ctrs, err := getContainersByContext(options.All, false, []string{nameOrId}, ic.Libpod) + if err != nil { + return nil, err + } + for _, con := range ctrs { + state, err := con.State() + if err != nil { + return nil, err + } + if state != define.ContainerStateRunning { + continue + } + portmappings, err := con.PortMappings() + if err != nil { + return nil, err + } + if len(portmappings) > 0 { + reports = append(reports, &entities.ContainerPortReport{ + Id: con.ID(), + Ports: portmappings, + }) + } + } + return reports, nil +} diff --git a/pkg/domain/infra/abi/cp.go b/pkg/domain/infra/abi/cp.go new file mode 100644 index 000000000..9fc1e3bee --- /dev/null +++ b/pkg/domain/infra/abi/cp.go @@ -0,0 +1,433 @@ +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/libpod/libpod" + "github.com/containers/libpod/libpod/define" + "github.com/containers/libpod/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) { + var extract bool + + 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 len(srcPath) == 0 || len(destPath) == 0 { + return nil, errors.Errorf("invalid arguments %s, %s you must specify paths", source, dest) + } + ctr := srcCtr + isFromHostToCtr := ctr == nil + if isFromHostToCtr { + ctr = destCtr + } + + 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) + } + }() + + 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) + } + }() + } + } + + 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(ctr, 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, errors.Wrapf(err, "error creating directory %q", destPath) + } + cleanedPath, err := securejoin.SecureJoin(mountPoint, filepath.Join(ctr.WorkingDir(), destPath)) + if err != nil { + return nil, err + } + destPath = cleanedPath + } + } else { + destOwner = idtools.IDPair{UID: os.Getuid(), GID: os.Getgid()} + if isVol, volDestName, volName := isVolumeDestName(srcPath, ctr); isVol { //nolint(gocritic) + path, err := pathWithVolumeMount(ctr, 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() + if err != nil { + return nil, errors.Wrapf(err, "err getting current working directory") + } + 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 +} + +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, + } + 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 + } + + } + 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]) + if err == nil { + return ctr, pathArr[1] + } + } + 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, errors.Wrapf(err, "error reading path %q", path) + } + 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 errors.Wrapf(err, "error checking directory %q", destdir) + } + destDirIsExist := err == nil + if err = os.MkdirAll(destdir, 0755); err != nil { + return errors.Wrapf(err, "error creating directory %q", destdir) + } + + // 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))) { + destPath = filepath.Join(destPath, filepath.Base(srcPath)) + } + 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 errors.Wrapf(err, "failed to get stat of dest path %s", destPath) + } + } + 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 errors.Wrapf(err, "error opening file %s", srcPath) + } + 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(ctr *libpod.Container, 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/events.go b/pkg/domain/infra/abi/events.go index 9540a5b96..20773cdce 100644 --- a/pkg/domain/infra/abi/events.go +++ b/pkg/domain/infra/abi/events.go @@ -1,5 +1,3 @@ -//+build ABISupport - package abi import ( diff --git a/pkg/domain/infra/abi/healthcheck.go b/pkg/domain/infra/abi/healthcheck.go index 699483243..351bf4f7e 100644 --- a/pkg/domain/infra/abi/healthcheck.go +++ b/pkg/domain/infra/abi/healthcheck.go @@ -1,5 +1,3 @@ -// +build ABISupport - package abi import ( diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go index 4353e0798..32f7d75e5 100644 --- a/pkg/domain/infra/abi/images.go +++ b/pkg/domain/infra/abi/images.go @@ -1,5 +1,3 @@ -// +build ABISupport - package abi import ( @@ -23,6 +21,7 @@ import ( domainUtils "github.com/containers/libpod/pkg/domain/utils" "github.com/containers/libpod/pkg/util" "github.com/containers/storage" + "github.com/hashicorp/go-multierror" imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -36,76 +35,6 @@ func (ir *ImageEngine) Exists(_ context.Context, nameOrId string) (*entities.Boo return &entities.BoolReport{Value: err == nil}, nil } -func (ir *ImageEngine) Delete(ctx context.Context, nameOrId []string, opts entities.ImageDeleteOptions) (*entities.ImageDeleteReport, error) { - report := entities.ImageDeleteReport{} - - if opts.All { - var previousTargets []*libpodImage.Image - repeatRun: - targets, err := ir.Libpod.ImageRuntime().GetRWImages() - if err != nil { - return &report, errors.Wrapf(err, "unable to query local images") - } - if len(targets) == 0 { - return &report, nil - } - if len(targets) > 0 && len(targets) == len(previousTargets) { - return &report, errors.New("unable to delete all images; re-run the rmi command again.") - } - previousTargets = targets - - for _, img := range targets { - isParent, err := img.IsParent(ctx) - if err != nil { - return &report, err - } - if isParent { - continue - } - err = ir.deleteImage(ctx, img, opts, report) - report.Errors = append(report.Errors, err) - } - if len(previousTargets) != 1 { - goto repeatRun - } - return &report, nil - } - - for _, id := range nameOrId { - image, err := ir.Libpod.ImageRuntime().NewFromLocal(id) - if err != nil { - return nil, err - } - - err = ir.deleteImage(ctx, image, opts, report) - if err != nil { - return &report, err - } - } - return &report, nil -} - -func (ir *ImageEngine) deleteImage(ctx context.Context, img *libpodImage.Image, opts entities.ImageDeleteOptions, report entities.ImageDeleteReport) error { - results, err := ir.Libpod.RemoveImage(ctx, img, opts.Force) - switch errors.Cause(err) { - case nil: - break - case storage.ErrImageUsedByContainer: - report.ImageInUse = errors.New( - fmt.Sprintf("A container associated with containers/storage, i.e. via Buildah, CRI-O, etc., may be associated with this image: %-12.12s\n", img.ID())) - return nil - case libpodImage.ErrNoSuchImage: - report.ImageNotFound = err - return nil - default: - return err - } - - report.Deleted = append(report.Deleted, results.Deleted) - report.Untagged = append(report.Untagged, results.Untagged...) - return nil -} - func (ir *ImageEngine) Prune(ctx context.Context, opts entities.ImagePruneOptions) (*entities.ImagePruneReport, error) { results, err := ir.Libpod.ImageRuntime().PruneImages(ctx, opts.All, opts.Filter) if err != nil { @@ -488,3 +417,135 @@ func (ir *ImageEngine) Tree(ctx context.Context, nameOrId string, opts entities. } return &entities.ImageTreeReport{Tree: results}, nil } + +// Remove removes one or more images from local storage. +func (ir *ImageEngine) Remove(ctx context.Context, images []string, opts entities.ImageRemoveOptions) (report *entities.ImageRemoveReport, finalError error) { + var ( + // noSuchImageErrors indicates that at least one image was not found. + noSuchImageErrors bool + // inUseErrors indicates that at least one image is being used by a + // container. + inUseErrors bool + // otherErrors indicates that at least one error other than the two + // above occured. + otherErrors bool + // deleteError is a multierror to conveniently collect errors during + // removal. We really want to delete as many images as possible and not + // error out immediately. + deleteError *multierror.Error + ) + + report = &entities.ImageRemoveReport{} + + // Set the removalCode and the error after all work is done. + defer func() { + switch { + // 2 + case inUseErrors: + // One of the specified images has child images or is + // being used by a container. + report.ExitCode = 2 + // 1 + case noSuchImageErrors && !(otherErrors || inUseErrors): + // One of the specified images did not exist, and no other + // failures. + report.ExitCode = 1 + // 0 + default: + // Nothing to do. + } + if deleteError != nil { + // go-multierror has a trailing new line which we need to remove to normalize the string. + finalError = deleteError.ErrorOrNil() + finalError = errors.New(strings.TrimSpace(finalError.Error())) + } + }() + + // deleteImage is an anonymous function to conveniently delete an image + // withouth having to pass all local data around. + deleteImage := func(img *image.Image) error { + results, err := ir.Libpod.RemoveImage(ctx, img, opts.Force) + switch errors.Cause(err) { + case nil: + break + case storage.ErrImageUsedByContainer: + inUseErrors = true // Important for exit codes in Podman. + return errors.New( + fmt.Sprintf("A container associated with containers/storage, i.e. via Buildah, CRI-O, etc., may be associated with this image: %-12.12s\n", img.ID())) + default: + otherErrors = true // Important for exit codes in Podman. + return err + } + + report.Deleted = append(report.Deleted, results.Deleted) + report.Untagged = append(report.Untagged, results.Untagged...) + return nil + } + + // Delete all images from the local storage. + if opts.All { + previousImages := 0 + // Remove all images one-by-one. + for { + storageImages, err := ir.Libpod.ImageRuntime().GetRWImages() + if err != nil { + deleteError = multierror.Append(deleteError, + errors.Wrapf(err, "unable to query local images")) + otherErrors = true // Important for exit codes in Podman. + return + } + // No images (left) to remove, so we're done. + if len(storageImages) == 0 { + return + } + // Prevent infinity loops by making a delete-progress check. + if previousImages == len(storageImages) { + otherErrors = true // Important for exit codes in Podman. + deleteError = multierror.Append(deleteError, + errors.New("unable to delete all images, check errors and re-run image removal if needed")) + break + } + previousImages = len(storageImages) + // Delete all "leaves" (i.e., images without child images). + for _, img := range storageImages { + isParent, err := img.IsParent(ctx) + if err != nil { + otherErrors = true // Important for exit codes in Podman. + deleteError = multierror.Append(deleteError, err) + } + // Skip parent images. + if isParent { + continue + } + if err := deleteImage(img); err != nil { + deleteError = multierror.Append(deleteError, err) + } + } + } + + return + } + + // Delete only the specified images. + for _, id := range images { + img, err := ir.Libpod.ImageRuntime().NewFromLocal(id) + switch errors.Cause(err) { + case nil: + break + case image.ErrNoSuchImage: + noSuchImageErrors = true // Important for exit codes in Podman. + fallthrough + default: + deleteError = multierror.Append(deleteError, err) + continue + } + + err = deleteImage(img) + if err != nil { + otherErrors = true // Important for exit codes in Podman. + deleteError = multierror.Append(deleteError, err) + } + } + + return +} diff --git a/pkg/domain/infra/abi/images_list.go b/pkg/domain/infra/abi/images_list.go index 68b961cb6..9add915ea 100644 --- a/pkg/domain/infra/abi/images_list.go +++ b/pkg/domain/infra/abi/images_list.go @@ -1,5 +1,3 @@ -// +build ABISupport - package abi import ( diff --git a/pkg/domain/infra/abi/pods.go b/pkg/domain/infra/abi/pods.go index 6b6e13e24..c4ae9efbf 100644 --- a/pkg/domain/infra/abi/pods.go +++ b/pkg/domain/infra/abi/pods.go @@ -1,5 +1,3 @@ -// +build ABISupport - package abi import ( diff --git a/pkg/domain/infra/abi/runtime.go b/pkg/domain/infra/abi/runtime.go index b53fb6d3a..7394cadfc 100644 --- a/pkg/domain/infra/abi/runtime.go +++ b/pkg/domain/infra/abi/runtime.go @@ -1,5 +1,3 @@ -// +build ABISupport - package abi import ( diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go index 078f5404d..e5c109ee6 100644 --- a/pkg/domain/infra/abi/system.go +++ b/pkg/domain/infra/abi/system.go @@ -1,20 +1,15 @@ -// +build ABISupport - package abi import ( "context" "fmt" "io/ioutil" - "net" "os" "strconv" - "strings" "syscall" "github.com/containers/common/pkg/config" "github.com/containers/libpod/libpod/define" - api "github.com/containers/libpod/pkg/api/server" "github.com/containers/libpod/pkg/cgroups" "github.com/containers/libpod/pkg/domain/entities" "github.com/containers/libpod/pkg/rootless" @@ -33,42 +28,6 @@ func (ic *ContainerEngine) Info(ctx context.Context) (*define.Info, error) { return ic.Libpod.Info() } -func (ic *ContainerEngine) RestService(_ context.Context, opts entities.ServiceOptions) error { - var ( - listener *net.Listener - err error - ) - - if opts.URI != "" { - fields := strings.Split(opts.URI, ":") - if len(fields) == 1 { - return errors.Errorf("%s is an invalid socket destination", opts.URI) - } - address := strings.Join(fields[1:], ":") - l, err := net.Listen(fields[0], address) - if err != nil { - return errors.Wrapf(err, "unable to create socket %s", opts.URI) - } - listener = &l - } - - server, err := api.NewServerWithSettings(ic.Libpod, opts.Timeout, listener) - if err != nil { - return err - } - defer func() { - if err := server.Shutdown(); err != nil { - logrus.Warnf("Error when stopping API service: %s", err) - } - }() - - err = server.Serve() - if listener != nil { - _ = (*listener).Close() - } - return err -} - func (ic *ContainerEngine) VarlinkService(_ context.Context, opts entities.ServiceOptions) error { var varlinkInterfaces = []*iopodman.VarlinkInterface{ iopodmanAPI.New(opts.Command, ic.Libpod), diff --git a/pkg/domain/infra/abi/terminal/sigproxy_linux.go b/pkg/domain/infra/abi/terminal/sigproxy_linux.go index d7f5853d8..b422e549e 100644 --- a/pkg/domain/infra/abi/terminal/sigproxy_linux.go +++ b/pkg/domain/infra/abi/terminal/sigproxy_linux.go @@ -1,5 +1,3 @@ -// +build ABISupport - package terminal import ( diff --git a/pkg/domain/infra/abi/terminal/terminal.go b/pkg/domain/infra/abi/terminal/terminal.go index f187bdd6b..0fc3af511 100644 --- a/pkg/domain/infra/abi/terminal/terminal.go +++ b/pkg/domain/infra/abi/terminal/terminal.go @@ -1,5 +1,3 @@ -// +build ABISupport - package terminal import ( diff --git a/pkg/domain/infra/abi/terminal/terminal_linux.go b/pkg/domain/infra/abi/terminal/terminal_linux.go index 664205df1..15701342f 100644 --- a/pkg/domain/infra/abi/terminal/terminal_linux.go +++ b/pkg/domain/infra/abi/terminal/terminal_linux.go @@ -1,5 +1,3 @@ -// +build ABISupport - package terminal import ( diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index 679bb371b..8867ce27f 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -371,3 +371,11 @@ func (ic *ContainerEngine) ContainerUnmount(ctx context.Context, nameOrIds []str func (ic *ContainerEngine) Config(_ context.Context) (*config.Config, error) { return config.Default() } + +func (ic *ContainerEngine) ContainerPort(ctx context.Context, nameOrId string, options entities.ContainerPortOptions) ([]*entities.ContainerPortReport, error) { + return nil, errors.New("not implemented") +} + +func (ic *ContainerEngine) ContainerCp(ctx context.Context, source, dest string, options entities.ContainerCpOptions) (*entities.ContainerCpReport, error) { + return nil, errors.New("not implemented") +} diff --git a/pkg/domain/infra/tunnel/events.go b/pkg/domain/infra/tunnel/events.go index 46d88341a..93da3aeb4 100644 --- a/pkg/domain/infra/tunnel/events.go +++ b/pkg/domain/infra/tunnel/events.go @@ -4,7 +4,6 @@ import ( "context" "strings" - "github.com/containers/libpod/pkg/api/handlers" "github.com/containers/libpod/pkg/bindings/system" "github.com/containers/libpod/pkg/domain/entities" "github.com/pkg/errors" @@ -21,10 +20,10 @@ func (ic *ContainerEngine) Events(ctx context.Context, opts entities.EventsOptio filters[split[0]] = append(filters[split[0]], strings.Join(split[1:], "=")) } } - binChan := make(chan handlers.Event) + binChan := make(chan entities.Event) go func() { for e := range binChan { - opts.EventChan <- e.ToLibpodEvent() + opts.EventChan <- entities.ConvertToLibpodEvent(e) } }() return system.Events(ic.ClientCxt, binChan, nil, &opts.Since, &opts.Until, filters) diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go index 2decd605d..822842936 100644 --- a/pkg/domain/infra/tunnel/images.go +++ b/pkg/domain/infra/tunnel/images.go @@ -19,25 +19,8 @@ func (ir *ImageEngine) Exists(_ context.Context, nameOrId string) (*entities.Boo return &entities.BoolReport{Value: found}, err } -func (ir *ImageEngine) Delete(ctx context.Context, nameOrId []string, opts entities.ImageDeleteOptions) (*entities.ImageDeleteReport, error) { - report := entities.ImageDeleteReport{} - - for _, id := range nameOrId { - results, err := images.Remove(ir.ClientCxt, id, &opts.Force) - if err != nil { - return nil, err - } - for _, e := range results { - if a, ok := e["Deleted"]; ok { - report.Deleted = append(report.Deleted, a) - } - - if a, ok := e["Untagged"]; ok { - report.Untagged = append(report.Untagged, a) - } - } - } - return &report, nil +func (ir *ImageEngine) Remove(ctx context.Context, imagesArg []string, opts entities.ImageRemoveOptions) (*entities.ImageRemoveReport, error) { + return images.Remove(ir.ClientCxt, imagesArg, opts) } func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions) ([]*entities.ImageSummary, error) { diff --git a/pkg/domain/infra/tunnel/system.go b/pkg/domain/infra/tunnel/system.go index f373525c5..97bf885e7 100644 --- a/pkg/domain/infra/tunnel/system.go +++ b/pkg/domain/infra/tunnel/system.go @@ -14,10 +14,6 @@ func (ic *ContainerEngine) Info(ctx context.Context) (*define.Info, error) { return system.Info(ic.ClientCxt) } -func (ic *ContainerEngine) RestService(_ context.Context, _ entities.ServiceOptions) error { - panic(errors.New("rest service is not supported when tunneling")) -} - func (ic *ContainerEngine) VarlinkService(_ context.Context, _ entities.ServiceOptions) error { panic(errors.New("varlink service is not supported when tunneling")) } |