diff options
Diffstat (limited to 'pkg/domain/infra')
-rw-r--r-- | pkg/domain/infra/abi/containers.go | 201 | ||||
-rw-r--r-- | pkg/domain/infra/abi/images.go | 112 | ||||
-rw-r--r-- | pkg/domain/infra/abi/images_list.go | 80 | ||||
-rw-r--r-- | pkg/domain/infra/abi/pods.go | 2 | ||||
-rw-r--r-- | pkg/domain/infra/abi/volumes.go | 108 | ||||
-rw-r--r-- | pkg/domain/infra/runtime_abi.go | 20 | ||||
-rw-r--r-- | pkg/domain/infra/runtime_image_proxy.go | 2 | ||||
-rw-r--r-- | pkg/domain/infra/runtime_libpod.go | 12 | ||||
-rw-r--r-- | pkg/domain/infra/runtime_proxy.go | 2 | ||||
-rw-r--r-- | pkg/domain/infra/runtime_tunnel.go | 16 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/containers.go | 106 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/helpers.go | 3 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/images.go | 44 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/runtime.go | 18 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/volumes.go | 54 |
15 files changed, 656 insertions, 124 deletions
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index cdcd77246..a3da310c2 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -4,11 +4,16 @@ package abi import ( "context" + "io/ioutil" + "strings" + "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/adapter/shortcuts" "github.com/containers/libpod/pkg/domain/entities" + "github.com/containers/libpod/pkg/signal" "github.com/pkg/errors" + "github.com/sirupsen/logrus" ) // TODO: Should return *entities.ContainerExistsReport, error @@ -41,26 +46,196 @@ func (ic *ContainerEngine) ContainerWait(ctx context.Context, namesOrIds []strin return responses, nil } -func (ic *ContainerEngine) ContainerDelete(ctx context.Context, opts entities.ContainerDeleteOptions) (*entities.ContainerDeleteReport, error) { - panic("implement me") +func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []string, options entities.PauseUnPauseOptions) ([]*entities.PauseUnpauseReport, error) { + var ( + ctrs []*libpod.Container + err error + report []*entities.PauseUnpauseReport + ) + if options.All { + ctrs, err = ic.Libpod.GetAllContainers() + } else { + ctrs, err = shortcuts.GetContainersByContext(false, false, namesOrIds, ic.Libpod) + } + if err != nil { + return nil, err + } + for _, c := range ctrs { + err := c.Pause() + report = append(report, &entities.PauseUnpauseReport{Id: c.ID(), Err: err}) + } + return report, nil } -func (ic *ContainerEngine) ContainerPrune(ctx context.Context) (*entities.ContainerPruneReport, error) { - panic("implement me") +func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []string, options entities.PauseUnPauseOptions) ([]*entities.PauseUnpauseReport, error) { + var ( + ctrs []*libpod.Container + err error + report []*entities.PauseUnpauseReport + ) + if options.All { + ctrs, err = ic.Libpod.GetAllContainers() + } else { + ctrs, err = shortcuts.GetContainersByContext(false, false, namesOrIds, ic.Libpod) + } + if err != nil { + return nil, err + } + for _, c := range ctrs { + err := c.Unpause() + report = append(report, &entities.PauseUnpauseReport{Id: c.ID(), Err: err}) + } + return report, nil } +func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []string, options entities.StopOptions) ([]*entities.StopReport, error) { + var ( + reports []*entities.StopReport + ) + names := namesOrIds + for _, cidFile := range options.CIDFiles { + content, err := ioutil.ReadFile(cidFile) + if err != nil { + return nil, errors.Wrap(err, "error reading CIDFile") + } + id := strings.Split(string(content), "\n")[0] + names = append(names, id) + } + ctrs, err := shortcuts.GetContainersByContext(options.All, options.Latest, names, ic.Libpod) + if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchCtr) { + return nil, err + } + for _, con := range ctrs { + report := entities.StopReport{Id: con.ID()} + err = con.StopWithTimeout(options.Timeout) + if err != nil { + // These first two are considered non-fatal under the right conditions + if errors.Cause(err) == define.ErrCtrStopped { + logrus.Debugf("Container %s is already stopped", con.ID()) + reports = append(reports, &report) + continue -func (ic *ContainerEngine) PodDelete(ctx context.Context, opts entities.PodPruneOptions) (*entities.PodDeleteReport, error) { - panic("implement me") + } else if options.All && errors.Cause(err) == define.ErrCtrStateInvalid { + logrus.Debugf("Container %s is not running, could not stop", con.ID()) + reports = append(reports, &report) + continue + } + report.Err = err + reports = append(reports, &report) + continue + } + reports = append(reports, &report) + } + return reports, nil } -func (ic *ContainerEngine) PodPrune(ctx context.Context) (*entities.PodPruneReport, error) { - panic("implement me") +func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []string, options entities.KillOptions) ([]*entities.KillReport, error) { + var ( + reports []*entities.KillReport + ) + sig, err := signal.ParseSignalNameOrNumber(options.Signal) + if err != nil { + return nil, err + } + ctrs, err := shortcuts.GetContainersByContext(options.All, options.Latest, namesOrIds, ic.Libpod) + if err != nil { + return nil, err + } + for _, con := range ctrs { + reports = append(reports, &entities.KillReport{ + Id: con.ID(), + Err: con.Kill(uint(sig)), + }) + } + return reports, nil } - -func (ic *ContainerEngine) VolumeDelete(ctx context.Context, opts entities.VolumeDeleteOptions) (*entities.VolumeDeleteReport, error) { - panic("implement me") +func (ic *ContainerEngine) ContainerRestart(ctx context.Context, namesOrIds []string, options entities.RestartOptions) ([]*entities.RestartReport, error) { + var ( + reports []*entities.RestartReport + ) + ctrs, err := shortcuts.GetContainersByContext(options.All, options.Latest, namesOrIds, ic.Libpod) + if err != nil { + return nil, err + } + for _, con := range ctrs { + timeout := con.StopTimeout() + if options.Timeout != nil { + timeout = *options.Timeout + } + reports = append(reports, &entities.RestartReport{ + Id: con.ID(), + Err: con.RestartWithTimeout(ctx, timeout), + }) + } + return reports, nil } -func (ic *ContainerEngine) VolumePrune(ctx context.Context) (*entities.VolumePruneReport, error) { - panic("implement me") +func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string, options entities.RmOptions) ([]*entities.RmReport, error) { + var ( + reports []*entities.RmReport + ) + if options.Storage { + for _, ctr := range namesOrIds { + report := entities.RmReport{Id: ctr} + if err := ic.Libpod.RemoveStorageContainer(ctr, options.Force); err != nil { + report.Err = err + } + reports = append(reports, &report) + } + return reports, nil + } + + names := namesOrIds + for _, cidFile := range options.CIDFiles { + content, err := ioutil.ReadFile(cidFile) + if err != nil { + return nil, errors.Wrap(err, "error reading CIDFile") + } + id := strings.Split(string(content), "\n")[0] + names = append(names, id) + } + + ctrs, err := shortcuts.GetContainersByContext(options.All, options.Latest, names, ic.Libpod) + if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchCtr) { + // Failed to get containers. If force is specified, get the containers ID + // and evict them + if !options.Force { + return nil, err + } + + for _, ctr := range namesOrIds { + logrus.Debugf("Evicting container %q", ctr) + report := entities.RmReport{Id: ctr} + id, err := ic.Libpod.EvictContainer(ctx, ctr, options.Volumes) + if err != nil { + if options.Ignore && errors.Cause(err) == define.ErrNoSuchCtr { + logrus.Debugf("Ignoring error (--allow-missing): %v", err) + reports = append(reports, &report) + continue + } + report.Err = errors.Wrapf(err, "Failed to evict container: %q", id) + reports = append(reports, &report) + continue + } + reports = append(reports, &report) + } + return reports, nil + } + + for _, c := range ctrs { + report := entities.RmReport{Id: c.ID()} + err := ic.Libpod.RemoveContainer(ctx, c, options.Force, options.Volumes) + if err != nil { + if options.Ignore && errors.Cause(err) == define.ErrNoSuchCtr { + logrus.Debugf("Ignoring error (--allow-missing): %v", err) + reports = append(reports, &report) + continue + } + logrus.Debugf("Failed to remove container %s: %s", c.ID(), err.Error()) + report.Err = err + reports = append(reports, &report) + continue + } + reports = append(reports, &report) + } + return reports, nil } diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go index 2db08f259..203f14987 100644 --- a/pkg/domain/infra/abi/images.go +++ b/pkg/domain/infra/abi/images.go @@ -4,67 +4,99 @@ package abi import ( "context" + "fmt" libpodImage "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/pkg/domain/entities" - "github.com/containers/libpod/pkg/domain/utils" + "github.com/containers/storage" + "github.com/pkg/errors" ) -func (ir *ImageEngine) Delete(ctx context.Context, nameOrId string, opts entities.ImageDeleteOptions) (*entities.ImageDeleteReport, error) { - image, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrId) - if err != nil { - return nil, err +func (ir *ImageEngine) Exists(_ context.Context, nameOrId string) (*entities.BoolReport, error) { + if _, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrId); err != nil { + return &entities.BoolReport{}, nil } + return &entities.BoolReport{Value: true}, nil +} - results, err := ir.Libpod.RemoveImage(ctx, image, opts.Force) - if err != nil { - return nil, err +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 && 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(targets) >= 0 || len(previousTargets) != 1 { + goto repeatRun + } + return &report, nil } - report := entities.ImageDeleteReport{} - if err := utils.DeepCopy(&report, results); err != nil { - return nil, err + 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) Prune(ctx context.Context, opts entities.ImagePruneOptions) (*entities.ImagePruneReport, error) { - results, err := ir.Libpod.ImageRuntime().PruneImages(ctx, opts.All, []string{}) - if err != nil { - return nil, err +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 := entities.ImagePruneReport{} - copy(report.Report.Id, results) - return &report, nil + report.Deleted = append(report.Deleted, results.Deleted) + for _, e := range results.Untagged { + report.Untagged = append(report.Untagged, e) + } + return nil } -func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions) (*entities.ImageListReport, error) { - var ( - images []*libpodImage.Image - err error - ) - - filters := utils.ToLibpodFilters(opts.Filters) - if len(filters) > 0 { - images, err = ir.Libpod.ImageRuntime().GetImagesWithFilters(filters) - } else { - images, err = ir.Libpod.ImageRuntime().GetImages() - } +func (ir *ImageEngine) Prune(ctx context.Context, opts entities.ImagePruneOptions) (*entities.ImagePruneReport, error) { + results, err := ir.Libpod.ImageRuntime().PruneImages(ctx, opts.All, []string{}) if err != nil { return nil, err } - report := entities.ImageListReport{ - Images: make([]entities.ImageSummary, len(images)), - } - for i, img := range images { - hold := entities.ImageSummary{} - if err := utils.DeepCopy(&hold, img); err != nil { - return nil, err - } - report.Images[i] = hold - } + report := entities.ImagePruneReport{} + copy(report.Report.Id, results) return &report, nil } diff --git a/pkg/domain/infra/abi/images_list.go b/pkg/domain/infra/abi/images_list.go new file mode 100644 index 000000000..2f4020374 --- /dev/null +++ b/pkg/domain/infra/abi/images_list.go @@ -0,0 +1,80 @@ +// +build ABISupport + +package abi + +import ( + "context" + + libpodImage "github.com/containers/libpod/libpod/image" + "github.com/containers/libpod/pkg/domain/entities" +) + +func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions) ([]*entities.ImageSummary, error) { + var ( + images []*libpodImage.Image + err error + ) + + // TODO: Future work support for domain.Filters + // filters := utils.ToLibpodFilters(opts.Filters) + + if len(opts.Filter) > 0 { + images, err = ir.Libpod.ImageRuntime().GetImagesWithFilters(opts.Filter) + } else { + images, err = ir.Libpod.ImageRuntime().GetImages() + } + if err != nil { + return nil, err + } + + summaries := make([]*entities.ImageSummary, len(images)) + for i, img := range images { + var repoTags []string + if opts.All { + pairs, err := libpodImage.ReposToMap(img.Names()) + if err != nil { + return nil, err + } + + for repo, tags := range pairs { + for _, tag := range tags { + repoTags = append(repoTags, repo+":"+tag) + } + } + } else { + repoTags, _ = img.RepoTags() + } + + digests := make([]string, len(img.Digests())) + for j, d := range img.Digests() { + digests[j] = string(d) + } + + e := entities.ImageSummary{ + ID: img.ID(), + + ConfigDigest: string(img.ConfigDigest), + Created: img.Created().Unix(), + Dangling: img.Dangling(), + Digest: string(img.Digest()), + Digests: digests, + History: img.NamesHistory(), + Names: img.Names(), + ParentId: img.Parent, + ReadOnly: img.IsReadOnly(), + SharedSize: 0, + VirtualSize: img.VirtualSize, + RepoTags: repoTags, + } + e.Labels, _ = img.Labels(context.TODO()) + + ctnrs, _ := img.Containers() + e.Containers = len(ctnrs) + + sz, _ := img.Size(context.TODO()) + e.Size = int64(*sz) + + summaries[i] = &e + } + return summaries, nil +} diff --git a/pkg/domain/infra/abi/pods.go b/pkg/domain/infra/abi/pods.go index de22de68e..8dd7b5a0c 100644 --- a/pkg/domain/infra/abi/pods.go +++ b/pkg/domain/infra/abi/pods.go @@ -4,10 +4,10 @@ package abi import ( "context" - "github.com/pkg/errors" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/domain/entities" + "github.com/pkg/errors" ) func (ic *ContainerEngine) PodExists(ctx context.Context, nameOrId string) (*entities.BoolReport, error) { diff --git a/pkg/domain/infra/abi/volumes.go b/pkg/domain/infra/abi/volumes.go index 0783af441..5527bb82e 100644 --- a/pkg/domain/infra/abi/volumes.go +++ b/pkg/domain/infra/abi/volumes.go @@ -7,7 +7,9 @@ import ( "github.com/containers/libpod/libpod" "github.com/containers/libpod/pkg/domain/entities" + "github.com/containers/libpod/pkg/domain/filters" "github.com/containers/libpod/pkg/domain/infra/abi/parse" + "github.com/pkg/errors" ) func (ic *ContainerEngine) VolumeCreate(ctx context.Context, opts entities.VolumeCreateOptions) (*entities.IdOrNameResponse, error) { @@ -36,3 +38,109 @@ func (ic *ContainerEngine) VolumeCreate(ctx context.Context, opts entities.Volum } return &entities.IdOrNameResponse{IdOrName: vol.Name()}, nil } + +func (ic *ContainerEngine) VolumeRm(ctx context.Context, namesOrIds []string, opts entities.VolumeRmOptions) ([]*entities.VolumeRmReport, error) { + var ( + err error + reports []*entities.VolumeRmReport + vols []*libpod.Volume + ) + if opts.All { + vols, err = ic.Libpod.Volumes() + if err != nil { + return nil, err + } + } else { + for _, id := range namesOrIds { + vol, err := ic.Libpod.LookupVolume(id) + if err != nil { + reports = append(reports, &entities.VolumeRmReport{ + Err: err, + Id: id, + }) + continue + } + vols = append(vols, vol) + } + } + for _, vol := range vols { + reports = append(reports, &entities.VolumeRmReport{ + Err: ic.Libpod.RemoveVolume(ctx, vol, opts.Force), + Id: vol.Name(), + }) + } + return reports, nil +} + +func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []string, opts entities.VolumeInspectOptions) ([]*entities.VolumeInspectReport, error) { + var ( + err error + reports []*entities.VolumeInspectReport + vols []*libpod.Volume + ) + + // Note: as with previous implementation, a single failure here + // results a return. + if opts.All { + vols, err = ic.Libpod.GetAllVolumes() + if err != nil { + return nil, err + } + } else { + for _, v := range namesOrIds { + vol, err := ic.Libpod.LookupVolume(v) + if err != nil { + return nil, errors.Wrapf(err, "error inspecting volume %s", v) + } + vols = append(vols, vol) + } + } + for _, v := range vols { + config := entities.VolumeConfigResponse{ + Name: v.Name(), + Driver: v.Driver(), + Mountpoint: v.MountPoint(), + CreatedAt: v.CreatedTime(), + Labels: v.Labels(), + Scope: v.Scope(), + Options: v.Options(), + UID: v.UID(), + GID: v.GID(), + } + reports = append(reports, &entities.VolumeInspectReport{VolumeConfigResponse: &config}) + } + return reports, nil +} + +func (ic *ContainerEngine) VolumePrune(ctx context.Context, opts entities.VolumePruneOptions) ([]*entities.VolumePruneReport, error) { + return ic.Libpod.PruneVolumes(ctx) +} + +func (ic *ContainerEngine) VolumeList(ctx context.Context, opts entities.VolumeListOptions) ([]*entities.VolumeListReport, error) { + var ( + reports []*entities.VolumeListReport + ) + volumeFilters, err := filters.GenerateVolumeFilters(opts.Filter) + if err != nil { + return nil, err + } + vols, err := ic.Libpod.Volumes(volumeFilters...) + if err != nil { + return nil, err + } + for _, v := range vols { + config := entities.VolumeConfigResponse{ + Name: v.Name(), + Driver: v.Driver(), + Mountpoint: v.MountPoint(), + CreatedAt: v.CreatedTime(), + Labels: v.Labels(), + Scope: v.Scope(), + Options: v.Options(), + UID: v.UID(), + GID: v.GID(), + } + reports = append(reports, &entities.VolumeListReport{VolumeConfigResponse: config}) + } + return reports, nil +} diff --git a/pkg/domain/infra/runtime_abi.go b/pkg/domain/infra/runtime_abi.go index 31f832423..f11026571 100644 --- a/pkg/domain/infra/runtime_abi.go +++ b/pkg/domain/infra/runtime_abi.go @@ -12,27 +12,27 @@ import ( ) // NewContainerEngine factory provides a libpod runtime for container-related operations -func NewContainerEngine(opts entities.EngineOptions) (entities.ContainerEngine, error) { - switch opts.EngineMode { +func NewContainerEngine(facts entities.EngineOptions) (entities.ContainerEngine, error) { + switch facts.EngineMode { case entities.ABIMode: - r, err := NewLibpodRuntime(opts.FlagSet, opts.Flags) + r, err := NewLibpodRuntime(facts.FlagSet, facts) return r, err case entities.TunnelMode: - ctx, err := bindings.NewConnection(context.Background(), opts.Uri, opts.Identities...) + ctx, err := bindings.NewConnection(context.Background(), facts.Uri, facts.Identities...) return &tunnel.ContainerEngine{ClientCxt: ctx}, err } - return nil, fmt.Errorf("runtime mode '%v' is not supported", opts.EngineMode) + return nil, fmt.Errorf("runtime mode '%v' is not supported", facts.EngineMode) } // NewContainerEngine factory provides a libpod runtime for image-related operations -func NewImageEngine(opts entities.EngineOptions) (entities.ImageEngine, error) { - switch opts.EngineMode { +func NewImageEngine(facts entities.EngineOptions) (entities.ImageEngine, error) { + switch facts.EngineMode { case entities.ABIMode: - r, err := NewLibpodImageRuntime(opts.FlagSet, opts.Flags) + r, err := NewLibpodImageRuntime(facts.FlagSet, facts) return r, err case entities.TunnelMode: - ctx, err := bindings.NewConnection(context.Background(), opts.Uri, opts.Identities...) + ctx, err := bindings.NewConnection(context.Background(), facts.Uri, facts.Identities...) return &tunnel.ImageEngine{ClientCxt: ctx}, err } - return nil, fmt.Errorf("runtime mode '%v' is not supported", opts.EngineMode) + return nil, fmt.Errorf("runtime mode '%v' is not supported", facts.EngineMode) } diff --git a/pkg/domain/infra/runtime_image_proxy.go b/pkg/domain/infra/runtime_image_proxy.go index d2e66c08c..befc66b9a 100644 --- a/pkg/domain/infra/runtime_image_proxy.go +++ b/pkg/domain/infra/runtime_image_proxy.go @@ -12,7 +12,7 @@ import ( // ContainerEngine Image Proxy will be EOL'ed after podmanV2 is separated from libpod repo -func NewLibpodImageRuntime(flags *pflag.FlagSet, opts entities.EngineFlags) (entities.ImageEngine, error) { +func NewLibpodImageRuntime(flags *pflag.FlagSet, opts entities.EngineOptions) (entities.ImageEngine, error) { r, err := GetRuntime(context.Background(), flags, opts) if err != nil { return nil, err diff --git a/pkg/domain/infra/runtime_libpod.go b/pkg/domain/infra/runtime_libpod.go index b835152bf..730ded2e0 100644 --- a/pkg/domain/infra/runtime_libpod.go +++ b/pkg/domain/infra/runtime_libpod.go @@ -22,11 +22,11 @@ type engineOpts struct { migrate bool noStore bool withFDS bool - flags entities.EngineFlags + flags entities.EngineOptions } // GetRuntimeMigrate gets a libpod runtime that will perform a migration of existing containers -func GetRuntimeMigrate(ctx context.Context, fs *flag.FlagSet, ef entities.EngineFlags, newRuntime string) (*libpod.Runtime, error) { +func GetRuntimeMigrate(ctx context.Context, fs *flag.FlagSet, ef entities.EngineOptions, newRuntime string) (*libpod.Runtime, error) { return getRuntime(ctx, fs, &engineOpts{ name: newRuntime, renumber: false, @@ -38,7 +38,7 @@ func GetRuntimeMigrate(ctx context.Context, fs *flag.FlagSet, ef entities.Engine } // GetRuntimeDisableFDs gets a libpod runtime that will disable sd notify -func GetRuntimeDisableFDs(ctx context.Context, fs *flag.FlagSet, ef entities.EngineFlags) (*libpod.Runtime, error) { +func GetRuntimeDisableFDs(ctx context.Context, fs *flag.FlagSet, ef entities.EngineOptions) (*libpod.Runtime, error) { return getRuntime(ctx, fs, &engineOpts{ renumber: false, migrate: false, @@ -49,7 +49,7 @@ func GetRuntimeDisableFDs(ctx context.Context, fs *flag.FlagSet, ef entities.Eng } // GetRuntimeRenumber gets a libpod runtime that will perform a lock renumber -func GetRuntimeRenumber(ctx context.Context, fs *flag.FlagSet, ef entities.EngineFlags) (*libpod.Runtime, error) { +func GetRuntimeRenumber(ctx context.Context, fs *flag.FlagSet, ef entities.EngineOptions) (*libpod.Runtime, error) { return getRuntime(ctx, fs, &engineOpts{ renumber: true, migrate: false, @@ -60,7 +60,7 @@ func GetRuntimeRenumber(ctx context.Context, fs *flag.FlagSet, ef entities.Engin } // GetRuntime generates a new libpod runtime configured by command line options -func GetRuntime(ctx context.Context, flags *flag.FlagSet, ef entities.EngineFlags) (*libpod.Runtime, error) { +func GetRuntime(ctx context.Context, flags *flag.FlagSet, ef entities.EngineOptions) (*libpod.Runtime, error) { return getRuntime(ctx, flags, &engineOpts{ renumber: false, migrate: false, @@ -71,7 +71,7 @@ func GetRuntime(ctx context.Context, flags *flag.FlagSet, ef entities.EngineFlag } // GetRuntimeNoStore generates a new libpod runtime configured by command line options -func GetRuntimeNoStore(ctx context.Context, fs *flag.FlagSet, ef entities.EngineFlags) (*libpod.Runtime, error) { +func GetRuntimeNoStore(ctx context.Context, fs *flag.FlagSet, ef entities.EngineOptions) (*libpod.Runtime, error) { return getRuntime(ctx, fs, &engineOpts{ renumber: false, migrate: false, diff --git a/pkg/domain/infra/runtime_proxy.go b/pkg/domain/infra/runtime_proxy.go index 4095ae6e2..2e38c74b9 100644 --- a/pkg/domain/infra/runtime_proxy.go +++ b/pkg/domain/infra/runtime_proxy.go @@ -12,7 +12,7 @@ import ( // ContainerEngine Proxy will be EOL'ed after podmanV2 is separated from libpod repo -func NewLibpodRuntime(flags *flag.FlagSet, opts entities.EngineFlags) (entities.ContainerEngine, error) { +func NewLibpodRuntime(flags *flag.FlagSet, opts entities.EngineOptions) (entities.ContainerEngine, error) { r, err := GetRuntime(context.Background(), flags, opts) if err != nil { return nil, err diff --git a/pkg/domain/infra/runtime_tunnel.go b/pkg/domain/infra/runtime_tunnel.go index 5816ef0c0..dc04b4e53 100644 --- a/pkg/domain/infra/runtime_tunnel.go +++ b/pkg/domain/infra/runtime_tunnel.go @@ -11,25 +11,25 @@ import ( "github.com/containers/libpod/pkg/domain/infra/tunnel" ) -func NewContainerEngine(opts entities.EngineOptions) (entities.ContainerEngine, error) { - switch opts.EngineMode { +func NewContainerEngine(facts entities.EngineOptions) (entities.ContainerEngine, error) { + switch facts.EngineMode { case entities.ABIMode: return nil, fmt.Errorf("direct runtime not supported") case entities.TunnelMode: - ctx, err := bindings.NewConnection(context.Background(), opts.Uri, opts.Identities...) + ctx, err := bindings.NewConnection(context.Background(), facts.Uri, facts.Identities...) return &tunnel.ContainerEngine{ClientCxt: ctx}, err } - return nil, fmt.Errorf("runtime mode '%v' is not supported", opts.EngineMode) + return nil, fmt.Errorf("runtime mode '%v' is not supported", facts.EngineMode) } // NewImageEngine factory provides a libpod runtime for image-related operations -func NewImageEngine(opts entities.EngineOptions) (entities.ImageEngine, error) { - switch opts.EngineMode { +func NewImageEngine(facts entities.EngineOptions) (entities.ImageEngine, error) { + switch facts.EngineMode { case entities.ABIMode: return nil, fmt.Errorf("direct image runtime not supported") case entities.TunnelMode: - ctx, err := bindings.NewConnection(context.Background(), opts.Uri, opts.Identities...) + ctx, err := bindings.NewConnection(context.Background(), facts.Uri, facts.Identities...) return &tunnel.ImageEngine{ClientCxt: ctx}, err } - return nil, fmt.Errorf("runtime mode '%v' is not supported", opts.EngineMode) + return nil, fmt.Errorf("runtime mode '%v' is not supported", facts.EngineMode) } diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index 8bf74126d..a8ecff41b 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -33,10 +33,108 @@ func (ic *ContainerEngine) ContainerWait(ctx context.Context, namesOrIds []strin return responses, nil } -func (r *ContainerEngine) ContainerDelete(ctx context.Context, opts entities.ContainerDeleteOptions) (*entities.ContainerDeleteReport, error) { - panic("implement me") +func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []string, options entities.PauseUnPauseOptions) ([]*entities.PauseUnpauseReport, error) { + var ( + reports []*entities.PauseUnpauseReport + ) + ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds) + if err != nil { + return nil, err + } + for _, c := range ctrs { + err := containers.Pause(ic.ClientCxt, c.ID) + reports = append(reports, &entities.PauseUnpauseReport{Id: c.ID, Err: err}) + } + return reports, nil } -func (r *ContainerEngine) ContainerPrune(ctx context.Context) (*entities.ContainerPruneReport, error) { - panic("implement me") +func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []string, options entities.PauseUnPauseOptions) ([]*entities.PauseUnpauseReport, error) { + var ( + reports []*entities.PauseUnpauseReport + ) + ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds) + if err != nil { + return nil, err + } + for _, c := range ctrs { + err := containers.Unpause(ic.ClientCxt, c.ID) + reports = append(reports, &entities.PauseUnpauseReport{Id: c.ID, Err: err}) + } + return reports, nil +} + +func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []string, options entities.StopOptions) ([]*entities.StopReport, error) { + var ( + reports []*entities.StopReport + ) + ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds) + if err != nil { + return nil, err + } + for _, c := range ctrs { + report := entities.StopReport{Id: c.ID} + report.Err = containers.Stop(ic.ClientCxt, c.ID, &options.Timeout) + // TODO we need to associate errors returned by http with common + // define.errors so that we can equity tests. this will allow output + // to be the same as the native client + reports = append(reports, &report) + } + return reports, nil +} + +func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []string, options entities.KillOptions) ([]*entities.KillReport, error) { + var ( + reports []*entities.KillReport + ) + ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds) + if err != nil { + return nil, err + } + for _, c := range ctrs { + reports = append(reports, &entities.KillReport{ + Id: c.ID, + Err: containers.Kill(ic.ClientCxt, c.ID, options.Signal), + }) + } + return reports, nil +} + +func (ic *ContainerEngine) ContainerRestart(ctx context.Context, namesOrIds []string, options entities.RestartOptions) ([]*entities.RestartReport, error) { + var ( + reports []*entities.RestartReport + timeout *int + ) + if options.Timeout != nil { + t := int(*options.Timeout) + timeout = &t + } + ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds) + if err != nil { + return nil, err + } + for _, c := range ctrs { + reports = append(reports, &entities.RestartReport{ + Id: c.ID, + Err: containers.Restart(ic.ClientCxt, c.ID, timeout), + }) + } + return reports, nil +} + +func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string, options entities.RmOptions) ([]*entities.RmReport, error) { + var ( + reports []*entities.RmReport + ) + ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds) + if err != nil { + return nil, err + } + // TODO there is no endpoint for container eviction. Need to discuss + for _, c := range ctrs { + reports = append(reports, &entities.RmReport{ + Id: c.ID, + Err: containers.Remove(ic.ClientCxt, c.ID, &options.Force, &options.Volumes), + }) + } + return reports, nil } diff --git a/pkg/domain/infra/tunnel/helpers.go b/pkg/domain/infra/tunnel/helpers.go index d5a3224c2..11fca5278 100644 --- a/pkg/domain/infra/tunnel/helpers.go +++ b/pkg/domain/infra/tunnel/helpers.go @@ -2,6 +2,7 @@ package tunnel import ( "context" + "strings" "github.com/containers/libpod/pkg/api/handlers/libpod" "github.com/containers/libpod/pkg/bindings" @@ -27,7 +28,7 @@ func getContainersByContext(contextWithConnection context.Context, all bool, nam for _, id := range namesOrIds { var found bool for _, con := range c { - if id == con.ID || util.StringInSlice(id, con.Names) { + if id == con.ID || strings.HasPrefix(con.ID, id) || util.StringInSlice(id, con.Names) { cons = append(cons, con) found = true break diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go index 718685e57..6a241641e 100644 --- a/pkg/domain/infra/tunnel/images.go +++ b/pkg/domain/infra/tunnel/images.go @@ -9,46 +9,48 @@ import ( "github.com/containers/libpod/pkg/domain/utils" ) -func (ir *ImageEngine) Delete(ctx context.Context, nameOrId string, opts entities.ImageDeleteOptions) (*entities.ImageDeleteReport, error) { - results, err := images.Remove(ir.ClientCxt, nameOrId, &opts.Force) - if err != nil { - return nil, err - } +func (ir *ImageEngine) Exists(_ context.Context, nameOrId string) (*entities.BoolReport, error) { + found, err := images.Exists(ir.ClientCxt, nameOrId) + return &entities.BoolReport{Value: found}, err +} - report := entities.ImageDeleteReport{ - Untagged: nil, - Deleted: "", - } +func (ir *ImageEngine) Delete(ctx context.Context, nameOrId []string, opts entities.ImageDeleteOptions) (*entities.ImageDeleteReport, error) { + report := entities.ImageDeleteReport{} - for _, e := range results { - if a, ok := e["Deleted"]; ok { - report.Deleted = a + 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) + if a, ok := e["Untagged"]; ok { + report.Untagged = append(report.Untagged, a) + } } } - return &report, err + return &report, nil } -func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions) (*entities.ImageListReport, error) { +func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions) ([]*entities.ImageSummary, error) { images, err := images.List(ir.ClientCxt, &opts.All, opts.Filters) + if err != nil { return nil, err } - report := entities.ImageListReport{ - Images: make([]entities.ImageSummary, len(images)), - } + is := make([]*entities.ImageSummary, len(images)) for i, img := range images { hold := entities.ImageSummary{} if err := utils.DeepCopy(&hold, img); err != nil { return nil, err } - report.Images[i] = hold + is[i] = &hold } - return &report, nil + return is, nil } func (ir *ImageEngine) History(ctx context.Context, nameOrId string, opts entities.ImageHistoryOptions) (*entities.ImageHistoryReport, error) { diff --git a/pkg/domain/infra/tunnel/runtime.go b/pkg/domain/infra/tunnel/runtime.go index eb9b34e4a..c111f99e9 100644 --- a/pkg/domain/infra/tunnel/runtime.go +++ b/pkg/domain/infra/tunnel/runtime.go @@ -2,8 +2,6 @@ package tunnel import ( "context" - - "github.com/containers/libpod/pkg/domain/entities" ) // Image-related runtime using an ssh-tunnel to utilize Podman service @@ -15,19 +13,3 @@ type ImageEngine struct { type ContainerEngine struct { ClientCxt context.Context } - -func (r *ContainerEngine) PodDelete(ctx context.Context, opts entities.PodPruneOptions) (*entities.PodDeleteReport, error) { - panic("implement me") -} - -func (r *ContainerEngine) PodPrune(ctx context.Context) (*entities.PodPruneReport, error) { - panic("implement me") -} - -func (r *ContainerEngine) VolumeDelete(ctx context.Context, opts entities.VolumeDeleteOptions) (*entities.VolumeDeleteReport, error) { - panic("implement me") -} - -func (r *ContainerEngine) VolumePrune(ctx context.Context) (*entities.VolumePruneReport, error) { - panic("implement me") -} diff --git a/pkg/domain/infra/tunnel/volumes.go b/pkg/domain/infra/tunnel/volumes.go index 49cf6a2f6..e48a7fa7c 100644 --- a/pkg/domain/infra/tunnel/volumes.go +++ b/pkg/domain/infra/tunnel/volumes.go @@ -14,3 +14,57 @@ func (ic *ContainerEngine) VolumeCreate(ctx context.Context, opts entities.Volum } return &entities.IdOrNameResponse{IdOrName: response.Name}, nil } + +func (ic *ContainerEngine) VolumeRm(ctx context.Context, namesOrIds []string, opts entities.VolumeRmOptions) ([]*entities.VolumeRmReport, error) { + var ( + reports []*entities.VolumeRmReport + ) + + if opts.All { + vols, err := volumes.List(ic.ClientCxt, nil) + if err != nil { + return nil, err + } + for _, v := range vols { + namesOrIds = append(namesOrIds, v.Name) + } + } + for _, id := range namesOrIds { + reports = append(reports, &entities.VolumeRmReport{ + Err: volumes.Remove(ic.ClientCxt, id, &opts.Force), + Id: id, + }) + } + return reports, nil +} + +func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []string, opts entities.VolumeInspectOptions) ([]*entities.VolumeInspectReport, error) { + var ( + reports []*entities.VolumeInspectReport + ) + if opts.All { + vols, err := volumes.List(ic.ClientCxt, nil) + if err != nil { + return nil, err + } + for _, v := range vols { + namesOrIds = append(namesOrIds, v.Name) + } + } + for _, id := range namesOrIds { + data, err := volumes.Inspect(ic.ClientCxt, id) + if err != nil { + return nil, err + } + reports = append(reports, &entities.VolumeInspectReport{VolumeConfigResponse: data}) + } + return reports, nil +} + +func (ic *ContainerEngine) VolumePrune(ctx context.Context, opts entities.VolumePruneOptions) ([]*entities.VolumePruneReport, error) { + return volumes.Prune(ic.ClientCxt) +} + +func (ic *ContainerEngine) VolumeList(ctx context.Context, opts entities.VolumeListOptions) ([]*entities.VolumeListReport, error) { + return volumes.List(ic.ClientCxt, opts.Filter) +} |