diff options
Diffstat (limited to 'pkg/varlinkapi')
-rw-r--r-- | pkg/varlinkapi/containers.go | 49 | ||||
-rw-r--r-- | pkg/varlinkapi/containers_create.go | 9 | ||||
-rw-r--r-- | pkg/varlinkapi/images.go | 144 | ||||
-rw-r--r-- | pkg/varlinkapi/mount.go | 49 | ||||
-rw-r--r-- | pkg/varlinkapi/pods.go | 24 |
5 files changed, 256 insertions, 19 deletions
diff --git a/pkg/varlinkapi/containers.go b/pkg/varlinkapi/containers.go index f517e9b6e..07d981786 100644 --- a/pkg/varlinkapi/containers.go +++ b/pkg/varlinkapi/containers.go @@ -278,6 +278,18 @@ func (i *LibpodAPI) RestartContainer(call iopodman.VarlinkCall, name string, tim return call.ReplyRestartContainer(ctr.ID()) } +// ContainerExists looks in local storage for the existence of a container +func (i *LibpodAPI) ContainerExists(call iopodman.VarlinkCall, name string) error { + _, err := i.Runtime.LookupContainer(name) + if errors.Cause(err) == libpod.ErrNoSuchCtr { + return call.ReplyContainerExists(1) + } + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + return call.ReplyContainerExists(0) +} + // KillContainer kills a running container. If you want to use the default SIGTERM signal, just send a -1 // for the signal arg. func (i *LibpodAPI) KillContainer(call iopodman.VarlinkCall, name string, signal int64) error { @@ -413,3 +425,40 @@ func (i *LibpodAPI) GetAttachSockets(call iopodman.VarlinkCall, name string) err } return call.ReplyGetAttachSockets(s) } + +// ContainerCheckpoint ... +func (i *LibpodAPI) ContainerCheckpoint(call iopodman.VarlinkCall, name string, keep, leaveRunning, tcpEstablished bool) error { + ctx := getContext() + ctr, err := i.Runtime.LookupContainer(name) + if err != nil { + return call.ReplyContainerNotFound(name) + } + + options := libpod.ContainerCheckpointOptions{ + Keep: keep, + TCPEstablished: tcpEstablished, + KeepRunning: leaveRunning, + } + if err := ctr.Checkpoint(ctx, options); err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + return call.ReplyContainerCheckpoint(ctr.ID()) +} + +// ContainerRestore ... +func (i *LibpodAPI) ContainerRestore(call iopodman.VarlinkCall, name string, keep, tcpEstablished bool) error { + ctx := getContext() + ctr, err := i.Runtime.LookupContainer(name) + if err != nil { + return call.ReplyContainerNotFound(name) + } + + options := libpod.ContainerCheckpointOptions{ + Keep: keep, + TCPEstablished: tcpEstablished, + } + if err := ctr.Restore(ctx, options); err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + return call.ReplyContainerRestore(ctr.ID()) +} diff --git a/pkg/varlinkapi/containers_create.go b/pkg/varlinkapi/containers_create.go index ca1a57048..bb6273fd1 100644 --- a/pkg/varlinkapi/containers_create.go +++ b/pkg/varlinkapi/containers_create.go @@ -13,6 +13,7 @@ import ( "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/pkg/inspect" "github.com/containers/libpod/pkg/namespaces" + "github.com/containers/libpod/pkg/rootless" cc "github.com/containers/libpod/pkg/spec" "github.com/containers/libpod/pkg/util" "github.com/docker/docker/pkg/signal" @@ -24,7 +25,7 @@ func (i *LibpodAPI) CreateContainer(call iopodman.VarlinkCall, config iopodman.C rtc := i.Runtime.GetConfig() ctx := getContext() - newImage, err := i.Runtime.ImageRuntime().New(ctx, config.Image, rtc.SignaturePolicyPath, "", os.Stderr, nil, image.SigningOptions{}, false, false) + newImage, err := i.Runtime.ImageRuntime().New(ctx, config.Image, rtc.SignaturePolicyPath, "", os.Stderr, nil, image.SigningOptions{}, false) if err != nil { return call.ReplyErrorOccurred(err.Error()) } @@ -126,7 +127,11 @@ func varlinkCreateToCreateConfig(ctx context.Context, create iopodman.Create, ru // NETWORK MODE networkMode := create.Net_mode if networkMode == "" { - networkMode = "bridge" + if rootless.IsRootless() { + networkMode = "slirp4netns" + } else { + networkMode = "bridge" + } } // WORKING DIR diff --git a/pkg/varlinkapi/images.go b/pkg/varlinkapi/images.go index d14c61c39..5e4cb4ccb 100644 --- a/pkg/varlinkapi/images.go +++ b/pkg/varlinkapi/images.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "io" + "os" "path/filepath" "strings" "time" @@ -12,13 +13,17 @@ 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" "github.com/containers/image/types" + "github.com/containers/libpod/cmd/podman/shared" "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/docker/go-units" "github.com/opencontainers/image-spec/specs-go/v1" "github.com/opencontainers/runtime-spec/specs-go" @@ -127,7 +132,7 @@ func (i *LibpodAPI) BuildImage(call iopodman.VarlinkCall, config iopodman.BuildI if config.Pull_always { pullPolicy = imagebuildah.PullAlways } - manifestType := "oci" + manifestType := "oci" //nolint if config.Image_format != "" { manifestType = config.Image_format } @@ -271,6 +276,9 @@ func (i *LibpodAPI) InspectImage(call iopodman.VarlinkCall, name string) error { return call.ReplyImageNotFound(name) } inspectInfo, err := newImage.Inspect(getContext()) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } b, err := json.Marshal(inspectInfo) if err != nil { return call.ReplyErrorOccurred(fmt.Sprintf("unable to serialize")) @@ -305,8 +313,12 @@ func (i *LibpodAPI) HistoryImage(call iopodman.VarlinkCall, name string) error { } // PushImage pushes an local image to registry -// TODO We need to add options for signing, credentials, tls, and multi-tag -func (i *LibpodAPI) PushImage(call iopodman.VarlinkCall, name, tag string, tlsVerify bool) error { +func (i *LibpodAPI) PushImage(call iopodman.VarlinkCall, name, tag string, tlsVerify bool, signaturePolicy, creds, certDir string, compress bool, format string, removeSignatures bool, signBy string) error { + var ( + registryCreds *types.DockerAuthConfig + manifestType string + ) + newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name) if err != nil { return call.ReplyImageNotFound(err.Error()) @@ -315,14 +327,38 @@ func (i *LibpodAPI) PushImage(call iopodman.VarlinkCall, name, tag string, tlsVe if tag != "" { destname = tag } - + if creds != "" { + creds, err := util.ParseRegistryCreds(creds) + if err != nil { + return err + } + registryCreds = creds + } dockerRegistryOptions := image.DockerRegistryOptions{ - DockerInsecureSkipTLSVerify: !tlsVerify, + DockerRegistryCreds: registryCreds, + DockerCertPath: certDir, + } + if !tlsVerify { + dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.OptionalBoolTrue + } + if format != "" { + switch format { + case "oci": //nolint + manifestType = v1.MediaTypeImageManifest + case "v2s1": + manifestType = manifest.DockerV2Schema1SignedMediaType + case "v2s2", "docker": + manifestType = manifest.DockerV2Schema2MediaType + default: + return call.ReplyErrorOccurred(fmt.Sprintf("unknown format %q. Choose on of the supported formats: 'oci', 'v2s1', or 'v2s2'", format)) + } + } + so := image.SigningOptions{ + RemoveSignatures: removeSignatures, + SignBy: signBy, } - so := image.SigningOptions{} - - if err := newImage.PushImageToHeuristicDestination(getContext(), destname, "", "", "", nil, false, so, &dockerRegistryOptions, false, nil); err != nil { + if err := newImage.PushImageToHeuristicDestination(getContext(), destname, manifestType, "", signaturePolicy, nil, compress, so, &dockerRegistryOptions, nil); err != nil { return call.ReplyErrorOccurred(err.Error()) } return call.ReplyPushImage(newImage.ID()) @@ -421,7 +457,7 @@ func (i *LibpodAPI) Commit(call iopodman.VarlinkCall, name, imageName string, ch sc := image.GetSystemContext(i.Runtime.GetConfig().SignaturePolicyPath, "", false) var mimeType string switch manifestType { - case "oci", "": + case "oci", "": //nolint mimeType = buildah.OCIv1ImageManifest case "docker": mimeType = manifest.DockerV2Schema2MediaType @@ -482,18 +518,96 @@ func (i *LibpodAPI) ExportImage(call iopodman.VarlinkCall, name, destination str return err } - if err := newImage.PushImageToHeuristicDestination(getContext(), destination, "", "", "", nil, compress, image.SigningOptions{}, &image.DockerRegistryOptions{}, false, additionalTags); err != nil { + if err := newImage.PushImageToHeuristicDestination(getContext(), destination, "", "", "", nil, compress, image.SigningOptions{}, &image.DockerRegistryOptions{}, additionalTags); err != nil { return call.ReplyErrorOccurred(err.Error()) } return call.ReplyExportImage(newImage.ID()) } // PullImage pulls an image from a registry to the image store. -// TODO This implementation is incomplete -func (i *LibpodAPI) PullImage(call iopodman.VarlinkCall, name string) error { - newImage, err := i.Runtime.ImageRuntime().New(getContext(), name, "", "", nil, &image.DockerRegistryOptions{}, image.SigningOptions{}, true, false) +func (i *LibpodAPI) PullImage(call iopodman.VarlinkCall, name string, certDir, creds, signaturePolicy string, tlsVerify bool) error { + var ( + registryCreds *types.DockerAuthConfig + imageID string + ) + if creds != "" { + creds, err := util.ParseRegistryCreds(creds) + if err != nil { + return err + } + registryCreds = creds + } + + dockerRegistryOptions := image.DockerRegistryOptions{ + DockerRegistryCreds: registryCreds, + DockerCertPath: certDir, + } + if tlsVerify { + dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!tlsVerify) + } + + 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) + } + newImage, err := i.Runtime.ImageRuntime().LoadFromArchiveReference(getContext(), srcRef, signaturePolicy, nil) + if err != nil { + return errors.Wrapf(err, "error pulling image from %q", name) + } + imageID = newImage[0].ID() + } else { + newImage, err := i.Runtime.ImageRuntime().New(getContext(), name, signaturePolicy, "", nil, &dockerRegistryOptions, so, false) + if err != nil { + return call.ReplyErrorOccurred(fmt.Sprintf("unable to pull %s: %s", name, err.Error())) + } + imageID = newImage.ID() + } + return call.ReplyPullImage(imageID) +} + +// ImageExists returns bool as to whether the input image exists in local storage +func (i *LibpodAPI) ImageExists(call iopodman.VarlinkCall, name string) error { + _, err := i.Runtime.ImageRuntime().NewFromLocal(name) + if errors.Cause(err) == image.ErrNoSuchImage { + return call.ReplyImageExists(1) + } + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + return call.ReplyImageExists(0) +} + +// ContainerRunlabel ... +func (i *LibpodAPI) ContainerRunlabel(call iopodman.VarlinkCall, input iopodman.Runlabel) error { + ctx := getContext() + dockerRegistryOptions := image.DockerRegistryOptions{ + DockerCertPath: input.CertDir, + } + if !input.TlsVerify { + dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.OptionalBoolTrue + } + + stdErr := os.Stderr + stdOut := os.Stdout + stdIn := os.Stdin + + runLabel, imageName, err := shared.GetRunlabel(input.Label, input.Image, ctx, i.Runtime, input.Pull, input.Creds, dockerRegistryOptions, input.Authfile, input.SignaturePolicyPath, nil) + if err != nil { + return err + } + if runLabel == "" { + return nil + } + + cmd, env, err := shared.GenerateRunlabelCommand(runLabel, imageName, input.Name, input.Opts, input.ExtraArgs) if err != nil { - return call.ReplyErrorOccurred(fmt.Sprintf("unable to pull %s: %s", name, err.Error())) + return err + } + if err := utils.ExecCmdWithStdStreams(stdIn, stdOut, stdErr, env, cmd[0], cmd[1:]...); err != nil { + return call.ReplyErrorOccurred(err.Error()) } - return call.ReplyPullImage(newImage.ID()) + return call.ReplyContainerRunlabel() } diff --git a/pkg/varlinkapi/mount.go b/pkg/varlinkapi/mount.go new file mode 100644 index 000000000..84e6b2709 --- /dev/null +++ b/pkg/varlinkapi/mount.go @@ -0,0 +1,49 @@ +package varlinkapi + +import ( + "github.com/containers/libpod/cmd/podman/varlink" +) + +// ListContainerMounts ... +func (i *LibpodAPI) ListContainerMounts(call iopodman.VarlinkCall) error { + var mounts []string + allContainers, err := i.Runtime.GetAllContainers() + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + for _, container := range allContainers { + mounted, mountPoint, err := container.Mounted() + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + if mounted { + mounts = append(mounts, mountPoint) + } + } + return call.ReplyListContainerMounts(mounts) +} + +// MountContainer ... +func (i *LibpodAPI) MountContainer(call iopodman.VarlinkCall, name string) error { + container, err := i.Runtime.LookupContainer(name) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + path, err := container.Mount() + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + return call.ReplyMountContainer(path) +} + +// UnmountContainer ... +func (i *LibpodAPI) UnmountContainer(call iopodman.VarlinkCall, name string, force bool) error { + container, err := i.Runtime.LookupContainer(name) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + if err := container.Unmount(force); err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + return call.ReplyUnmountContainer() +} diff --git a/pkg/varlinkapi/pods.go b/pkg/varlinkapi/pods.go index 7930a956f..6e758786a 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/rootless" "syscall" "github.com/containers/libpod/cmd/podman/shared" @@ -12,6 +13,10 @@ 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)) } @@ -27,6 +32,21 @@ func (i *LibpodAPI) CreatePod(call iopodman.VarlinkCall, create iopodman.PodCrea if len(create.Share) == 0 && create.Infra { return call.ReplyErrorOccurred("You must share kernel namespaces to run an infra container") } + + if len(create.Publish) > 0 { + if !create.Infra { + return call.ReplyErrorOccurred("you must have an infra container to publish port bindings to the host") + } + if rootless.IsRootless() { + return call.ReplyErrorOccurred("rootless networking does not allow port binding to the host") + } + portBindings, err := shared.CreatePortBindings(create.Publish) + if err != nil { + return err + } + options = append(options, libpod.WithInfraContainerPorts(portBindings)) + + } if create.Infra { options = append(options, libpod.WithInfraContainer()) nsOptions, err := shared.GetNamespaceOptions(create.Share) @@ -120,12 +140,12 @@ func (i *LibpodAPI) StartPod(call iopodman.VarlinkCall, name string) error { } // StopPod ... -func (i *LibpodAPI) StopPod(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) } - ctrErrs, err := pod.Stop(getContext(), true) + ctrErrs, err := pod.StopWithTimeout(getContext(), true, int(timeout)) callErr := handlePodCall(call, pod, ctrErrs, err) if callErr != nil { return err |