diff options
Diffstat (limited to 'pkg/varlinkapi')
-rw-r--r-- | pkg/varlinkapi/containers.go | 42 | ||||
-rw-r--r-- | pkg/varlinkapi/images.go | 373 | ||||
-rw-r--r-- | pkg/varlinkapi/pods.go | 56 |
3 files changed, 355 insertions, 116 deletions
diff --git a/pkg/varlinkapi/containers.go b/pkg/varlinkapi/containers.go index 7345a1dd8..ad9f107a7 100644 --- a/pkg/varlinkapi/containers.go +++ b/pkg/varlinkapi/containers.go @@ -47,7 +47,7 @@ func (i *LibpodAPI) ListContainers(call iopodman.VarlinkCall) error { func (i *LibpodAPI) GetContainer(call iopodman.VarlinkCall, id string) error { ctr, err := i.Runtime.LookupContainer(id) if err != nil { - return call.ReplyContainerNotFound(id) + return call.ReplyContainerNotFound(id, err.Error()) } opts := shared.PsOptions{ Namespace: true, @@ -64,7 +64,7 @@ func (i *LibpodAPI) GetContainer(call iopodman.VarlinkCall, id string) error { func (i *LibpodAPI) InspectContainer(call iopodman.VarlinkCall, name string) error { ctr, err := i.Runtime.LookupContainer(name) if err != nil { - return call.ReplyContainerNotFound(name) + return call.ReplyContainerNotFound(name, err.Error()) } inspectInfo, err := ctr.Inspect(true) if err != nil { @@ -90,7 +90,7 @@ func (i *LibpodAPI) InspectContainer(call iopodman.VarlinkCall, name string) err func (i *LibpodAPI) ListContainerProcesses(call iopodman.VarlinkCall, name string, opts []string) error { ctr, err := i.Runtime.LookupContainer(name) if err != nil { - return call.ReplyContainerNotFound(name) + return call.ReplyContainerNotFound(name, err.Error()) } containerState, err := ctr.State() if err != nil { @@ -118,7 +118,7 @@ func (i *LibpodAPI) GetContainerLogs(call iopodman.VarlinkCall, name string) err var logs []string ctr, err := i.Runtime.LookupContainer(name) if err != nil { - return call.ReplyContainerNotFound(name) + return call.ReplyContainerNotFound(name, err.Error()) } logPath := ctr.LogPath() @@ -198,7 +198,7 @@ func (i *LibpodAPI) ListContainerChanges(call iopodman.VarlinkCall, name string) func (i *LibpodAPI) ExportContainer(call iopodman.VarlinkCall, name, outPath string) error { ctr, err := i.Runtime.LookupContainer(name) if err != nil { - return call.ReplyContainerNotFound(name) + return call.ReplyContainerNotFound(name, err.Error()) } outputFile, err := ioutil.TempFile("", "varlink_recv") if err != nil { @@ -220,7 +220,7 @@ func (i *LibpodAPI) ExportContainer(call iopodman.VarlinkCall, name, outPath str func (i *LibpodAPI) GetContainerStats(call iopodman.VarlinkCall, name string) error { ctr, err := i.Runtime.LookupContainer(name) if err != nil { - return call.ReplyContainerNotFound(name) + return call.ReplyContainerNotFound(name, err.Error()) } containerStats, err := ctr.GetContainerStats(&libpod.ContainerStats{}) if err != nil { @@ -251,7 +251,7 @@ func (i *LibpodAPI) GetContainerStats(call iopodman.VarlinkCall, name string) er func (i *LibpodAPI) StartContainer(call iopodman.VarlinkCall, name string) error { ctr, err := i.Runtime.LookupContainer(name) if err != nil { - return call.ReplyContainerNotFound(name) + return call.ReplyContainerNotFound(name, err.Error()) } state, err := ctr.State() if err != nil { @@ -270,7 +270,7 @@ func (i *LibpodAPI) StartContainer(call iopodman.VarlinkCall, name string) error func (i *LibpodAPI) StopContainer(call iopodman.VarlinkCall, name string, timeout int64) error { ctr, err := i.Runtime.LookupContainer(name) if err != nil { - return call.ReplyContainerNotFound(name) + return call.ReplyContainerNotFound(name, err.Error()) } if err := ctr.StopWithTimeout(uint(timeout)); err != nil && err != libpod.ErrCtrStopped { return call.ReplyErrorOccurred(err.Error()) @@ -282,7 +282,7 @@ func (i *LibpodAPI) StopContainer(call iopodman.VarlinkCall, name string, timeou func (i *LibpodAPI) RestartContainer(call iopodman.VarlinkCall, name string, timeout int64) error { ctr, err := i.Runtime.LookupContainer(name) if err != nil { - return call.ReplyContainerNotFound(name) + return call.ReplyContainerNotFound(name, err.Error()) } if err := ctr.RestartWithTimeout(getContext(), uint(timeout)); err != nil { return call.ReplyErrorOccurred(err.Error()) @@ -311,7 +311,7 @@ func (i *LibpodAPI) KillContainer(call iopodman.VarlinkCall, name string, signal } ctr, err := i.Runtime.LookupContainer(name) if err != nil { - return call.ReplyContainerNotFound(name) + return call.ReplyContainerNotFound(name, err.Error()) } if err := ctr.Kill(killSignal); err != nil { return call.ReplyErrorOccurred(err.Error()) @@ -323,7 +323,7 @@ func (i *LibpodAPI) KillContainer(call iopodman.VarlinkCall, name string, signal func (i *LibpodAPI) PauseContainer(call iopodman.VarlinkCall, name string) error { ctr, err := i.Runtime.LookupContainer(name) if err != nil { - return call.ReplyContainerNotFound(name) + return call.ReplyContainerNotFound(name, err.Error()) } if err := ctr.Pause(); err != nil { return call.ReplyErrorOccurred(err.Error()) @@ -335,7 +335,7 @@ func (i *LibpodAPI) PauseContainer(call iopodman.VarlinkCall, name string) error func (i *LibpodAPI) UnpauseContainer(call iopodman.VarlinkCall, name string) error { ctr, err := i.Runtime.LookupContainer(name) if err != nil { - return call.ReplyContainerNotFound(name) + return call.ReplyContainerNotFound(name, err.Error()) } if err := ctr.Unpause(); err != nil { return call.ReplyErrorOccurred(err.Error()) @@ -347,7 +347,7 @@ func (i *LibpodAPI) UnpauseContainer(call iopodman.VarlinkCall, name string) err func (i *LibpodAPI) WaitContainer(call iopodman.VarlinkCall, name string) error { ctr, err := i.Runtime.LookupContainer(name) if err != nil { - return call.ReplyContainerNotFound(name) + return call.ReplyContainerNotFound(name, err.Error()) } exitCode, err := ctr.Wait() if err != nil { @@ -362,7 +362,7 @@ func (i *LibpodAPI) RemoveContainer(call iopodman.VarlinkCall, name string, forc ctx := getContext() ctr, err := i.Runtime.LookupContainer(name) if err != nil { - return call.ReplyContainerNotFound(name) + return call.ReplyContainerNotFound(name, err.Error()) } if err := i.Runtime.RemoveContainer(ctx, ctr, force, removeVolumes); err != nil { return call.ReplyErrorOccurred(err.Error()) @@ -398,7 +398,7 @@ func (i *LibpodAPI) DeleteStoppedContainers(call iopodman.VarlinkCall) error { func (i *LibpodAPI) GetAttachSockets(call iopodman.VarlinkCall, name string) error { ctr, err := i.Runtime.LookupContainer(name) if err != nil { - return call.ReplyContainerNotFound(name) + return call.ReplyContainerNotFound(name, err.Error()) } status, err := ctr.State() @@ -427,7 +427,7 @@ func (i *LibpodAPI) ContainerCheckpoint(call iopodman.VarlinkCall, name string, ctx := getContext() ctr, err := i.Runtime.LookupContainer(name) if err != nil { - return call.ReplyContainerNotFound(name) + return call.ReplyContainerNotFound(name, err.Error()) } options := libpod.ContainerCheckpointOptions{ @@ -446,7 +446,7 @@ func (i *LibpodAPI) ContainerRestore(call iopodman.VarlinkCall, name string, kee ctx := getContext() ctr, err := i.Runtime.LookupContainer(name) if err != nil { - return call.ReplyContainerNotFound(name) + return call.ReplyContainerNotFound(name, err.Error()) } options := libpod.ContainerCheckpointOptions{ @@ -475,7 +475,7 @@ func getArtifact(ctr *libpod.Container) (*cc.CreateConfig, error) { func (i *LibpodAPI) ContainerConfig(call iopodman.VarlinkCall, name string) error { ctr, err := i.Runtime.LookupContainer(name) if err != nil { - return call.ReplyErrorOccurred(err.Error()) + return call.ReplyContainerNotFound(name, err.Error()) } config := ctr.Config() b, err := json.Marshal(config) @@ -489,7 +489,7 @@ func (i *LibpodAPI) ContainerConfig(call iopodman.VarlinkCall, name string) erro func (i *LibpodAPI) ContainerArtifacts(call iopodman.VarlinkCall, name, artifactName string) error { ctr, err := i.Runtime.LookupContainer(name) if err != nil { - return call.ReplyErrorOccurred(err.Error()) + return call.ReplyContainerNotFound(name, err.Error()) } artifacts, err := ctr.GetArtifact(artifactName) if err != nil { @@ -506,7 +506,7 @@ func (i *LibpodAPI) ContainerArtifacts(call iopodman.VarlinkCall, name, artifact func (i *LibpodAPI) ContainerInspectData(call iopodman.VarlinkCall, name string) error { ctr, err := i.Runtime.LookupContainer(name) if err != nil { - return call.ReplyErrorOccurred(err.Error()) + return call.ReplyContainerNotFound(name, err.Error()) } data, err := ctr.Inspect(true) if err != nil { @@ -524,7 +524,7 @@ func (i *LibpodAPI) ContainerInspectData(call iopodman.VarlinkCall, name string) func (i *LibpodAPI) ContainerStateData(call iopodman.VarlinkCall, name string) error { ctr, err := i.Runtime.LookupContainer(name) if err != nil { - return call.ReplyErrorOccurred(err.Error()) + return call.ReplyContainerNotFound(name, err.Error()) } data, err := ctr.ContainerState() if err != nil { diff --git a/pkg/varlinkapi/images.go b/pkg/varlinkapi/images.go index 8deb4cbe2..210f139ce 100644 --- a/pkg/varlinkapi/images.go +++ b/pkg/varlinkapi/images.go @@ -13,7 +13,6 @@ import ( "github.com/containers/buildah" "github.com/containers/buildah/imagebuildah" - "github.com/containers/image/docker" dockerarchive "github.com/containers/image/docker/archive" "github.com/containers/image/manifest" "github.com/containers/image/transports/alltransports" @@ -22,7 +21,6 @@ import ( "github.com/containers/libpod/cmd/podman/varlink" "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/image" - sysreg "github.com/containers/libpod/pkg/registries" "github.com/containers/libpod/pkg/util" "github.com/containers/libpod/utils" "github.com/containers/storage/pkg/archive" @@ -75,7 +73,7 @@ func (i *LibpodAPI) ListImages(call iopodman.VarlinkCall) error { func (i *LibpodAPI) GetImage(call iopodman.VarlinkCall, id string) error { newImage, err := i.Runtime.ImageRuntime().NewFromLocal(id) if err != nil { - return call.ReplyImageNotFound(id) + return call.ReplyImageNotFound(id, err.Error()) } labels, err := newImage.Labels(getContext()) if err != nil { @@ -137,7 +135,7 @@ func (i *LibpodAPI) BuildImage(call iopodman.VarlinkCall, config iopodman.BuildI logrus.Debugf("untar of %s successful", contextDir) // All output (stdout, stderr) is captured in output as well - output := bytes.NewBuffer([]byte{}) + var output bytes.Buffer commonOpts := &buildah.CommonBuildOptions{ AddHost: config.BuildOptions.AddHosts, @@ -170,20 +168,20 @@ func (i *LibpodAPI) BuildImage(call iopodman.VarlinkCall, config iopodman.BuildI Compression: stringCompressionToArchiveType(config.Compression), ContextDirectory: newContextDir, DefaultMountsFilePath: config.DefaultsMountFilePath, - Err: output, + Err: &output, ForceRmIntermediateCtrs: config.ForceRmIntermediateCtrs, IIDFile: config.Iidfile, Labels: config.Label, Layers: config.Layers, NoCache: config.Nocache, - Out: output, + Out: &output, Output: config.Output, NamespaceOptions: namespace, OutputFormat: config.OutputFormat, PullPolicy: stringPullPolicyToType(config.PullPolicy), Quiet: config.Quiet, RemoveIntermediateCtrs: config.RemoteIntermediateCtrs, - ReportWriter: output, + ReportWriter: &output, RuntimeArgs: config.RuntimeArgs, SignaturePolicyPath: config.SignaturePolicyPath, Squash: config.Squash, @@ -208,7 +206,13 @@ func (i *LibpodAPI) BuildImage(call iopodman.VarlinkCall, config iopodman.BuildI newPathDockerFiles = append(newPathDockerFiles, filepath.Join(newContextDir, base)) } - c := build(i.Runtime, options, newPathDockerFiles) + c := make(chan error) + go func() { + err := i.Runtime.Build(getContext(), options, newPathDockerFiles...) + c <- err + close(c) + }() + var log []string done := false for { @@ -257,23 +261,12 @@ func (i *LibpodAPI) BuildImage(call iopodman.VarlinkCall, config iopodman.BuildI return call.ReplyBuildImage(br) } -func build(runtime *libpod.Runtime, options imagebuildah.BuildOptions, dockerfiles []string) chan error { - c := make(chan error) - go func() { - err := runtime.Build(getContext(), options, dockerfiles...) - c <- err - close(c) - }() - - return c -} - // InspectImage returns an image's inspect information as a string that can be serialized. // Requires an image ID or name func (i *LibpodAPI) InspectImage(call iopodman.VarlinkCall, name string) error { newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name) if err != nil { - return call.ReplyImageNotFound(name) + return call.ReplyImageNotFound(name, err.Error()) } inspectInfo, err := newImage.Inspect(getContext()) if err != nil { @@ -291,7 +284,7 @@ func (i *LibpodAPI) InspectImage(call iopodman.VarlinkCall, name string) error { func (i *LibpodAPI) HistoryImage(call iopodman.VarlinkCall, name string) error { newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name) if err != nil { - return call.ReplyImageNotFound(name) + return call.ReplyImageNotFound(name, err.Error()) } history, err := newImage.History(getContext()) if err != nil { @@ -320,7 +313,7 @@ func (i *LibpodAPI) PushImage(call iopodman.VarlinkCall, name, tag string, tlsVe ) newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name) if err != nil { - return call.ReplyImageNotFound(err.Error()) + return call.ReplyImageNotFound(name, err.Error()) } destname := name if tag != "" { @@ -416,7 +409,7 @@ func (i *LibpodAPI) PushImage(call iopodman.VarlinkCall, name, tag string, tlsVe func (i *LibpodAPI) TagImage(call iopodman.VarlinkCall, name, tag string) error { newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name) if err != nil { - return call.ReplyImageNotFound(name) + return call.ReplyImageNotFound(name, err.Error()) } if err := newImage.TagImage(tag); err != nil { return call.ReplyErrorOccurred(err.Error()) @@ -430,7 +423,7 @@ func (i *LibpodAPI) RemoveImage(call iopodman.VarlinkCall, name string, force bo ctx := getContext() newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name) if err != nil { - return call.ReplyImageNotFound(name) + return call.ReplyImageNotFound(name, err.Error()) } _, err = i.Runtime.RemoveImage(ctx, newImage, force) if err != nil { @@ -441,54 +434,53 @@ func (i *LibpodAPI) RemoveImage(call iopodman.VarlinkCall, name string, force bo // SearchImages searches all registries configured in /etc/containers/registries.conf for an image // Requires an image name and a search limit as int -func (i *LibpodAPI) SearchImages(call iopodman.VarlinkCall, query string, limit *int64, tlsVerify *bool) error { - sc := image.GetSystemContext("", "", false) +func (i *LibpodAPI) SearchImages(call iopodman.VarlinkCall, query string, limit *int64, tlsVerify *bool, filter iopodman.ImageSearchFilter) error { + // Transform all arguments to proper types first + argLimit := 0 + argTLSVerify := types.OptionalBoolUndefined + argIsOfficial := types.OptionalBoolUndefined + argIsAutomated := types.OptionalBoolUndefined + if limit != nil { + argLimit = int(*limit) + } if tlsVerify != nil { - sc.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!*tlsVerify) + argTLSVerify = types.NewOptionalBool(!*tlsVerify) + } + if filter.Is_official != nil { + argIsOfficial = types.NewOptionalBool(*filter.Is_official) + } + if filter.Is_automated != nil { + argIsAutomated = types.NewOptionalBool(*filter.Is_automated) } - var registries []string - // Check if search query has a registry in it - registry, err := sysreg.GetRegistry(query) - if err != nil { - return call.ReplyErrorOccurred(fmt.Sprintf("error getting registry from %q: %q", query, err)) + // Transform a SearchFilter the backend can deal with + sFilter := image.SearchFilter{ + IsOfficial: argIsOfficial, + IsAutomated: argIsAutomated, + Stars: int(filter.Star_count), } - if registry != "" { - registries = append(registries, registry) - query = query[len(registry)+1:] - } else { - registries, err = sysreg.GetRegistries() - if err != nil { - return call.ReplyErrorOccurred(fmt.Sprintf("unable to get system registries: %q", err)) - } + + searchOptions := image.SearchOptions{ + Limit: argLimit, + Filter: sFilter, + InsecureSkipTLSVerify: argTLSVerify, + } + results, err := image.SearchImages(query, searchOptions) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) } + var imageResults []iopodman.ImageSearchResult - for _, reg := range registries { - var lim = 1000 - if limit != nil { - lim = int(*limit) - } - results, err := docker.SearchRegistry(getContext(), sc, reg, query, lim) - if err != nil { - // If we are searching multiple registries, don't make something like an - // auth error fatal. Unfortunately we cannot differentiate between auth - // errors and other possibles errors - if len(registries) > 1 { - continue - } - return call.ReplyErrorOccurred(err.Error()) - } - for _, result := range results { - i := iopodman.ImageSearchResult{ - Registry: reg, - Description: result.Description, - Is_official: result.IsOfficial, - Is_automated: result.IsAutomated, - Name: result.Name, - Star_count: int64(result.StarCount), - } - imageResults = append(imageResults, i) + for _, result := range results { + i := iopodman.ImageSearchResult{ + Registry: result.Index, + Description: result.Description, + Is_official: result.Official == "[OK]", + Is_automated: result.Automated == "[OK]", + Name: result.Name, + Star_count: int64(result.Stars), } + imageResults = append(imageResults, i) } return call.ReplySearchImages(imageResults) } @@ -520,7 +512,7 @@ func (i *LibpodAPI) DeleteUnusedImages(call iopodman.VarlinkCall) error { func (i *LibpodAPI) Commit(call iopodman.VarlinkCall, name, imageName string, changes []string, author, message string, pause bool, manifestType string) error { ctr, err := i.Runtime.LookupContainer(name) if err != nil { - return call.ReplyContainerNotFound(name) + return call.ReplyContainerNotFound(name, err.Error()) } sc := image.GetSystemContext(i.Runtime.GetConfig().SignaturePolicyPath, "", false) var mimeType string @@ -584,7 +576,7 @@ func (i *LibpodAPI) ImportImage(call iopodman.VarlinkCall, source, reference, me func (i *LibpodAPI) ExportImage(call iopodman.VarlinkCall, name, destination string, compress bool, tags []string) error { newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name) if err != nil { - return call.ReplyImageNotFound(name) + return call.ReplyImageNotFound(name, err.Error()) } additionalTags, err := image.GetAdditionalTags(tags) @@ -622,24 +614,74 @@ func (i *LibpodAPI) PullImage(call iopodman.VarlinkCall, name string, certDir, c so := image.SigningOptions{} - if strings.HasPrefix(name, dockerarchive.Transport.Name()+":") { - srcRef, err := alltransports.ParseImageName(name) - if err != nil { - return errors.Wrapf(err, "error parsing %q", name) + if call.WantsMore() { + call.Continues = true + } + output := bytes.NewBuffer([]byte{}) + c := make(chan error) + go func() { + //err := newImage.PushImageToHeuristicDestination(getContext(), destname, manifestType, "", signaturePolicy, output, compress, so, &dockerRegistryOptions, nil) + if strings.HasPrefix(name, dockerarchive.Transport.Name()+":") { + srcRef, err := alltransports.ParseImageName(name) + if err != nil { + c <- errors.Wrapf(err, "error parsing %q", name) + } + newImage, err := i.Runtime.ImageRuntime().LoadFromArchiveReference(getContext(), srcRef, signaturePolicy, output) + if err != nil { + c <- errors.Wrapf(err, "error pulling image from %q", name) + } + imageID = newImage[0].ID() + } else { + newImage, err := i.Runtime.ImageRuntime().New(getContext(), name, signaturePolicy, "", output, &dockerRegistryOptions, so, false, nil) + if err != nil { + c <- errors.Wrapf(err, "unable to pull %s", name) + } + imageID = newImage.ID() } - newImage, err := i.Runtime.ImageRuntime().LoadFromArchiveReference(getContext(), srcRef, signaturePolicy, nil) - if err != nil { - return errors.Wrapf(err, "error pulling image from %q", name) + c <- nil + close(c) + }() + + var log []string + done := false + for { + line, err := output.ReadString('\n') + if err == nil { + log = append(log, line) + continue + } else if err == io.EOF { + select { + case err := <-c: + if err != nil { + logrus.Errorf("reading of output during pull failed for %s", name) + return call.ReplyErrorOccurred(err.Error()) + } + done = true + default: + if !call.WantsMore() { + time.Sleep(1 * time.Second) + break + } + br := iopodman.MoreResponse{ + Logs: log, + } + call.ReplyPullImage(br) + log = []string{} + } + } else { + return call.ReplyErrorOccurred(err.Error()) } - imageID = newImage[0].ID() - } else { - newImage, err := i.Runtime.ImageRuntime().New(getContext(), name, signaturePolicy, "", nil, &dockerRegistryOptions, so, false, nil) - if err != nil { - return call.ReplyErrorOccurred(fmt.Sprintf("unable to pull %s: %s", name, err.Error())) + if done { + break } - imageID = newImage.ID() } - return call.ReplyPullImage(imageID) + call.Continues = false + + br := iopodman.MoreResponse{ + Logs: log, + Id: imageID, + } + return call.ReplyPullImage(br) } // ImageExists returns bool as to whether the input image exists in local storage @@ -694,3 +736,172 @@ func (i *LibpodAPI) ImagesPrune(call iopodman.VarlinkCall, all bool) error { } return call.ReplyImagesPrune(prunedImages) } + +// ImageSave .... +func (i *LibpodAPI) ImageSave(call iopodman.VarlinkCall, options iopodman.ImageSaveOptions) error { + newImage, err := i.Runtime.ImageRuntime().NewFromLocal(options.Name) + if err != nil { + if errors.Cause(err) == libpod.ErrNoSuchImage { + return call.ReplyImageNotFound(options.Name, err.Error()) + } + return call.ReplyErrorOccurred(err.Error()) + } + + // Determine if we are dealing with a tarball or dir + var output string + outputToDir := false + if options.Format == "oci-archive" || options.Format == "docker-archive" { + tempfile, err := ioutil.TempFile("", "varlink_send") + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + output = tempfile.Name() + tempfile.Close() + } else { + var err error + outputToDir = true + output, err = ioutil.TempDir("", "varlink_send") + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + } + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + if call.WantsMore() { + call.Continues = true + } + + saveOutput := bytes.NewBuffer([]byte{}) + c := make(chan error) + go func() { + err := newImage.Save(getContext(), options.Name, options.Format, output, options.MoreTags, options.Quiet, options.Compress) + c <- err + close(c) + }() + var log []string + done := false + for { + line, err := saveOutput.ReadString('\n') + if err == nil { + log = append(log, line) + continue + } else if err == io.EOF { + select { + case err := <-c: + if err != nil { + logrus.Errorf("reading of output during save failed for %s", newImage.ID()) + return call.ReplyErrorOccurred(err.Error()) + } + done = true + default: + if !call.WantsMore() { + time.Sleep(1 * time.Second) + break + } + br := iopodman.MoreResponse{ + Logs: log, + } + call.ReplyImageSave(br) + log = []string{} + } + } else { + return call.ReplyErrorOccurred(err.Error()) + } + if done { + break + } + } + call.Continues = false + + sendfile := output + // Image has been saved to `output` + if outputToDir { + // If the output is a directory, we need to tar up the directory to send it back + //Create a tempfile for the directory tarball + outputFile, err := ioutil.TempFile("", "varlink_save_dir") + if err != nil { + return err + } + defer outputFile.Close() + if err := utils.TarToFilesystem(output, outputFile); err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + sendfile = outputFile.Name() + } + br := iopodman.MoreResponse{ + Logs: log, + Id: sendfile, + } + return call.ReplyPushImage(br) +} + +// LoadImage ... +func (i *LibpodAPI) LoadImage(call iopodman.VarlinkCall, name, inputFile string, deleteInputFile, quiet bool) error { + var ( + names string + writer io.Writer + err error + ) + if !quiet { + writer = os.Stderr + } + + if call.WantsMore() { + call.Continues = true + } + output := bytes.NewBuffer([]byte{}) + + c := make(chan error) + go func() { + names, err = i.Runtime.LoadImage(getContext(), name, inputFile, writer, "") + c <- err + close(c) + }() + + var log []string + done := false + for { + line, err := output.ReadString('\n') + if err == nil { + log = append(log, line) + continue + } else if err == io.EOF { + select { + case err := <-c: + if err != nil { + logrus.Error(err) + return call.ReplyErrorOccurred(err.Error()) + } + done = true + default: + if !call.WantsMore() { + time.Sleep(1 * time.Second) + break + } + br := iopodman.MoreResponse{ + Logs: log, + } + call.ReplyLoadImage(br) + log = []string{} + } + } else { + return call.ReplyErrorOccurred(err.Error()) + } + if done { + break + } + } + call.Continues = false + + br := iopodman.MoreResponse{ + Logs: log, + Id: names, + } + if deleteInputFile { + if err := os.Remove(inputFile); err != nil { + logrus.Errorf("unable to delete input file %s", inputFile) + } + } + return call.ReplyLoadImage(br) +} diff --git a/pkg/varlinkapi/pods.go b/pkg/varlinkapi/pods.go index 6e758786a..4ca4c4270 100644 --- a/pkg/varlinkapi/pods.go +++ b/pkg/varlinkapi/pods.go @@ -2,6 +2,7 @@ package varlinkapi import ( "encoding/json" + "github.com/containers/libpod/pkg/adapter/shortcuts" "github.com/containers/libpod/pkg/rootless" "syscall" @@ -13,10 +14,6 @@ import ( // CreatePod ... func (i *LibpodAPI) CreatePod(call iopodman.VarlinkCall, create iopodman.PodCreate) error { var options []libpod.PodCreateOption - - if create.InfraCommand != "" || create.InfraImage != "" { - return call.ReplyErrorOccurred("the infra-command and infra-image options are not supported yet") - } if create.CgroupParent != "" { options = append(options, libpod.WithPodCgroupParent(create.CgroupParent)) } @@ -89,7 +86,7 @@ func (i *LibpodAPI) ListPods(call iopodman.VarlinkCall) error { func (i *LibpodAPI) GetPod(call iopodman.VarlinkCall, name string) error { pod, err := i.Runtime.LookupPod(name) if err != nil { - return call.ReplyPodNotFound(name) + return call.ReplyPodNotFound(name, err.Error()) } opts := shared.PsOptions{} @@ -105,7 +102,7 @@ func (i *LibpodAPI) GetPod(call iopodman.VarlinkCall, name string) error { func (i *LibpodAPI) InspectPod(call iopodman.VarlinkCall, name string) error { pod, err := i.Runtime.LookupPod(name) if err != nil { - return call.ReplyPodNotFound(name) + return call.ReplyPodNotFound(name, err.Error()) } inspectData, err := pod.Inspect() if err != nil { @@ -122,7 +119,7 @@ func (i *LibpodAPI) InspectPod(call iopodman.VarlinkCall, name string) error { func (i *LibpodAPI) StartPod(call iopodman.VarlinkCall, name string) error { pod, err := i.Runtime.LookupPod(name) if err != nil { - return call.ReplyPodNotFound(name) + return call.ReplyPodNotFound(name, err.Error()) } ctnrs, err := pod.AllContainers() if err != nil { @@ -143,7 +140,7 @@ func (i *LibpodAPI) StartPod(call iopodman.VarlinkCall, name string) error { func (i *LibpodAPI) StopPod(call iopodman.VarlinkCall, name string, timeout int64) error { pod, err := i.Runtime.LookupPod(name) if err != nil { - return call.ReplyPodNotFound(name) + return call.ReplyPodNotFound(name, err.Error()) } ctrErrs, err := pod.StopWithTimeout(getContext(), true, int(timeout)) callErr := handlePodCall(call, pod, ctrErrs, err) @@ -157,7 +154,7 @@ func (i *LibpodAPI) StopPod(call iopodman.VarlinkCall, name string, timeout int6 func (i *LibpodAPI) RestartPod(call iopodman.VarlinkCall, name string) error { pod, err := i.Runtime.LookupPod(name) if err != nil { - return call.ReplyPodNotFound(name) + return call.ReplyPodNotFound(name, err.Error()) } ctnrs, err := pod.AllContainers() if err != nil { @@ -184,7 +181,7 @@ func (i *LibpodAPI) KillPod(call iopodman.VarlinkCall, name string, signal int64 pod, err := i.Runtime.LookupPod(name) if err != nil { - return call.ReplyPodNotFound(name) + return call.ReplyPodNotFound(name, err.Error()) } ctrErrs, err := pod.Kill(killSignal) callErr := handlePodCall(call, pod, ctrErrs, err) @@ -198,7 +195,7 @@ func (i *LibpodAPI) KillPod(call iopodman.VarlinkCall, name string, signal int64 func (i *LibpodAPI) PausePod(call iopodman.VarlinkCall, name string) error { pod, err := i.Runtime.LookupPod(name) if err != nil { - return call.ReplyPodNotFound(name) + return call.ReplyPodNotFound(name, err.Error()) } ctrErrs, err := pod.Pause() callErr := handlePodCall(call, pod, ctrErrs, err) @@ -212,7 +209,7 @@ func (i *LibpodAPI) PausePod(call iopodman.VarlinkCall, name string) error { func (i *LibpodAPI) UnpausePod(call iopodman.VarlinkCall, name string) error { pod, err := i.Runtime.LookupPod(name) if err != nil { - return call.ReplyPodNotFound(name) + return call.ReplyPodNotFound(name, err.Error()) } ctrErrs, err := pod.Unpause() callErr := handlePodCall(call, pod, ctrErrs, err) @@ -227,7 +224,7 @@ func (i *LibpodAPI) RemovePod(call iopodman.VarlinkCall, name string, force bool ctx := getContext() pod, err := i.Runtime.LookupPod(name) if err != nil { - return call.ReplyPodNotFound(name) + return call.ReplyPodNotFound(name, err.Error()) } if err = i.Runtime.RemovePod(ctx, pod, force, force); err != nil { return call.ReplyErrorOccurred(err.Error()) @@ -240,7 +237,7 @@ func (i *LibpodAPI) RemovePod(call iopodman.VarlinkCall, name string, force bool func (i *LibpodAPI) GetPodStats(call iopodman.VarlinkCall, name string) error { pod, err := i.Runtime.LookupPod(name) if err != nil { - return call.ReplyPodNotFound(name) + return call.ReplyPodNotFound(name, err.Error()) } prevStats := make(map[string]*libpod.ContainerStats) podStats, err := pod.GetPodStats(prevStats) @@ -271,3 +268,34 @@ func (i *LibpodAPI) GetPodStats(call iopodman.VarlinkCall, name string) error { } return call.ReplyGetPodStats(pod.ID(), containersStats) } + +// GetPodsByContext returns a slice of pod ids based on all, latest, or a list +func (i *LibpodAPI) GetPodsByContext(call iopodman.VarlinkCall, all, latest bool, input []string) error { + var podids []string + + pods, err := shortcuts.GetPodsByContext(all, latest, input, i.Runtime) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + for _, p := range pods { + podids = append(podids, p.ID()) + } + return call.ReplyGetPodsByContext(podids) +} + +// PodStateData returns a container's state data in string format +func (i *LibpodAPI) PodStateData(call iopodman.VarlinkCall, name string) error { + pod, err := i.Runtime.LookupPod(name) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + data, err := pod.Inspect() + if err != nil { + return call.ReplyErrorOccurred("unable to obtain pod state") + } + b, err := json.Marshal(data) + if err != nil { + return call.ReplyErrorOccurred("unable to serialize pod inspect data") + } + return call.ReplyPodStateData(string(b)) +} |