Clean up some existing varlink endpoints

Going through and adding options (like tls-verify, signature option, etc)
to some varlink endpoints (like push/pull) many of which had not been
updated since their original authoring.

Signed-off-by: baude <bbaude@redhat.com>
This commit is contained in:
baude
2018-12-11 13:44:55 -06:00
parent 8645df84db
commit 06d763d964
6 changed files with 156 additions and 65 deletions

19
API.md
View File

@ -87,9 +87,9 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in
[func Ping() StringResponse](#Ping)
[func PullImage(name: string) string](#PullImage)
[func PullImage(name: string, certDir: string, creds: string, signaturePolicy: string, tlsVerify: bool) string](#PullImage)
[func PushImage(name: string, tag: string, tlsverify: bool) string](#PushImage)
[func PushImage(name: string, tag: string, tlsverify: bool, signaturePolicy: string, creds: string, certDir: string, compress: bool, format: string, removeSignatures: bool, signBy: string) string](#PushImage)
[func RemoveContainer(name: string, force: bool) string](#RemoveContainer)
@ -739,7 +739,7 @@ $ varlink call -m unix:/run/podman/io.podman/io.podman.Ping
### <a name="PullImage"></a>func PullImage
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method PullImage(name: [string](https://godoc.org/builtin#string)) [string](https://godoc.org/builtin#string)</div>
method PullImage(name: [string](https://godoc.org/builtin#string), certDir: [string](https://godoc.org/builtin#string), creds: [string](https://godoc.org/builtin#string), signaturePolicy: [string](https://godoc.org/builtin#string), tlsVerify: [bool](https://godoc.org/builtin#bool)) [string](https://godoc.org/builtin#string)</div>
PullImage pulls an image from a repository to local storage. After the pull is successful, the ID of the image
is returned.
#### Example
@ -752,7 +752,7 @@ $ varlink call -m unix:/run/podman/io.podman/io.podman.PullImage '{"name": "regi
### <a name="PushImage"></a>func PushImage
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method PushImage(name: [string](https://godoc.org/builtin#string), tag: [string](https://godoc.org/builtin#string), tlsverify: [bool](https://godoc.org/builtin#bool)) [string](https://godoc.org/builtin#string)</div>
method PushImage(name: [string](https://godoc.org/builtin#string), tag: [string](https://godoc.org/builtin#string), tlsverify: [bool](https://godoc.org/builtin#bool), signaturePolicy: [string](https://godoc.org/builtin#string), creds: [string](https://godoc.org/builtin#string), certDir: [string](https://godoc.org/builtin#string), compress: [bool](https://godoc.org/builtin#bool), format: [string](https://godoc.org/builtin#string), removeSignatures: [bool](https://godoc.org/builtin#bool), signBy: [string](https://godoc.org/builtin#string)) [string](https://godoc.org/builtin#string)</div>
PushImage takes three input arguments: the name or ID of an image, the fully-qualified destination name of the image,
and a boolean as to whether tls-verify should be used (with false disabling TLS, not affecting the default behavior).
It will return an [ImageNotFound](#ImageNotFound) error if
@ -1499,9 +1499,8 @@ reason [string](https://godoc.org/builtin#string)
### <a name="PodCreate"></a>type PodCreate
PodCreate is an input structure for creating pods.
It emulates options to podman pod create, however
changing pause image name and pause container
is not currently supported
It emulates options to podman pod create. The infraCommand and
infraImage options are currently NotSupported.
name [string](https://godoc.org/builtin#string)
@ -1512,6 +1511,12 @@ labels [map[string]](#map[string])
share [[]string](#[]string)
infra [bool](https://godoc.org/builtin#bool)
infraCommand [string](https://godoc.org/builtin#string)
infraImage [string](https://godoc.org/builtin#string)
publish [[]string](#[]string)
### <a name="PodmanInfo"></a>type PodmanInfo
PodmanInfo describes the Podman host and build

View File

@ -3,15 +3,12 @@ package main
import (
"fmt"
"os"
"strconv"
"strings"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
"github.com/cri-o/ocicni/pkg/ocicni"
"github.com/docker/go-connections/nat"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
@ -150,7 +147,7 @@ func podCreateCmd(c *cli.Context) error {
}
if len(c.StringSlice("publish")) > 0 {
portBindings, err := CreatePortBindings(c.StringSlice("publish"))
portBindings, err := shared.CreatePortBindings(c.StringSlice("publish"))
if err != nil {
return err
}
@ -178,36 +175,3 @@ func podCreateCmd(c *cli.Context) error {
return nil
}
// CreatePortBindings iterates ports mappings and exposed ports into a format CNI understands
func CreatePortBindings(ports []string) ([]ocicni.PortMapping, error) {
var portBindings []ocicni.PortMapping
// The conversion from []string to natBindings is temporary while mheon reworks the port
// deduplication code. Eventually that step will not be required.
_, natBindings, err := nat.ParsePortSpecs(ports)
if err != nil {
return nil, err
}
for containerPb, hostPb := range natBindings {
var pm ocicni.PortMapping
pm.ContainerPort = int32(containerPb.Int())
for _, i := range hostPb {
var hostPort int
var err error
pm.HostIP = i.HostIP
if i.HostPort == "" {
hostPort = containerPb.Int()
} else {
hostPort, err = strconv.Atoi(i.HostPort)
if err != nil {
return nil, errors.Wrapf(err, "unable to convert host port to integer")
}
}
pm.HostPort = int32(hostPort)
pm.Protocol = containerPb.Proto()
portBindings = append(portBindings, pm)
}
}
return portBindings, nil
}

View File

@ -1,7 +1,11 @@
package shared
import (
"strconv"
"github.com/containers/libpod/libpod"
"github.com/cri-o/ocicni/pkg/ocicni"
"github.com/docker/go-connections/nat"
"github.com/pkg/errors"
)
@ -95,3 +99,36 @@ func GetNamespaceOptions(ns []string) ([]libpod.PodCreateOption, error) {
}
return options, nil
}
// CreatePortBindings iterates ports mappings and exposed ports into a format CNI understands
func CreatePortBindings(ports []string) ([]ocicni.PortMapping, error) {
var portBindings []ocicni.PortMapping
// The conversion from []string to natBindings is temporary while mheon reworks the port
// deduplication code. Eventually that step will not be required.
_, natBindings, err := nat.ParsePortSpecs(ports)
if err != nil {
return nil, err
}
for containerPb, hostPb := range natBindings {
var pm ocicni.PortMapping
pm.ContainerPort = int32(containerPb.Int())
for _, i := range hostPb {
var hostPort int
var err error
pm.HostIP = i.HostIP
if i.HostPort == "" {
hostPort = containerPb.Int()
} else {
hostPort, err = strconv.Atoi(i.HostPort)
if err != nil {
return nil, errors.Wrapf(err, "unable to convert host port to integer")
}
}
pm.HostPort = int32(hostPort)
pm.Protocol = containerPb.Proto()
portBindings = append(portBindings, pm)
}
}
return portBindings, nil
}

View File

@ -343,15 +343,17 @@ type ListPodContainerInfo (
)
# PodCreate is an input structure for creating pods.
# It emulates options to podman pod create, however
# changing pause image name and pause container
# is not currently supported
# It emulates options to podman pod create. The infraCommand and
# infraImage options are currently NotSupported.
type PodCreate (
name: string,
cgroupParent: string,
labels: [string]string,
share: []string,
infra: bool
infra: bool,
infraCommand: string,
infraImage: string,
publish: []string
)
# ListPodData is the returned struct for an individual pod
@ -632,7 +634,7 @@ method HistoryImage(name: string) -> (history: []ImageHistory)
# and a boolean as to whether tls-verify should be used (with false disabling TLS, not affecting the default behavior).
# It will return an [ImageNotFound](#ImageNotFound) error if
# the image cannot be found in local storage; otherwise the ID of the image will be returned on success.
method PushImage(name: string, tag: string, tlsverify: bool) -> (image: string)
method PushImage(name: string, tag: string, tlsverify: bool, signaturePolicy: string, creds: string, certDir: string, compress: bool, format: string, removeSignatures: bool, signBy: string) -> (image: string)
# TagImage takes the name or ID of an image in local storage as well as the desired tag name. If the image cannot
# be found, an [ImageNotFound](#ImageNotFound) error will be returned; otherwise, the ID of the image is returned on success.
@ -700,7 +702,7 @@ method ExportImage(name: string, destination: string, compress: bool, tags: []st
# "id": "426866d6fa419873f97e5cbd320eeb22778244c1dfffa01c944db3114f55772e"
# }
# ~~~
method PullImage(name: string) -> (id: string)
method PullImage(name: string, certDir: string, creds: string, signaturePolicy: string, tlsVerify: bool) -> (id: string)
# CreatePod creates a new empty pod. It uses a [PodCreate](#PodCreate) type for input.
# On success, the ID of the newly created pod will be returned.

View File

@ -13,7 +13,9 @@ 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"
@ -130,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
}
@ -311,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())
@ -321,15 +327,38 @@ func (i *LibpodAPI) PushImage(call iopodman.VarlinkCall, name, tag string, tlsVe
if tag != "" {
destname = tag
}
dockerRegistryOptions := image.DockerRegistryOptions{}
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.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, 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())
@ -428,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
@ -496,13 +525,47 @@ func (i *LibpodAPI) ExportImage(call iopodman.VarlinkCall, name, destination str
}
// 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)
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()))
}
return call.ReplyPullImage(newImage.ID())
imageID = newImage.ID()
}
return call.ReplyPullImage(imageID)
}
// ImageExists returns bool as to whether the input image exists in local storage

View File

@ -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)