diff options
Diffstat (limited to 'pkg/domain/infra/abi')
-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 |
5 files changed, 449 insertions, 54 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 +} |