diff options
Diffstat (limited to 'pkg/domain/infra/tunnel')
-rw-r--r-- | pkg/domain/infra/tunnel/containers.go | 179 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/healthcheck.go | 13 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/helpers.go | 34 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/images.go | 201 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/pods.go | 196 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/system.go | 1 |
6 files changed, 605 insertions, 19 deletions
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index a8ecff41b..4101068ba 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -2,9 +2,16 @@ package tunnel import ( "context" + "io" + "os" + "github.com/containers/image/v5/docker/reference" + "github.com/containers/libpod/libpod/define" + "github.com/containers/libpod/pkg/api/handlers/libpod" "github.com/containers/libpod/pkg/bindings/containers" "github.com/containers/libpod/pkg/domain/entities" + "github.com/containers/libpod/pkg/specgen" + "github.com/pkg/errors" ) func (ic *ContainerEngine) ContainerExists(ctx context.Context, nameOrId string) (*entities.BoolReport, error) { @@ -138,3 +145,175 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string, } return reports, nil } + +func (ic *ContainerEngine) ContainerInspect(ctx context.Context, namesOrIds []string, options entities.InspectOptions) ([]*entities.ContainerInspectReport, error) { + var ( + reports []*entities.ContainerInspectReport + ) + ctrs, err := getContainersByContext(ic.ClientCxt, false, namesOrIds) + if err != nil { + return nil, err + } + for _, con := range ctrs { + data, err := containers.Inspect(ic.ClientCxt, con.ID, &options.Size) + if err != nil { + return nil, err + } + reports = append(reports, &entities.ContainerInspectReport{InspectContainerData: data}) + } + return reports, nil +} + +func (ic *ContainerEngine) ContainerTop(ctx context.Context, options entities.TopOptions) (*entities.StringSliceReport, error) { + switch { + case options.Latest: + return nil, errors.New("latest is not supported") + case options.NameOrID == "": + return nil, errors.New("NameOrID must be specified") + } + + topOutput, err := containers.Top(ic.ClientCxt, options.NameOrID, options.Descriptors) + if err != nil { + return nil, err + } + return &entities.StringSliceReport{Value: topOutput}, nil +} + +func (ic *ContainerEngine) ContainerCommit(ctx context.Context, nameOrId string, options entities.CommitOptions) (*entities.CommitReport, error) { + var ( + repo string + tag string = "latest" + ) + if len(options.ImageName) > 0 { + ref, err := reference.Parse(options.ImageName) + if err != nil { + return nil, 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 nil, errors.Errorf("invalid image name %q", options.ImageName) + } + } + commitOpts := containers.CommitOptions{ + Author: &options.Author, + Changes: options.Changes, + Comment: &options.Message, + Format: &options.Format, + Pause: &options.Pause, + Repo: &repo, + Tag: &tag, + } + response, err := containers.Commit(ic.ClientCxt, nameOrId, commitOpts) + if err != nil { + return nil, err + } + 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) +} + +func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds []string, options entities.CheckpointOptions) ([]*entities.CheckpointReport, error) { + var ( + reports []*entities.CheckpointReport + err error + ctrs []libpod.ListContainer + ) + + if options.All { + allCtrs, err := getContainersByContext(ic.ClientCxt, true, []string{}) + if err != nil { + return nil, err + } + // narrow the list to running only + for _, c := range allCtrs { + if c.State == define.ContainerStateRunning.String() { + ctrs = append(ctrs, c) + } + } + + } else { + ctrs, err = getContainersByContext(ic.ClientCxt, false, namesOrIds) + if err != nil { + return nil, err + } + } + for _, c := range ctrs { + report, err := containers.Checkpoint(ic.ClientCxt, c.ID, &options.Keep, &options.LeaveRuninng, &options.TCPEstablished, &options.IgnoreRootFS, &options.Export) + if err != nil { + reports = append(reports, &entities.CheckpointReport{Id: c.ID, Err: err}) + } + reports = append(reports, report) + } + return reports, nil +} + +func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []string, options entities.RestoreOptions) ([]*entities.RestoreReport, error) { + var ( + reports []*entities.RestoreReport + err error + ctrs []libpod.ListContainer + ) + if options.All { + allCtrs, err := getContainersByContext(ic.ClientCxt, true, []string{}) + if err != nil { + return nil, err + } + // narrow the list to exited only + for _, c := range allCtrs { + if c.State == define.ContainerStateExited.String() { + ctrs = append(ctrs, c) + } + } + + } else { + ctrs, err = getContainersByContext(ic.ClientCxt, false, namesOrIds) + if err != nil { + return nil, err + } + } + for _, c := range ctrs { + report, err := containers.Restore(ic.ClientCxt, c.ID, &options.Keep, &options.TCPEstablished, &options.IgnoreRootFS, &options.IgnoreStaticIP, &options.IgnoreStaticMAC, &options.Name, &options.Import) + if err != nil { + reports = append(reports, &entities.RestoreReport{Id: c.ID, Err: err}) + } + reports = append(reports, report) + } + return reports, nil +} + +func (ic *ContainerEngine) ContainerCreate(ctx context.Context, s *specgen.SpecGenerator) (*entities.ContainerCreateReport, error) { + response, err := containers.CreateWithSpec(ic.ClientCxt, s) + if err != nil { + return nil, err + } + return &entities.ContainerCreateReport{Id: response.ID}, nil +} + +func (ic *ContainerEngine) ContainerAttach(ctx context.Context, nameOrId string, options entities.AttachOptions) error { + return errors.New("not implemented") +} + +func (ic *ContainerEngine) ContainerExec(ctx context.Context, nameOrId string, options entities.ExecOptions) (int, error) { + return 125, errors.New("not implemented") +} + +func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []string, options entities.ContainerStartOptions) ([]*entities.ContainerStartReport, error) { + return nil, errors.New("not implemented") +} 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/helpers.go b/pkg/domain/infra/tunnel/helpers.go index 11fca5278..f9183c955 100644 --- a/pkg/domain/infra/tunnel/helpers.go +++ b/pkg/domain/infra/tunnel/helpers.go @@ -4,9 +4,12 @@ import ( "context" "strings" + "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/api/handlers/libpod" "github.com/containers/libpod/pkg/bindings" "github.com/containers/libpod/pkg/bindings/containers" + "github.com/containers/libpod/pkg/bindings/pods" + "github.com/containers/libpod/pkg/domain/entities" "github.com/containers/libpod/pkg/util" "github.com/pkg/errors" ) @@ -40,3 +43,34 @@ func getContainersByContext(contextWithConnection context.Context, all bool, nam } return cons, nil } + +func getPodsByContext(contextWithConnection context.Context, all bool, namesOrIds []string) ([]*entities.ListPodsReport, error) { + var ( + sPods []*entities.ListPodsReport + ) + if all && len(namesOrIds) > 0 { + return nil, errors.New("cannot lookup specific pods and all") + } + + fPods, err := pods.List(contextWithConnection, nil) + if err != nil { + return nil, err + } + if all { + return fPods, nil + } + for _, nameOrId := range namesOrIds { + var found bool + for _, f := range fPods { + if f.Name == nameOrId || strings.HasPrefix(f.Id, nameOrId) { + sPods = append(sPods, f) + found = true + break + } + } + if !found { + return nil, errors.Wrapf(define.ErrNoSuchPod, "unable to find pod %q", nameOrId) + } + } + return sPods, nil +} diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go index 60df40498..516914a68 100644 --- a/pkg/domain/infra/tunnel/images.go +++ b/pkg/domain/infra/tunnel/images.go @@ -2,34 +2,41 @@ package tunnel import ( "context" - "net/url" + "io/ioutil" + "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" + utils2 "github.com/containers/libpod/utils" + "github.com/pkg/errors" ) -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.ImageSummary, error) { @@ -69,12 +76,168 @@ func (ir *ImageEngine) History(ctx context.Context, nameOrId string, opts entiti } func (ir *ImageEngine) Prune(ctx context.Context, opts entities.ImagePruneOptions) (*entities.ImagePruneReport, error) { - results, err := images.Prune(ir.ClientCxt, url.Values{}) + results, err := images.Prune(ir.ClientCxt, &opts.All, opts.Filters) + if err != nil { + return nil, err + } + + report := entities.ImagePruneReport{ + Report: entities.Report{ + Id: results, + Err: nil, + }, + Size: 0, + } + 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 +} - report := entities.ImagePruneReport{} - copy(report.Report.Id, results) +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) +} + +func (ir *ImageEngine) Push(ctx context.Context, source string, destination string, options entities.ImagePushOptions) error { + return images.Push(ir.ClientCxt, source, destination, options) +} + +func (ir *ImageEngine) Save(ctx context.Context, nameOrId string, tags []string, options entities.ImageSaveOptions) error { + var ( + f *os.File + err error + ) + + switch options.Format { + case "oci-dir", "docker-dir": + f, err = ioutil.TempFile("", "podman_save") + if err == nil { + defer func() { _ = os.Remove(f.Name()) }() + } + default: + f, err = os.Create(options.Output) + } + if err != nil { + return err + } + + exErr := images.Export(ir.ClientCxt, nameOrId, f, &options.Format, &options.Compress) + if err := f.Close(); err != nil { + return err + } + if exErr != nil { + return exErr + } + + if options.Format != "oci-dir" && options.Format != "docker-dir" { + return nil + } + + f, err = os.Open(f.Name()) + if err != nil { + return err + } + info, err := os.Stat(options.Output) + switch { + case err == nil: + if info.Mode().IsRegular() { + return errors.Errorf("%q already exists as a regular file", options.Output) + } + case os.IsNotExist(err): + if err := os.Mkdir(options.Output, 0755); err != nil { + return err + } + default: + return err + } + return utils2.UntarToFileSystem(options.Output, f, nil) +} diff --git a/pkg/domain/infra/tunnel/pods.go b/pkg/domain/infra/tunnel/pods.go index 500069d51..dad77284f 100644 --- a/pkg/domain/infra/tunnel/pods.go +++ b/pkg/domain/infra/tunnel/pods.go @@ -5,9 +5,205 @@ import ( "github.com/containers/libpod/pkg/bindings/pods" "github.com/containers/libpod/pkg/domain/entities" + "github.com/containers/libpod/pkg/specgen" + "github.com/pkg/errors" ) func (ic *ContainerEngine) PodExists(ctx context.Context, nameOrId string) (*entities.BoolReport, error) { exists, err := pods.Exists(ic.ClientCxt, nameOrId) return &entities.BoolReport{Value: exists}, err } + +func (ic *ContainerEngine) PodKill(ctx context.Context, namesOrIds []string, options entities.PodKillOptions) ([]*entities.PodKillReport, error) { + var ( + reports []*entities.PodKillReport + ) + foundPods, err := getPodsByContext(ic.ClientCxt, options.All, namesOrIds) + if err != nil { + return nil, err + } + for _, p := range foundPods { + response, err := pods.Kill(ic.ClientCxt, p.Id, &options.Signal) + if err != nil { + report := entities.PodKillReport{ + Errs: []error{err}, + Id: p.Id, + } + reports = append(reports, &report) + continue + } + reports = append(reports, response) + } + return reports, nil +} + +func (ic *ContainerEngine) PodPause(ctx context.Context, namesOrIds []string, options entities.PodPauseOptions) ([]*entities.PodPauseReport, error) { + var ( + reports []*entities.PodPauseReport + ) + foundPods, err := getPodsByContext(ic.ClientCxt, options.All, namesOrIds) + if err != nil { + return nil, err + } + for _, p := range foundPods { + response, err := pods.Pause(ic.ClientCxt, p.Id) + if err != nil { + report := entities.PodPauseReport{ + Errs: []error{err}, + Id: p.Id, + } + reports = append(reports, &report) + continue + } + reports = append(reports, response) + } + return reports, nil +} + +func (ic *ContainerEngine) PodUnpause(ctx context.Context, namesOrIds []string, options entities.PodunpauseOptions) ([]*entities.PodUnpauseReport, error) { + var ( + reports []*entities.PodUnpauseReport + ) + foundPods, err := getPodsByContext(ic.ClientCxt, options.All, namesOrIds) + if err != nil { + return nil, err + } + for _, p := range foundPods { + response, err := pods.Unpause(ic.ClientCxt, p.Id) + if err != nil { + report := entities.PodUnpauseReport{ + Errs: []error{err}, + Id: p.Id, + } + reports = append(reports, &report) + continue + } + reports = append(reports, response) + } + return reports, nil +} + +func (ic *ContainerEngine) PodStop(ctx context.Context, namesOrIds []string, options entities.PodStopOptions) ([]*entities.PodStopReport, error) { + var ( + reports []*entities.PodStopReport + timeout int = -1 + ) + foundPods, err := getPodsByContext(ic.ClientCxt, options.All, namesOrIds) + if err != nil { + return nil, err + } + if options.Timeout != -1 { + timeout = options.Timeout + } + for _, p := range foundPods { + response, err := pods.Stop(ic.ClientCxt, p.Id, &timeout) + if err != nil { + report := entities.PodStopReport{ + Errs: []error{err}, + Id: p.Id, + } + reports = append(reports, &report) + continue + } + reports = append(reports, response) + } + return reports, nil +} + +func (ic *ContainerEngine) PodRestart(ctx context.Context, namesOrIds []string, options entities.PodRestartOptions) ([]*entities.PodRestartReport, error) { + var reports []*entities.PodRestartReport + foundPods, err := getPodsByContext(ic.ClientCxt, options.All, namesOrIds) + if err != nil { + return nil, err + } + for _, p := range foundPods { + response, err := pods.Restart(ic.ClientCxt, p.Id) + if err != nil { + report := entities.PodRestartReport{ + Errs: []error{err}, + Id: p.Id, + } + reports = append(reports, &report) + continue + } + reports = append(reports, response) + } + return reports, nil +} + +func (ic *ContainerEngine) PodStart(ctx context.Context, namesOrIds []string, options entities.PodStartOptions) ([]*entities.PodStartReport, error) { + var reports []*entities.PodStartReport + foundPods, err := getPodsByContext(ic.ClientCxt, options.All, namesOrIds) + if err != nil { + return nil, err + } + for _, p := range foundPods { + response, err := pods.Start(ic.ClientCxt, p.Id) + if err != nil { + report := entities.PodStartReport{ + Errs: []error{err}, + Id: p.Id, + } + reports = append(reports, &report) + continue + } + reports = append(reports, response) + } + return reports, nil +} + +func (ic *ContainerEngine) PodRm(ctx context.Context, namesOrIds []string, options entities.PodRmOptions) ([]*entities.PodRmReport, error) { + var reports []*entities.PodRmReport + foundPods, err := getPodsByContext(ic.ClientCxt, options.All, namesOrIds) + if err != nil { + return nil, err + } + for _, p := range foundPods { + response, err := pods.Remove(ic.ClientCxt, p.Id, &options.Force) + if err != nil { + report := entities.PodRmReport{ + Err: err, + Id: p.Id, + } + reports = append(reports, &report) + continue + } + reports = append(reports, response) + } + return reports, nil +} + +func (ic *ContainerEngine) PodCreate(ctx context.Context, opts entities.PodCreateOptions) (*entities.PodCreateReport, error) { + podSpec := specgen.NewPodSpecGenerator() + opts.ToPodSpecGen(podSpec) + return pods.CreatePodFromSpec(ic.ClientCxt, podSpec) +} + +func (ic *ContainerEngine) PodTop(ctx context.Context, options entities.PodTopOptions) (*entities.StringSliceReport, error) { + switch { + case options.Latest: + return nil, errors.New("latest is not supported") + case options.NameOrID == "": + return nil, errors.New("NameOrID must be specified") + } + + topOutput, err := pods.Top(ic.ClientCxt, options.NameOrID, options.Descriptors) + if err != nil { + return nil, err + } + 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) +} + +func (ic *ContainerEngine) PodInspect(ctx context.Context, options entities.PodInspectOptions) (*entities.PodInspectReport, error) { + switch { + case options.Latest: + return nil, errors.New("latest is not supported") + case options.NameOrID == "": + return nil, errors.New("NameOrID must be specified") + } + return pods.Inspect(ic.ClientCxt, options.NameOrID) +} diff --git a/pkg/domain/infra/tunnel/system.go b/pkg/domain/infra/tunnel/system.go new file mode 100644 index 000000000..5bafef1fe --- /dev/null +++ b/pkg/domain/infra/tunnel/system.go @@ -0,0 +1 @@ +package tunnel |