diff options
Diffstat (limited to 'pkg/domain')
-rw-r--r-- | pkg/domain/entities/containers.go | 10 | ||||
-rw-r--r-- | pkg/domain/entities/engine_container.go | 20 | ||||
-rw-r--r-- | pkg/domain/entities/engine_image.go | 6 | ||||
-rw-r--r-- | pkg/domain/entities/healthcheck.go | 3 | ||||
-rw-r--r-- | pkg/domain/entities/images.go | 80 | ||||
-rw-r--r-- | pkg/domain/entities/pods.go | 13 | ||||
-rw-r--r-- | pkg/domain/entities/types.go | 7 | ||||
-rw-r--r-- | pkg/domain/infra/abi/containers.go | 10 | ||||
-rw-r--r-- | pkg/domain/infra/abi/healthcheck.go | 26 | ||||
-rw-r--r-- | pkg/domain/infra/abi/images.go | 183 | ||||
-rw-r--r-- | pkg/domain/infra/abi/pods.go | 59 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/containers.go | 18 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/healthcheck.go | 13 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/images.go | 99 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/pods.go | 4 |
15 files changed, 524 insertions, 27 deletions
diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go index 3389e4db5..d51124f55 100644 --- a/pkg/domain/entities/containers.go +++ b/pkg/domain/entities/containers.go @@ -98,12 +98,6 @@ type RmReport struct { Id string } -type ContainerInspectOptions struct { - Format string - Latest bool - Size bool -} - type ContainerInspectReport struct { *define.InspectContainerData } @@ -123,3 +117,7 @@ type CommitOptions struct { type CommitReport struct { Id string } + +type ContainerExportOptions struct { + Output string +} diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go index dddaa6013..a122857cd 100644 --- a/pkg/domain/entities/engine_container.go +++ b/pkg/domain/entities/engine_container.go @@ -2,34 +2,38 @@ package entities import ( "context" + + "github.com/containers/libpod/libpod/define" ) type ContainerEngine interface { ContainerCommit(ctx context.Context, nameOrId string, options CommitOptions) (*CommitReport, error) ContainerExists(ctx context.Context, nameOrId string) (*BoolReport, error) - ContainerInspect(ctx context.Context, namesOrIds []string, options ContainerInspectOptions) ([]*ContainerInspectReport, error) + ContainerInspect(ctx context.Context, namesOrIds []string, options InspectOptions) ([]*ContainerInspectReport, error) + ContainerExport(ctx context.Context, nameOrId string, options ContainerExportOptions) 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) ContainerTop(ctx context.Context, options TopOptions) (*StringSliceReport, error) + ContainerUnpause(ctx context.Context, namesOrIds []string, options PauseUnPauseOptions) ([]*PauseUnpauseReport, error) + ContainerWait(ctx context.Context, namesOrIds []string, options WaitOptions) ([]WaitReport, error) + HealthCheckRun(ctx context.Context, nameOrId string, options HealthCheckOptions) (*define.HealthCheckResults, error) PodCreate(ctx context.Context, opts PodCreateOptions) (*PodCreateReport, error) PodExists(ctx context.Context, nameOrId string) (*BoolReport, error) PodKill(ctx context.Context, namesOrIds []string, options PodKillOptions) ([]*PodKillReport, error) PodPause(ctx context.Context, namesOrIds []string, options PodPauseOptions) ([]*PodPauseReport, error) + PodPs(ctx context.Context, options PodPSOptions) ([]*ListPodsReport, error) PodRestart(ctx context.Context, namesOrIds []string, options PodRestartOptions) ([]*PodRestartReport, error) + PodRm(ctx context.Context, namesOrIds []string, options PodRmOptions) ([]*PodRmReport, error) PodStart(ctx context.Context, namesOrIds []string, options PodStartOptions) ([]*PodStartReport, error) PodStop(ctx context.Context, namesOrIds []string, options PodStopOptions) ([]*PodStopReport, error) - PodRm(ctx context.Context, namesOrIds []string, options PodRmOptions) ([]*PodRmReport, error) - PodUnpause(ctx context.Context, namesOrIds []string, options PodunpauseOptions) ([]*PodUnpauseReport, error) PodTop(ctx context.Context, options PodTopOptions) (*StringSliceReport, error) - + PodUnpause(ctx context.Context, namesOrIds []string, options PodunpauseOptions) ([]*PodUnpauseReport, error) VolumeCreate(ctx context.Context, opts VolumeCreateOptions) (*IdOrNameResponse, 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) + VolumePrune(ctx context.Context, opts VolumePruneOptions) ([]*VolumePruneReport, error) + VolumeRm(ctx context.Context, namesOrIds []string, opts VolumeRmOptions) ([]*VolumeRmReport, error) } diff --git a/pkg/domain/entities/engine_image.go b/pkg/domain/entities/engine_image.go index d0c860a04..ac856c05f 100644 --- a/pkg/domain/entities/engine_image.go +++ b/pkg/domain/entities/engine_image.go @@ -8,6 +8,12 @@ type ImageEngine interface { 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) + Inspect(ctx context.Context, names []string, opts InspectOptions) (*ImageInspectReport, error) List(ctx context.Context, opts ImageListOptions) ([]*ImageSummary, error) Prune(ctx context.Context, opts ImagePruneOptions) (*ImagePruneReport, error) + Pull(ctx context.Context, rawImage string, opts ImagePullOptions) (*ImagePullReport, error) + Tag(ctx context.Context, nameOrId string, tags []string, options ImageTagOptions) error + Untag(ctx context.Context, nameOrId string, tags []string, options ImageUntagOptions) error + Load(ctx context.Context, opts ImageLoadOptions) (*ImageLoadReport, error) + Import(ctx context.Context, opts ImageImportOptions) (*ImageImportReport, error) } diff --git a/pkg/domain/entities/healthcheck.go b/pkg/domain/entities/healthcheck.go new file mode 100644 index 000000000..a880805f9 --- /dev/null +++ b/pkg/domain/entities/healthcheck.go @@ -0,0 +1,3 @@ +package entities + +type HealthCheckOptions struct{} diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go index 20af0356f..d136f42fd 100644 --- a/pkg/domain/entities/images.go +++ b/pkg/domain/entities/images.go @@ -4,6 +4,8 @@ import ( "net/url" "github.com/containers/image/v5/manifest" + "github.com/containers/image/v5/types" + "github.com/containers/libpod/pkg/inspect" docker "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/opencontainers/go-digest" @@ -11,7 +13,6 @@ import ( ) type Image struct { - IdOrNamed ID string `json:"Id"` RepoTags []string `json:",omitempty"` RepoDigests []string `json:",omitempty"` @@ -110,11 +111,37 @@ type ImageHistoryReport struct { Layers []ImageHistoryLayer } -type ImageInspectOptions struct { - TypeObject string `json:",omitempty"` - Format string `json:",omitempty"` - Size bool `json:",omitempty"` - Latest bool `json:",omitempty"` +// ImagePullOptions are the arguments for pulling images. +type ImagePullOptions struct { + // AllTags can be specified to pull all tags of the spiecifed image. Note + // that this only works if the specified image does not include a tag. + AllTags bool + // Authfile is the path to the authentication file. Ignored for remote + // calls. + Authfile string + // CertDir is the path to certificate directories. Ignored for remote + // calls. + CertDir string + // Credentials for authenticating against the registry in the format + // USERNAME:PASSWORD. + Credentials string + // OverrideArch will overwrite the local architecture for image pulls. + OverrideArch string + // OverrideOS will overwrite the local operating system (OS) for image + // pulls. + OverrideOS string + // Quiet can be specified to suppress pull progress when pulling. Ignored + // for remote calls. + Quiet bool + // SignaturePolicy to use when pulling. Ignored for remote calls. + SignaturePolicy string + // TLSVerify to enable/disable HTTPS and certificate verification. + TLSVerify types.OptionalBool +} + +// ImagePullReport is the response from pulling one or more images. +type ImagePullReport struct { + Images []string } type ImageListOptions struct { @@ -123,10 +150,6 @@ type ImageListOptions struct { Filters url.Values `json:"filters" schema:"filters"` } -// type ImageListReport struct { -// Images []ImageSummary -// } - type ImagePruneOptions struct { All bool `json:"all" schema:"all"` Filter []string `json:"filter" schema:"filter"` @@ -137,3 +160,40 @@ type ImagePruneReport struct { Report Report Size int64 } + +type ImageTagOptions struct{} +type ImageUntagOptions struct{} + +type ImageData struct { + *inspect.ImageData +} + +type ImageInspectReport struct { + Images []*ImageData + Errors map[string]error +} + +type ImageLoadOptions struct { + Name string + Tag string + Input string + Quiet bool + SignaturePolicy string +} + +type ImageLoadReport struct { + Name string +} + +type ImageImportOptions struct { + Changes []string + Message string + Quiet bool + Reference string + Source string + SourceIsURL bool +} + +type ImageImportReport struct { + Id string +} diff --git a/pkg/domain/entities/pods.go b/pkg/domain/entities/pods.go index d92d1bc7a..a0b2c6cec 100644 --- a/pkg/domain/entities/pods.go +++ b/pkg/domain/entities/pods.go @@ -22,6 +22,7 @@ type ListPodsReport struct { Containers []*ListPodContainer Created time.Time Id string + InfraId string Name string Namespace string Status string @@ -151,3 +152,15 @@ type PodTopOptions struct { Descriptors []string NameOrID string } + +type PodPSOptions struct { + CtrNames bool + CtrIds bool + CtrStatus bool + Filters map[string][]string + Format string + Latest bool + Namespace bool + Quiet bool + Sort string +} diff --git a/pkg/domain/entities/types.go b/pkg/domain/entities/types.go index a1a729584..dd7aaa07f 100644 --- a/pkg/domain/entities/types.go +++ b/pkg/domain/entities/types.go @@ -42,3 +42,10 @@ type NetOptions struct { StaticIP *net.IP StaticMAC *net.HardwareAddr } + +// All CLI inspect commands and inspect sub-commands use the same options +type InspectOptions struct { + Format string `json:",omitempty"` + Latest bool `json:",omitempty"` + Size bool `json:",omitempty"` +} diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index d25af24c5..d4c5ac311 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -243,7 +243,7 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string, return reports, nil } -func (ic *ContainerEngine) ContainerInspect(ctx context.Context, namesOrIds []string, options entities.ContainerInspectOptions) ([]*entities.ContainerInspectReport, error) { +func (ic *ContainerEngine) ContainerInspect(ctx context.Context, namesOrIds []string, options entities.InspectOptions) ([]*entities.ContainerInspectReport, error) { var reports []*entities.ContainerInspectReport ctrs, err := shortcuts.GetContainersByContext(false, options.Latest, namesOrIds, ic.Libpod) if err != nil { @@ -325,3 +325,11 @@ func (ic *ContainerEngine) ContainerCommit(ctx context.Context, nameOrId string, } return &entities.CommitReport{Id: newImage.ID()}, nil } + +func (ic *ContainerEngine) ContainerExport(ctx context.Context, nameOrId string, options entities.ContainerExportOptions) error { + ctr, err := ic.Libpod.LookupContainer(nameOrId) + if err != nil { + return err + } + return ctr.Export(options.Output) +} diff --git a/pkg/domain/infra/abi/healthcheck.go b/pkg/domain/infra/abi/healthcheck.go new file mode 100644 index 000000000..699483243 --- /dev/null +++ b/pkg/domain/infra/abi/healthcheck.go @@ -0,0 +1,26 @@ +// +build ABISupport + +package abi + +import ( + "context" + + "github.com/containers/libpod/libpod" + "github.com/containers/libpod/libpod/define" + "github.com/containers/libpod/pkg/domain/entities" +) + +func (ic *ContainerEngine) HealthCheckRun(ctx context.Context, nameOrId string, options entities.HealthCheckOptions) (*define.HealthCheckResults, error) { + status, err := ic.Libpod.HealthCheck(nameOrId) + if err != nil { + return nil, err + } + hcStatus := "unhealthy" + if status == libpod.HealthCheckSuccess { + hcStatus = "healthy" + } + report := define.HealthCheckResults{ + Status: hcStatus, + } + return &report, nil +} diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go index 44420c1e1..f8c63730c 100644 --- a/pkg/domain/infra/abi/images.go +++ b/pkg/domain/infra/abi/images.go @@ -5,11 +5,23 @@ package abi import ( "context" "fmt" + "io" + "os" + "strings" + "github.com/containers/image/v5/docker" + dockerarchive "github.com/containers/image/v5/docker/archive" + "github.com/containers/image/v5/docker/reference" + "github.com/containers/image/v5/transports/alltransports" + "github.com/containers/image/v5/types" + "github.com/containers/libpod/libpod/image" libpodImage "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/pkg/domain/entities" + domainUtils "github.com/containers/libpod/pkg/domain/utils" + "github.com/containers/libpod/pkg/util" "github.com/containers/storage" "github.com/pkg/errors" + "github.com/sirupsen/logrus" ) func (ir *ImageEngine) Exists(_ context.Context, nameOrId string) (*entities.BoolReport, error) { @@ -134,6 +146,120 @@ func ToDomainHistoryLayer(layer *libpodImage.History) entities.ImageHistoryLayer return l } +func (ir *ImageEngine) Pull(ctx context.Context, rawImage string, options entities.ImagePullOptions) (*entities.ImagePullReport, error) { + var writer io.Writer + if !options.Quiet { + writer = os.Stderr + } + + dockerPrefix := fmt.Sprintf("%s://", docker.Transport.Name()) + imageRef, err := alltransports.ParseImageName(rawImage) + if err != nil { + imageRef, err = alltransports.ParseImageName(fmt.Sprintf("%s%s", dockerPrefix, rawImage)) + if err != nil { + return nil, errors.Errorf("invalid image reference %q", rawImage) + } + } + + // Special-case for docker-archive which allows multiple tags. + if imageRef.Transport().Name() == dockerarchive.Transport.Name() { + newImage, err := ir.Libpod.ImageRuntime().LoadFromArchiveReference(ctx, imageRef, options.SignaturePolicy, writer) + if err != nil { + return nil, errors.Wrapf(err, "error pulling image %q", rawImage) + } + return &entities.ImagePullReport{Images: []string{newImage[0].ID()}}, nil + } + + var registryCreds *types.DockerAuthConfig + if options.Credentials != "" { + creds, err := util.ParseRegistryCreds(options.Credentials) + if err != nil { + return nil, err + } + registryCreds = creds + } + dockerRegistryOptions := image.DockerRegistryOptions{ + DockerRegistryCreds: registryCreds, + DockerCertPath: options.CertDir, + OSChoice: options.OverrideOS, + ArchitectureChoice: options.OverrideArch, + DockerInsecureSkipTLSVerify: options.TLSVerify, + } + + if !options.AllTags { + newImage, err := ir.Libpod.ImageRuntime().New(ctx, rawImage, options.SignaturePolicy, options.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, util.PullImageAlways) + if err != nil { + return nil, errors.Wrapf(err, "error pulling image %q", rawImage) + } + return &entities.ImagePullReport{Images: []string{newImage.ID()}}, nil + } + + // --all-tags requires the docker transport + if imageRef.Transport().Name() != docker.Transport.Name() { + return nil, errors.New("--all-tags requires docker transport") + } + + // Trim the docker-transport prefix. + rawImage = strings.TrimPrefix(rawImage, docker.Transport.Name()) + + // all-tags doesn't work with a tagged reference, so let's check early + namedRef, err := reference.Parse(rawImage) + if err != nil { + return nil, errors.Wrapf(err, "error parsing %q", rawImage) + } + if _, isTagged := namedRef.(reference.Tagged); isTagged { + return nil, errors.New("--all-tags requires a reference without a tag") + + } + + systemContext := image.GetSystemContext("", options.Authfile, false) + tags, err := docker.GetRepositoryTags(ctx, systemContext, imageRef) + if err != nil { + return nil, errors.Wrapf(err, "error getting repository tags") + } + + var foundIDs []string + for _, tag := range tags { + name := rawImage + ":" + tag + newImage, err := ir.Libpod.ImageRuntime().New(ctx, name, options.SignaturePolicy, options.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, util.PullImageAlways) + if err != nil { + logrus.Errorf("error pulling image %q", name) + continue + } + foundIDs = append(foundIDs, newImage.ID()) + } + + if len(tags) != len(foundIDs) { + return nil, errors.Errorf("error pulling image %q", rawImage) + } + return &entities.ImagePullReport{Images: foundIDs}, nil +} + +func (ir *ImageEngine) Inspect(ctx context.Context, names []string, opts entities.InspectOptions) (*entities.ImageInspectReport, error) { + report := entities.ImageInspectReport{ + Errors: make(map[string]error), + } + + for _, id := range names { + img, err := ir.Libpod.ImageRuntime().NewFromLocal(id) + if err != nil { + report.Errors[id] = err + continue + } + + results, err := img.Inspect(ctx) + if err != nil { + report.Errors[id] = err + continue + } + + cookedResults := entities.ImageData{} + _ = domainUtils.DeepCopy(&cookedResults, results) + report.Images = append(report.Images, &cookedResults) + } + return &report, nil +} + // func (r *imageRuntime) Delete(ctx context.Context, nameOrId string, opts entities.ImageDeleteOptions) (*entities.ImageDeleteReport, error) { // image, err := r.libpod.ImageEngine().NewFromLocal(nameOrId) // if err != nil { @@ -146,7 +272,7 @@ func ToDomainHistoryLayer(layer *libpodImage.History) entities.ImageHistoryLayer // } // // report := entities.ImageDeleteReport{} -// if err := utils.DeepCopy(&report, results); err != nil { +// if err := domainUtils.DeepCopy(&report, results); err != nil { // return nil, err // } // return &report, nil @@ -164,3 +290,58 @@ func ToDomainHistoryLayer(layer *libpodImage.History) entities.ImageHistoryLayer // copy(report.Report.Id, id) // return &report, nil // } + +func (ir *ImageEngine) Tag(ctx context.Context, nameOrId string, tags []string, options entities.ImageTagOptions) error { + newImage, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrId) + if err != nil { + return err + } + for _, tag := range tags { + if err := newImage.TagImage(tag); err != nil { + return err + } + } + return nil +} + +func (ir *ImageEngine) Untag(ctx context.Context, nameOrId string, tags []string, options entities.ImageUntagOptions) error { + newImage, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrId) + if err != nil { + return err + } + for _, tag := range tags { + if err := newImage.UntagImage(tag); err != nil { + return err + } + } + return nil +} + +func (ir *ImageEngine) Load(ctx context.Context, opts entities.ImageLoadOptions) (*entities.ImageLoadReport, error) { + var ( + writer io.Writer + ) + if !opts.Quiet { + writer = os.Stderr + } + name, err := ir.Libpod.LoadImage(ctx, opts.Name, opts.Input, writer, opts.SignaturePolicy) + if err != nil { + return nil, err + } + newImage, err := ir.Libpod.ImageRuntime().NewFromLocal(name) + if err != nil { + return nil, errors.Wrap(err, "image loaded but no additional tags were created") + } + if err := newImage.TagImage(opts.Name); err != nil { + return nil, errors.Wrapf(err, "error adding %q to image %q", opts.Name, newImage.InputName) + } + return &entities.ImageLoadReport{Name: name}, nil +} + +func (ir *ImageEngine) Import(ctx context.Context, opts entities.ImageImportOptions) (*entities.ImageImportReport, error) { + id, err := ir.Libpod.Import(ctx, opts.Source, opts.Reference, opts.Changes, opts.Message, opts.Quiet) + if err != nil { + return nil, err + } + return &entities.ImageImportReport{Id: id}, nil +} diff --git a/pkg/domain/infra/abi/pods.go b/pkg/domain/infra/abi/pods.go index 8abcc6e4b..494a048ec 100644 --- a/pkg/domain/infra/abi/pods.go +++ b/pkg/domain/infra/abi/pods.go @@ -7,6 +7,7 @@ import ( "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/define" + "github.com/containers/libpod/libpod/podfilters" "github.com/containers/libpod/pkg/domain/entities" "github.com/containers/libpod/pkg/signal" "github.com/containers/libpod/pkg/specgen" @@ -272,3 +273,61 @@ func (ic *ContainerEngine) PodTop(ctx context.Context, options entities.PodTopOp report.Value, err = pod.GetPodPidInformation(options.Descriptors) return report, err } + +func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOptions) ([]*entities.ListPodsReport, error) { + var ( + filters []libpod.PodFilter + reports []*entities.ListPodsReport + ) + for k, v := range options.Filters { + for _, filter := range v { + f, err := podfilters.GeneratePodFilterFunc(k, filter) + if err != nil { + return nil, err + } + filters = append(filters, f) + + } + } + pds, err := ic.Libpod.Pods(filters...) + if err != nil { + return nil, err + } + for _, p := range pds { + var lpcs []*entities.ListPodContainer + status, err := p.GetPodStatus() + if err != nil { + return nil, err + } + cons, err := p.AllContainers() + if err != nil { + return nil, err + } + for _, c := range cons { + state, err := c.State() + if err != nil { + return nil, err + } + lpcs = append(lpcs, &entities.ListPodContainer{ + Id: c.ID(), + Names: c.Name(), + Status: state.String(), + }) + } + infraId, err := p.InfraContainerID() + if err != nil { + return nil, err + } + reports = append(reports, &entities.ListPodsReport{ + Cgroup: p.CgroupParent(), + Containers: lpcs, + Created: p.CreatedTime(), + Id: p.ID(), + InfraId: infraId, + Name: p.Name(), + Namespace: p.Namespace(), + Status: status, + }) + } + return reports, nil +} diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index 3c8be90dc..8885ae7c7 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -2,6 +2,8 @@ package tunnel import ( "context" + "io" + "os" "github.com/containers/image/v5/docker/reference" @@ -142,7 +144,7 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string, return reports, nil } -func (ic *ContainerEngine) ContainerInspect(ctx context.Context, namesOrIds []string, options entities.ContainerInspectOptions) ([]*entities.ContainerInspectReport, error) { +func (ic *ContainerEngine) ContainerInspect(ctx context.Context, namesOrIds []string, options entities.InspectOptions) ([]*entities.ContainerInspectReport, error) { var ( reports []*entities.ContainerInspectReport ) @@ -210,3 +212,17 @@ func (ic *ContainerEngine) ContainerCommit(ctx context.Context, nameOrId string, } return &entities.CommitReport{Id: response.ID}, nil } + +func (ic *ContainerEngine) ContainerExport(ctx context.Context, nameOrId string, options entities.ContainerExportOptions) error { + var ( + err error + w io.Writer + ) + if len(options.Output) > 0 { + w, err = os.Create(options.Output) + if err != nil { + return err + } + } + return containers.Export(ic.ClientCxt, nameOrId, w) +} diff --git a/pkg/domain/infra/tunnel/healthcheck.go b/pkg/domain/infra/tunnel/healthcheck.go new file mode 100644 index 000000000..e589489b3 --- /dev/null +++ b/pkg/domain/infra/tunnel/healthcheck.go @@ -0,0 +1,13 @@ +package tunnel + +import ( + "context" + + "github.com/containers/libpod/libpod/define" + "github.com/containers/libpod/pkg/bindings/containers" + "github.com/containers/libpod/pkg/domain/entities" +) + +func (ic *ContainerEngine) HealthCheckRun(ctx context.Context, nameOrId string, options entities.HealthCheckOptions) (*define.HealthCheckResults, error) { + return containers.RunHealthCheck(ic.ClientCxt, nameOrId) +} diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go index 6a3adc9ee..155f5e4bd 100644 --- a/pkg/domain/infra/tunnel/images.go +++ b/pkg/domain/infra/tunnel/images.go @@ -2,10 +2,13 @@ package tunnel import ( "context" + "os" + "github.com/containers/image/v5/docker/reference" images "github.com/containers/libpod/pkg/bindings/images" "github.com/containers/libpod/pkg/domain/entities" "github.com/containers/libpod/pkg/domain/utils" + "github.com/pkg/errors" ) func (ir *ImageEngine) Exists(_ context.Context, nameOrId string) (*entities.BoolReport, error) { @@ -85,3 +88,99 @@ func (ir *ImageEngine) Prune(ctx context.Context, opts entities.ImagePruneOption } return &report, nil } + +func (ir *ImageEngine) Pull(ctx context.Context, rawImage string, options entities.ImagePullOptions) (*entities.ImagePullReport, error) { + pulledImages, err := images.Pull(ir.ClientCxt, rawImage, options) + if err != nil { + return nil, err + } + return &entities.ImagePullReport{Images: pulledImages}, nil +} + +func (ir *ImageEngine) Tag(ctx context.Context, nameOrId string, tags []string, options entities.ImageTagOptions) error { + for _, newTag := range tags { + var ( + tag, repo string + ) + ref, err := reference.Parse(newTag) + if err != nil { + return err + } + if t, ok := ref.(reference.Tagged); ok { + tag = t.Tag() + } + if r, ok := ref.(reference.Named); ok { + repo = r.Name() + } + if len(repo) < 1 { + return errors.Errorf("invalid image name %q", nameOrId) + } + if err := images.Tag(ir.ClientCxt, nameOrId, tag, repo); err != nil { + return err + } + } + return nil +} + +func (ir *ImageEngine) Untag(ctx context.Context, nameOrId string, tags []string, options entities.ImageUntagOptions) error { + for _, newTag := range tags { + var ( + tag, repo string + ) + ref, err := reference.Parse(newTag) + if err != nil { + return err + } + if t, ok := ref.(reference.Tagged); ok { + tag = t.Tag() + } + if r, ok := ref.(reference.Named); ok { + repo = r.Name() + } + if len(repo) < 1 { + return errors.Errorf("invalid image name %q", nameOrId) + } + if err := images.Untag(ir.ClientCxt, nameOrId, tag, repo); err != nil { + return err + } + } + return nil +} + +func (ir *ImageEngine) Inspect(_ context.Context, names []string, opts entities.InspectOptions) (*entities.ImageInspectReport, error) { + report := entities.ImageInspectReport{} + for _, id := range names { + r, err := images.GetImage(ir.ClientCxt, id, &opts.Size) + if err != nil { + report.Errors[id] = err + } + report.Images = append(report.Images, r) + } + return &report, nil +} + +func (ir *ImageEngine) Load(ctx context.Context, opts entities.ImageLoadOptions) (*entities.ImageLoadReport, error) { + f, err := os.Open(opts.Input) + if err != nil { + return nil, err + } + defer f.Close() + return images.Load(ir.ClientCxt, f, &opts.Name) +} + +func (ir *ImageEngine) Import(ctx context.Context, opts entities.ImageImportOptions) (*entities.ImageImportReport, error) { + var ( + err error + sourceURL *string + f *os.File + ) + if opts.SourceIsURL { + sourceURL = &opts.Source + } else { + f, err = os.Open(opts.Source) + if err != nil { + return nil, err + } + } + return images.Import(ir.ClientCxt, opts.Changes, &opts.Message, &opts.Reference, sourceURL, f) +} diff --git a/pkg/domain/infra/tunnel/pods.go b/pkg/domain/infra/tunnel/pods.go index 9561a9807..ad87a0a29 100644 --- a/pkg/domain/infra/tunnel/pods.go +++ b/pkg/domain/infra/tunnel/pods.go @@ -193,3 +193,7 @@ func (ic *ContainerEngine) PodTop(ctx context.Context, options entities.PodTopOp } return &entities.StringSliceReport{Value: topOutput}, nil } + +func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOptions) ([]*entities.ListPodsReport, error) { + return pods.List(ic.ClientCxt, options.Filters) +} |