summaryrefslogtreecommitdiff
path: root/pkg/domain
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/domain')
-rw-r--r--pkg/domain/entities/containers.go60
-rw-r--r--pkg/domain/entities/engine.go8
-rw-r--r--pkg/domain/entities/engine_container.go16
-rw-r--r--pkg/domain/entities/engine_image.go5
-rw-r--r--pkg/domain/entities/images.go75
-rw-r--r--pkg/domain/entities/set.go45
-rw-r--r--pkg/domain/entities/types.go8
-rw-r--r--pkg/domain/entities/volumes.go89
-rw-r--r--pkg/domain/filters/volumes.go70
-rw-r--r--pkg/domain/infra/abi/containers.go201
-rw-r--r--pkg/domain/infra/abi/images.go112
-rw-r--r--pkg/domain/infra/abi/images_list.go80
-rw-r--r--pkg/domain/infra/abi/pods.go2
-rw-r--r--pkg/domain/infra/abi/volumes.go108
-rw-r--r--pkg/domain/infra/runtime_abi.go20
-rw-r--r--pkg/domain/infra/runtime_image_proxy.go2
-rw-r--r--pkg/domain/infra/runtime_libpod.go12
-rw-r--r--pkg/domain/infra/runtime_proxy.go2
-rw-r--r--pkg/domain/infra/runtime_tunnel.go16
-rw-r--r--pkg/domain/infra/tunnel/containers.go106
-rw-r--r--pkg/domain/infra/tunnel/helpers.go3
-rw-r--r--pkg/domain/infra/tunnel/images.go44
-rw-r--r--pkg/domain/infra/tunnel/runtime.go18
-rw-r--r--pkg/domain/infra/tunnel/volumes.go54
24 files changed, 947 insertions, 209 deletions
diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go
index 0e1208b3b..8b7406ae8 100644
--- a/pkg/domain/entities/containers.go
+++ b/pkg/domain/entities/containers.go
@@ -21,3 +21,63 @@ type WaitReport struct {
type BoolReport struct {
Value bool
}
+
+type PauseUnPauseOptions struct {
+ All bool
+}
+
+type PauseUnpauseReport struct {
+ Err error
+ Id string
+}
+
+type StopOptions struct {
+ All bool
+ CIDFiles []string
+ Ignore bool
+ Latest bool
+ Timeout uint
+}
+
+type StopReport struct {
+ Err error
+ Id string
+}
+
+type KillOptions struct {
+ All bool
+ Latest bool
+ Signal string
+}
+
+type KillReport struct {
+ Err error
+ Id string
+}
+
+type RestartOptions struct {
+ All bool
+ Latest bool
+ Running bool
+ Timeout *uint
+}
+
+type RestartReport struct {
+ Err error
+ Id string
+}
+
+type RmOptions struct {
+ All bool
+ CIDFiles []string
+ Force bool
+ Ignore bool
+ Latest bool
+ Storage bool
+ Volumes bool
+}
+
+type RmReport struct {
+ Err error
+ Id string
+}
diff --git a/pkg/domain/entities/engine.go b/pkg/domain/entities/engine.go
index 08ef1df92..8553f5326 100644
--- a/pkg/domain/entities/engine.go
+++ b/pkg/domain/entities/engine.go
@@ -19,16 +19,12 @@ func (m EngineMode) String() string {
return string(m)
}
-// FIXME: merge EngineOptions and EngineFlags
type EngineOptions struct {
Uri string
Identities []string
FlagSet *pflag.FlagSet
- Flags EngineFlags
EngineMode EngineMode
-}
-type EngineFlags struct {
CGroupManager string
CniConfigDir string
ConmonPath string
@@ -61,9 +57,9 @@ type EngineFlags struct {
IgnoreHosts bool
}
-func NewEngineOptions() (EngineFlags, error) {
+func NewEngineOptions() (EngineOptions, error) {
u, _ := user.Current()
- return EngineFlags{
+ return EngineOptions{
CGroupManager: define.SystemdCgroupsManager,
CniConfigDir: "",
Config: "",
diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go
index 5820c12c3..2efdbd602 100644
--- a/pkg/domain/entities/engine_container.go
+++ b/pkg/domain/entities/engine_container.go
@@ -5,14 +5,18 @@ import (
)
type ContainerEngine interface {
- ContainerDelete(ctx context.Context, opts ContainerDeleteOptions) (*ContainerDeleteReport, error)
- ContainerPrune(ctx context.Context) (*ContainerPruneReport, error)
ContainerExists(ctx context.Context, nameOrId string) (*BoolReport, error)
+ ContainerKill(ctx context.Context, namesOrIds []string, options KillOptions) ([]*KillReport, error)
+ ContainerPause(ctx context.Context, namesOrIds []string, options PauseUnPauseOptions) ([]*PauseUnpauseReport, error)
+ ContainerRestart(ctx context.Context, namesOrIds []string, options RestartOptions) ([]*RestartReport, error)
+ ContainerRm(ctx context.Context, namesOrIds []string, options RmOptions) ([]*RmReport, error)
+ ContainerUnpause(ctx context.Context, namesOrIds []string, options PauseUnPauseOptions) ([]*PauseUnpauseReport, error)
+ ContainerStop(ctx context.Context, namesOrIds []string, options StopOptions) ([]*StopReport, error)
ContainerWait(ctx context.Context, namesOrIds []string, options WaitOptions) ([]WaitReport, error)
- PodDelete(ctx context.Context, opts PodPruneOptions) (*PodDeleteReport, error)
PodExists(ctx context.Context, nameOrId string) (*BoolReport, error)
- PodPrune(ctx context.Context) (*PodPruneReport, error)
VolumeCreate(ctx context.Context, opts VolumeCreateOptions) (*IdOrNameResponse, error)
- VolumeDelete(ctx context.Context, opts VolumeDeleteOptions) (*VolumeDeleteReport, error)
- VolumePrune(ctx context.Context) (*VolumePruneReport, error)
+ VolumeInspect(ctx context.Context, namesOrIds []string, opts VolumeInspectOptions) ([]*VolumeInspectReport, error)
+ VolumeRm(ctx context.Context, namesOrIds []string, opts VolumeRmOptions) ([]*VolumeRmReport, error)
+ VolumePrune(ctx context.Context, opts VolumePruneOptions) ([]*VolumePruneReport, error)
+ VolumeList(ctx context.Context, opts VolumeListOptions) ([]*VolumeListReport, error)
}
diff --git a/pkg/domain/entities/engine_image.go b/pkg/domain/entities/engine_image.go
index 27676d781..d0c860a04 100644
--- a/pkg/domain/entities/engine_image.go
+++ b/pkg/domain/entities/engine_image.go
@@ -5,8 +5,9 @@ import (
)
type ImageEngine interface {
- Delete(ctx context.Context, nameOrId string, opts ImageDeleteOptions) (*ImageDeleteReport, error)
+ Delete(ctx context.Context, nameOrId []string, opts ImageDeleteOptions) (*ImageDeleteReport, error)
+ Exists(ctx context.Context, nameOrId string) (*BoolReport, error)
History(ctx context.Context, nameOrId string, opts ImageHistoryOptions) (*ImageHistoryReport, error)
- List(ctx context.Context, opts ImageListOptions) (*ImageListReport, error)
+ List(ctx context.Context, opts ImageListOptions) ([]*ImageSummary, error)
Prune(ctx context.Context, opts ImagePruneOptions) (*ImagePruneReport, error)
}
diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go
index c84ed5351..4a51b3de4 100644
--- a/pkg/domain/entities/images.go
+++ b/pkg/domain/entities/images.go
@@ -48,22 +48,24 @@ func (i *Image) Id() string {
}
type ImageSummary struct {
- Identifier
- ID string `json:"Id"`
- ParentId string `json:",omitempty"`
- RepoTags []string `json:",omitempty"`
- Created int `json:",omitempty"`
- Size int `json:",omitempty"`
- SharedSize int `json:",omitempty"`
- VirtualSize int `json:",omitempty"`
- Labels string `json:",omitempty"`
- Containers int `json:",omitempty"`
- ReadOnly bool `json:",omitempty"`
- Dangling bool `json:",omitempty"`
+ ID string `json:"Id"`
+ ParentId string `json:",omitempty"`
+ RepoTags []string `json:",omitempty"`
+ Created int64 `json:",omitempty"`
+ 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"`
// Podman extensions
- Digest digest.Digest `json:",omitempty"`
- ConfigDigest digest.Digest `json:",omitempty"`
+ Names []string `json:",omitempty"`
+ Digest string `json:",omitempty"`
+ Digests []string `json:",omitempty"`
+ ConfigDigest string `json:",omitempty"`
+ History []string `json:",omitempty"`
}
func (i *ImageSummary) Id() string {
@@ -78,34 +80,26 @@ func (i *ImageSummary) IsDangling() bool {
return i.Dangling
}
-type ImageOptions struct {
- All bool
- Digests bool
- Filter []string
- Format string
- Noheading bool
- NoTrunc bool
- Quiet bool
- Sort string
- History bool
-}
-
type ImageDeleteOptions struct {
+ All bool
Force bool
}
-// ImageDeleteResponse is the response for removing an image from storage and containers
-// what was untagged vs actually removed
+// ImageDeleteResponse is the response for removing one or more image(s) from storage
+// and containers what was untagged vs actually removed
type ImageDeleteReport struct {
- Untagged []string `json:"untagged"`
- Deleted string `json:"deleted"`
+ Untagged []string `json:",omitempty"`
+ Deleted []string `json:",omitempty"`
+ Errors []error
+ ImageNotFound error
+ ImageInUse error
}
type ImageHistoryOptions struct{}
type ImageHistoryLayer struct {
ID string `json:"Id"`
- Created int64 `json:"Created,omitempty"`
+ Created int64 `json:",omitempty"`
CreatedBy string `json:",omitempty"`
Tags []string `json:",omitempty"`
Size int64 `json:",omitempty"`
@@ -124,21 +118,14 @@ type ImageInspectOptions struct {
}
type ImageListOptions struct {
- All bool `json:"all" schema:"all"`
- Digests bool `json:"digests" schema:"digests"`
- Filter []string `json:",omitempty"`
- Filters url.Values `json:"filters" schema:"filters"`
- Format string `json:",omitempty"`
- History bool `json:",omitempty"`
- Noheading bool `json:",omitempty"`
- NoTrunc bool `json:",omitempty"`
- Quiet bool `json:",omitempty"`
- Sort string `json:",omitempty"`
+ All bool `json:"all" schema:"all"`
+ Filter []string `json:",omitempty"`
+ Filters url.Values `json:"filters" schema:"filters"`
}
-type ImageListReport struct {
- Images []ImageSummary
-}
+// type ImageListReport struct {
+// Images []ImageSummary
+// }
type ImagePruneOptions struct {
All bool
diff --git a/pkg/domain/entities/set.go b/pkg/domain/entities/set.go
new file mode 100644
index 000000000..c8d6cb1a9
--- /dev/null
+++ b/pkg/domain/entities/set.go
@@ -0,0 +1,45 @@
+package entities
+
+import (
+ "strings"
+)
+
+type stringSet struct {
+ m map[string]struct{}
+}
+
+func NewStringSet(elem ...string) *stringSet {
+ s := &stringSet{}
+ s.m = make(map[string]struct{}, len(elem))
+ for _, e := range elem {
+ s.Add(e)
+ }
+ return s
+}
+
+func (s *stringSet) Add(elem string) {
+ s.m[elem] = struct{}{}
+}
+
+func (s *stringSet) Remove(elem string) {
+ delete(s.m, elem)
+}
+
+func (s *stringSet) Contains(elem string) bool {
+ _, ok := s.m[elem]
+ return ok
+}
+
+func (s *stringSet) Elements() []string {
+ keys := make([]string, len(s.m))
+ i := 0
+ for k := range s.m {
+ keys[i] = k
+ i++
+ }
+ return keys
+}
+
+func (s *stringSet) String() string {
+ return strings.Join(s.Elements(), ", ")
+}
diff --git a/pkg/domain/entities/types.go b/pkg/domain/entities/types.go
index 6f947dc4d..e7757a74b 100644
--- a/pkg/domain/entities/types.go
+++ b/pkg/domain/entities/types.go
@@ -13,13 +13,5 @@ type Report struct {
Err map[string]error
}
-type ContainerDeleteOptions struct{}
-type ContainerDeleteReport struct{ Report }
-type ContainerPruneReport struct{ Report }
-
type PodDeleteReport struct{ Report }
type PodPruneOptions struct{}
-type PodPruneReport struct{ Report }
-type VolumeDeleteOptions struct{}
-type VolumeDeleteReport struct{ Report }
-type VolumePruneReport struct{ Report }
diff --git a/pkg/domain/entities/volumes.go b/pkg/domain/entities/volumes.go
index ad12d0d01..23c066083 100644
--- a/pkg/domain/entities/volumes.go
+++ b/pkg/domain/entities/volumes.go
@@ -1,6 +1,8 @@
package entities
-import "time"
+import (
+ "time"
+)
// swagger:model VolumeCreate
type VolumeCreateOptions struct {
@@ -20,22 +22,71 @@ type IdOrNameResponse struct {
}
type VolumeConfigResponse struct {
- // Name of the volume.
- Name string `json:"name"`
- Labels map[string]string `json:"labels"`
- // The volume driver. Empty string or local does not activate a volume
- // driver, all other volumes will.
- Driver string `json:"volumeDriver"`
- // The location the volume is mounted at.
- MountPoint string `json:"mountPoint"`
- // Time the volume was created.
- CreatedTime time.Time `json:"createdAt,omitempty"`
- // Options to pass to the volume driver. For the local driver, this is
- // a list of mount options. For other drivers, they are passed to the
- // volume driver handling the volume.
- Options map[string]string `json:"volumeOptions,omitempty"`
- // UID the volume will be created as.
- UID int `json:"uid"`
- // GID the volume will be created as.
- GID int `json:"gid"`
+ // Name is the name of the volume.
+ Name string `json:"Name"`
+ // Driver is the driver used to create the volume.
+ // This will be properly implemented in a future version.
+ Driver string `json:"Driver"`
+ // Mountpoint is the path on the host where the volume is mounted.
+ Mountpoint string `json:"Mountpoint"`
+ // CreatedAt is the date and time the volume was created at. This is not
+ // stored for older Libpod volumes; if so, it will be omitted.
+ CreatedAt time.Time `json:"CreatedAt,omitempty"`
+ // Status is presently unused and provided only for Docker compatibility.
+ // In the future it will be used to return information on the volume's
+ // current state.
+ Status map[string]string `json:"Status,omitempty"`
+ // Labels includes the volume's configured labels, key:value pairs that
+ // can be passed during volume creation to provide information for third
+ // party tools.
+ Labels map[string]string `json:"Labels"`
+ // Scope is unused and provided solely for Docker compatibility. It is
+ // unconditionally set to "local".
+ Scope string `json:"Scope"`
+ // Options is a set of options that were used when creating the volume.
+ // It is presently not used.
+ Options map[string]string `json:"Options"`
+ // UID is the UID that the volume was created with.
+ UID int `json:"UID,omitempty"`
+ // GID is the GID that the volume was created with.
+ GID int `json:"GID,omitempty"`
+ // Anonymous indicates that the volume was created as an anonymous
+ // volume for a specific container, and will be be removed when any
+ // container using it is removed.
+ Anonymous bool `json:"Anonymous,omitempty"`
+}
+
+type VolumeRmOptions struct {
+ All bool
+ Force bool
+}
+
+type VolumeRmReport struct {
+ Err error
+ Id string
+}
+
+type VolumeInspectOptions struct {
+ All bool
+}
+
+type VolumeInspectReport struct {
+ *VolumeConfigResponse
+}
+
+type VolumePruneOptions struct {
+ Force bool
+}
+
+type VolumePruneReport struct {
+ Err error
+ Id string
+}
+
+type VolumeListOptions struct {
+ Filter map[string][]string
+}
+
+type VolumeListReport struct {
+ VolumeConfigResponse
}
diff --git a/pkg/domain/filters/volumes.go b/pkg/domain/filters/volumes.go
new file mode 100644
index 000000000..f97c3f570
--- /dev/null
+++ b/pkg/domain/filters/volumes.go
@@ -0,0 +1,70 @@
+package filters
+
+import (
+ "strings"
+
+ "github.com/containers/libpod/libpod"
+ "github.com/pkg/errors"
+)
+
+func GenerateVolumeFilters(filters map[string][]string) ([]libpod.VolumeFilter, error) {
+ var vf []libpod.VolumeFilter
+ for filter, v := range filters {
+ for _, val := range v {
+ switch filter {
+ case "name":
+ nameVal := val
+ vf = append(vf, func(v *libpod.Volume) bool {
+ return nameVal == v.Name()
+ })
+ case "driver":
+ driverVal := val
+ vf = append(vf, func(v *libpod.Volume) bool {
+ return v.Driver() == driverVal
+ })
+ case "scope":
+ scopeVal := val
+ vf = append(vf, func(v *libpod.Volume) bool {
+ return v.Scope() == scopeVal
+ })
+ case "label":
+ filterArray := strings.SplitN(val, "=", 2)
+ filterKey := filterArray[0]
+ var filterVal string
+ if len(filterArray) > 1 {
+ filterVal = filterArray[1]
+ } else {
+ filterVal = ""
+ }
+ vf = append(vf, func(v *libpod.Volume) bool {
+ for labelKey, labelValue := range v.Labels() {
+ if labelKey == filterKey && ("" == filterVal || labelValue == filterVal) {
+ return true
+ }
+ }
+ return false
+ })
+ case "opt":
+ filterArray := strings.SplitN(val, "=", 2)
+ filterKey := filterArray[0]
+ var filterVal string
+ if len(filterArray) > 1 {
+ filterVal = filterArray[1]
+ } else {
+ filterVal = ""
+ }
+ vf = append(vf, func(v *libpod.Volume) bool {
+ for labelKey, labelValue := range v.Options() {
+ if labelKey == filterKey && ("" == filterVal || labelValue == filterVal) {
+ return true
+ }
+ }
+ return false
+ })
+ default:
+ return nil, errors.Errorf("%q is in an invalid volume filter", filter)
+ }
+ }
+ }
+ return vf, nil
+}
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)
+}