Merge pull request #2264 from larskarlitski/varlink-api

Make varlink API more idiomatic
This commit is contained in:
OpenShift Merge Robot
2019-02-12 16:59:45 +01:00
committed by GitHub
8 changed files with 89 additions and 152 deletions

View File

@ -34,7 +34,7 @@ SELINUXOPT ?= $(shell test -x /usr/sbin/selinuxenabled && selinuxenabled && echo
PACKAGES ?= $(shell $(GO) list -tags "${BUILDTAGS}" ./... | grep -v github.com/containers/libpod/vendor | grep -v e2e | grep -v system )
COMMIT_NO ?= $(shell git rev-parse HEAD 2> /dev/null || true)
GIT_COMMIT ?= $(if $(shell git status --porcelain --untracked-files=no),"${COMMIT_NO}-dirty","${COMMIT_NO}")
GIT_COMMIT ?= $(if $(shell git status --porcelain --untracked-files=no),${COMMIT_NO}-dirty,${COMMIT_NO})
BUILD_INFO ?= $(shell date +%s)
LIBPOD := ${PROJECT}/libpod
LDFLAGS_PODMAN ?= $(LDFLAGS) -X $(LIBPOD).gitCommit=$(GIT_COMMIT) -X $(LIBPOD).buildInfo=$(BUILD_INFO)

View File

@ -83,7 +83,7 @@ func varlinkCmd(c *cliconfig.VarlinkValues) error {
logrus.Infof("varlink service expired (use --timeout to increase session time beyond %d ms, 0 means never timeout)", c.Int64("timeout"))
return nil
default:
return errors.Errorf("unable to start varlink service")
return errors.Wrapf(err, "unable to start varlink service")
}
}

View File

@ -3,23 +3,6 @@
interface io.podman
# Version is the structure returned by GetVersion
type Version (
version: string,
go_version: string,
git_commit: string,
built: int,
os_arch: string,
remote_api_version: int
)
type NotImplemented (
comment: string
)
type StringResponse (
message: string
)
# ContainerChanges describes the return struct for ListContainerChanges
type ContainerChanges (
changed: []string,
@ -40,14 +23,12 @@ type VolumeRemoveOpts (
force: bool
)
# ImageInList describes the structure that is returned in
# ListImages.
type ImageInList (
type Image (
id: string,
parentId: string,
repoTags: []string,
repoDigests: []string,
created: string,
created: string, # as RFC3339
size: int,
virtualSize: int,
containers: int,
@ -58,16 +39,15 @@ type ImageInList (
# ImageHistory describes the returned structure from ImageHistory.
type ImageHistory (
id: string,
created: string,
created: string, # as RFC3339
createdBy: string,
tags: []string,
size: int,
comment: string
)
# ImageSearch is the returned structure for SearchImage. It is returned
# in array form.
type ImageSearch (
# Represents a single search result from SearchImages
type ImageSearchResult (
description: string,
is_official: bool,
is_automated: bool,
@ -75,13 +55,12 @@ type ImageSearch (
star_count: int
)
# ListContainerData is the returned struct for an individual container
type ListContainerData (
type Container (
id: string,
image: string,
imageid: string,
command: []string,
createdat: string,
createdat: string, # as RFC3339
runningfor: string,
status: string,
ports: []ContainerPortMappings,
@ -406,34 +385,29 @@ type Runlabel(
opts: [string]string
)
# Ping provides a response for developers to ensure their varlink setup is working.
# #### Example
# ~~~
# $ varlink call -m unix:/run/podman/io.podman/io.podman.Ping
# {
# "ping": {
# "message": "OK"
# }
# }
# ~~~
method Ping() -> (ping: StringResponse)
# GetVersion returns a Version structure describing the libpod setup on their
# system.
method GetVersion() -> (version: Version)
# GetVersion returns version and build information of the podman service
method GetVersion() -> (
version: string,
go_version: string,
git_commit: string,
built: string, # as RFC3339
os_arch: string,
remote_api_version: int
)
# GetInfo returns a [PodmanInfo](#PodmanInfo) struct that describes podman and its host such as storage stats,
# build information of Podman, and system-wide registries.
method GetInfo() -> (info: PodmanInfo)
# ListContainers returns a list of containers in no particular order. There are
# returned as an array of ListContainerData structs. See also [GetContainer](#GetContainer).
method ListContainers() -> (containers: []ListContainerData)
# ListContainers returns information about all containers.
# See also [GetContainer](#GetContainer).
method ListContainers() -> (containers: []Container)
# GetContainer takes a name or ID of a container and returns single ListContainerData
# structure. A [ContainerNotFound](#ContainerNotFound) error will be returned if the container cannot be found.
# See also [ListContainers](ListContainers) and [InspectContainer](#InspectContainer).
method GetContainer(name: string) -> (container: ListContainerData)
# GetContainer returns information about a single container. If a container
# with the given id doesn't exist, a [ContainerNotFound](#ContainerNotFound)
# error will be returned. See also [ListContainers](ListContainers) and
# [InspectContainer](#InspectContainer).
method GetContainer(id: string) -> (container: Container)
# CreateContainer creates a new container from an image. It uses a [Create](#Create) type for input. The minimum
# input required for CreateContainer is an image name. If the image name is not found, an [ImageNotFound](#ImageNotFound)
@ -521,7 +495,7 @@ method ExportContainer(name: string, path: string) -> (tarfile: string)
method GetContainerStats(name: string) -> (container: ContainerStats)
# This method has not be implemented yet.
method ResizeContainerTty() -> (notimplemented: NotImplemented)
# method ResizeContainerTty() -> (notimplemented: NotImplemented)
# StartContainer starts a created or stopped container. It takes the name or ID of container. It returns
# the container ID once started. If the container cannot be found, a [ContainerNotFound](#ContainerNotFound)
@ -553,10 +527,10 @@ method RestartContainer(name: string, timeout: int) -> (container: string)
method KillContainer(name: string, signal: int) -> (container: string)
# This method has not be implemented yet.
method UpdateContainer() -> (notimplemented: NotImplemented)
# method UpdateContainer() -> (notimplemented: NotImplemented)
# This method has not be implemented yet.
method RenameContainer() -> (notimplemented: NotImplemented)
# method RenameContainer() -> (notimplemented: NotImplemented)
# PauseContainer takes the name or ID of container and pauses it. If the container cannot be found,
# a [ContainerNotFound](#ContainerNotFound) error will be returned; otherwise the ID of the container is returned.
@ -569,7 +543,7 @@ method PauseContainer(name: string) -> (container: string)
method UnpauseContainer(name: string) -> (container: string)
# This method has not be implemented yet.
method AttachToContainer() -> (notimplemented: NotImplemented)
# method AttachToContainer() -> (notimplemented: NotImplemented)
# GetAttachSockets takes the name or ID of an existing container. It returns file paths for two sockets needed
# to properly communicate with a container. The first is the actual I/O socket that the container uses. The
@ -621,13 +595,13 @@ method RemoveContainer(name: string, force: bool) -> (container: string)
# ~~~
method DeleteStoppedContainers() -> (containers: []string)
# ListImages returns an array of ImageInList structures which provide basic information about
# an image currently in storage. See also [InspectImage](InspectImage).
method ListImages() -> (images: []ImageInList)
# ListImages returns information about the images that are currently in storage.
# See also [InspectImage](InspectImage).
method ListImages() -> (images: []Image)
# GetImage returns a single image in an [ImageInList](#ImageInList) struct. You must supply an image name as a string.
# If the image cannot be found, an [ImageNotFound](#ImageNotFound) error will be returned.
method GetImage(name: string) -> (image: ImageInList)
# GetImage returns information about a single image in storage.
# If the image caGetImage returns be found, [ImageNotFound](#ImageNotFound) will be returned.
method GetImage(id: string) -> (image: Image)
# BuildImage takes a [BuildInfo](#BuildInfo) structure and builds an image. At a minimum, you must provide the
# 'dockerfile' and 'tags' options in the BuildInfo structure. It will return a [BuildResponse](#BuildResponse) structure
@ -635,7 +609,7 @@ method GetImage(name: string) -> (image: ImageInList)
method BuildImage(build: BuildInfo) -> (image: BuildResponse)
# This function is not implemented yet.
method CreateImage() -> (notimplemented: NotImplemented)
# method CreateImage() -> (notimplemented: NotImplemented)
# InspectImage takes the name or ID of an image and returns a string respresentation of data associated with the
#image. You must serialize the string into JSON to use it further. An [ImageNotFound](#ImageNotFound) error will
@ -669,10 +643,10 @@ method TagImage(name: string, tagged: string) -> (image: string)
# ~~~
method RemoveImage(name: string, force: bool) -> (image: string)
# SearchImage takes the string of an image name and a limit of searches from each registries to be returned. SearchImage
# will then use a glob-like match to find the image you are searching for. The images are returned in an array of
# ImageSearch structures which contain information about the image as well as its fully-qualified name.
method SearchImage(name: string, limit: int) -> (images: []ImageSearch)
# SearchImages searches available registries for images that contain the
# contents of "query" in their name. If "limit" is given, limits the amount of
# search results per registry.
method SearchImages(query: string, limit: ?int) -> (results: []ImageSearchResult)
# DeleteUnusedImages deletes any images not associated with a container. The IDs of the deleted images are returned
# in a string array.
@ -926,10 +900,10 @@ method UnpausePod(name: string) -> (pod: string)
method RemovePod(name: string, force: bool) -> (pod: string)
# This method has not be implemented yet.
method WaitPod() -> (notimplemented: NotImplemented)
# method WaitPod() -> (notimplemented: NotImplemented)
# This method has not been implemented yet.
method TopPod() -> (notimplemented: NotImplemented)
# method TopPod() -> (notimplemented: NotImplemented)
# GetPodStats takes the name or ID of a pod and returns a pod name and slice of ContainerStats structure which
# contains attributes like memory and cpu usage. If the pod cannot be found, a [PodNotFound](#PodNotFound)
@ -1033,19 +1007,19 @@ method UnmountContainer(name: string, force: bool) -> ()
method ImagesPrune(all: bool) -> (pruned: []string)
# This function is not implemented yet.
method ListContainerPorts(name: string) -> (notimplemented: NotImplemented)
# method ListContainerPorts(name: string) -> (notimplemented: NotImplemented)
# GenerateKube generates a Kubernetes v1 Pod description of a Podman container or pod
# and its containers. The description is in YAML. See also [ReplayKube](ReplayKube).
method GenerateKube() -> (notimplemented: NotImplemented)
# method GenerateKube() -> (notimplemented: NotImplemented)
# GenerateKubeService generates a Kubernetes v1 Service description of a Podman container or pod
# and its containers. The description is in YAML. See also [GenerateKube](GenerateKube).
method GenerateKubeService() -> (notimplemented: NotImplemented)
# method GenerateKubeService() -> (notimplemented: NotImplemented)
# ReplayKube recreates a pod and its containers based on a Kubernetes v1 Pod description (in YAML)
# like that created by GenerateKube. See also [GenerateKube](GenerateKube).
method ReplayKube() -> (notimplemented: NotImplemented)
# method ReplayKube() -> (notimplemented: NotImplemented)
# ContainerConfig returns a container's config in string form. This call is for
# development of Podman only and generally should not be used.
@ -1072,10 +1046,10 @@ method VolumeRemove(options: VolumeRemoveOpts) -> (volumeNames: []string)
# ImageNotFound means the image could not be found by the provided name or ID in local storage.
error ImageNotFound (name: string)
error ImageNotFound (id: string)
# ContainerNotFound means the container could not be found by the provided name or ID in local storage.
error ContainerNotFound (name: string)
error ContainerNotFound (id: string)
# NoContainerRunning means none of the containers requested are running in a command that requires a running container.
error NoContainerRunning ()

View File

@ -6,7 +6,6 @@ import (
"bufio"
"context"
"encoding/json"
"fmt"
"github.com/pkg/errors"
"io"
"os"
@ -112,8 +111,8 @@ func (r *LocalRuntime) GetImages() ([]*ContainerImage, error) {
return newImages, nil
}
func imageInListToContainerImage(i iopodman.ImageInList, name string, runtime *LocalRuntime) (*ContainerImage, error) {
created, err := splitStringDate(i.Created)
func imageInListToContainerImage(i iopodman.Image, name string, runtime *LocalRuntime) (*ContainerImage, error) {
created, err := time.ParseInLocation(time.RFC3339, i.Created, time.UTC)
if err != nil {
return nil, err
}
@ -182,12 +181,6 @@ func (r *LocalRuntime) New(ctx context.Context, name, signaturePolicyPath, authf
return newImage, nil
}
func splitStringDate(d string) (time.Time, error) {
fields := strings.Fields(d)
t := fmt.Sprintf("%sT%sZ", fields[0], fields[1])
return time.ParseInLocation(time.RFC3339Nano, t, time.UTC)
}
// IsParent goes through the layers in the store and checks if i.TopLayer is
// the parent of any other layer in store. Double check that image with that
// layer exists as well.
@ -251,7 +244,7 @@ func (ci *ContainerImage) History(ctx context.Context) ([]*image.History, error)
return nil, err
}
for _, h := range reply {
created, err := splitStringDate(h.Created)
created, err := time.ParseInLocation(time.RFC3339, h.Created, time.UTC)
if err != nil {
return nil, err
}

View File

@ -21,7 +21,7 @@ import (
// ListContainers ...
func (i *LibpodAPI) ListContainers(call iopodman.VarlinkCall) error {
var (
listContainers []iopodman.ListContainerData
listContainers []iopodman.Container
)
containers, err := i.Runtime.GetAllContainers()
@ -44,10 +44,10 @@ func (i *LibpodAPI) ListContainers(call iopodman.VarlinkCall) error {
}
// GetContainer ...
func (i *LibpodAPI) GetContainer(call iopodman.VarlinkCall, name string) error {
ctr, err := i.Runtime.LookupContainer(name)
func (i *LibpodAPI) GetContainer(call iopodman.VarlinkCall, id string) error {
ctr, err := i.Runtime.LookupContainer(id)
if err != nil {
return call.ReplyContainerNotFound(name)
return call.ReplyContainerNotFound(id)
}
opts := shared.PsOptions{
Namespace: true,
@ -247,11 +247,6 @@ func (i *LibpodAPI) GetContainerStats(call iopodman.VarlinkCall, name string) er
return call.ReplyGetContainerStats(cs)
}
// ResizeContainerTty ...
func (i *LibpodAPI) ResizeContainerTty(call iopodman.VarlinkCall) error {
return call.ReplyMethodNotImplemented("ResizeContainerTty")
}
// StartContainer ...
func (i *LibpodAPI) StartContainer(call iopodman.VarlinkCall, name string) error {
ctr, err := i.Runtime.LookupContainer(name)
@ -324,16 +319,6 @@ func (i *LibpodAPI) KillContainer(call iopodman.VarlinkCall, name string, signal
return call.ReplyKillContainer(ctr.ID())
}
// UpdateContainer ...
func (i *LibpodAPI) UpdateContainer(call iopodman.VarlinkCall) error {
return call.ReplyMethodNotImplemented("UpdateContainer")
}
// RenameContainer ...
func (i *LibpodAPI) RenameContainer(call iopodman.VarlinkCall) error {
return call.ReplyMethodNotImplemented("RenameContainer")
}
// PauseContainer ...
func (i *LibpodAPI) PauseContainer(call iopodman.VarlinkCall, name string) error {
ctr, err := i.Runtime.LookupContainer(name)
@ -358,12 +343,6 @@ func (i *LibpodAPI) UnpauseContainer(call iopodman.VarlinkCall, name string) err
return call.ReplyUnpauseContainer(ctr.ID())
}
// AttachToContainer ...
// TODO: DO we also want a different one for websocket?
func (i *LibpodAPI) AttachToContainer(call iopodman.VarlinkCall) error {
return call.ReplyMethodNotImplemented("AttachToContainer")
}
// WaitContainer ...
func (i *LibpodAPI) WaitContainer(call iopodman.VarlinkCall, name string) error {
ctr, err := i.Runtime.LookupContainer(name)

View File

@ -37,7 +37,7 @@ func (i *LibpodAPI) ListImages(call iopodman.VarlinkCall) error {
if err != nil {
return call.ReplyErrorOccurred(fmt.Sprintf("unable to get list of images %q", err))
}
var imageList []iopodman.ImageInList
var imageList []iopodman.Image
for _, image := range images {
labels, _ := image.Labels(getContext())
containers, _ := image.Containers()
@ -52,12 +52,12 @@ func (i *LibpodAPI) ListImages(call iopodman.VarlinkCall) error {
return call.ReplyErrorOccurred(err.Error())
}
i := iopodman.ImageInList{
i := iopodman.Image{
Id: image.ID(),
ParentId: image.Parent,
RepoTags: image.Names(),
RepoDigests: repoDigests,
Created: image.Created().String(),
Created: image.Created().Format(time.RFC3339),
Size: int64(*size),
VirtualSize: image.VirtualSize,
Containers: int64(len(containers)),
@ -69,11 +69,11 @@ func (i *LibpodAPI) ListImages(call iopodman.VarlinkCall) error {
return call.ReplyListImages(imageList)
}
// GetImage returns a single image in the form of a ImageInList
func (i *LibpodAPI) GetImage(call iopodman.VarlinkCall, name string) error {
newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name)
// GetImage returns a single image in the form of a Image
func (i *LibpodAPI) GetImage(call iopodman.VarlinkCall, id string) error {
newImage, err := i.Runtime.ImageRuntime().NewFromLocal(id)
if err != nil {
return call.ReplyImageNotFound(err.Error())
return call.ReplyImageNotFound(id)
}
labels, err := newImage.Labels(getContext())
if err != nil {
@ -92,12 +92,12 @@ func (i *LibpodAPI) GetImage(call iopodman.VarlinkCall, name string) error {
return err
}
il := iopodman.ImageInList{
il := iopodman.Image{
Id: newImage.ID(),
ParentId: newImage.Parent,
RepoTags: newImage.Names(),
RepoDigests: repoDigests,
Created: newImage.Created().String(),
Created: newImage.Created().Format(time.RFC3339),
Size: int64(*size),
VirtualSize: newImage.VirtualSize,
Containers: int64(len(containers)),
@ -276,12 +276,6 @@ func build(runtime *libpod.Runtime, options imagebuildah.BuildOptions, dockerfil
return c
}
// CreateImage ...
// TODO With Pull being added, should we skip Create?
func (i *LibpodAPI) CreateImage(call iopodman.VarlinkCall) error {
return call.ReplyMethodNotImplemented("CreateImage")
}
// 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 {
@ -315,7 +309,7 @@ func (i *LibpodAPI) HistoryImage(call iopodman.VarlinkCall, name string) error {
for _, hist := range history {
imageHistory := iopodman.ImageHistory{
Id: hist.ID,
Created: hist.Created.String(),
Created: hist.Created.Format(time.RFC3339),
CreatedBy: hist.CreatedBy,
Tags: newImage.Names(),
Size: hist.Size,
@ -405,17 +399,21 @@ func (i *LibpodAPI) RemoveImage(call iopodman.VarlinkCall, name string, force bo
return call.ReplyRemoveImage(newImage.ID())
}
// SearchImage searches all registries configured in /etc/containers/registries.conf for an image
// 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) SearchImage(call iopodman.VarlinkCall, name string, limit int64) error {
func (i *LibpodAPI) SearchImages(call iopodman.VarlinkCall, query string, limit *int64) error {
sc := image.GetSystemContext("", "", false)
registries, err := sysreg.GetRegistries()
if err != nil {
return call.ReplyErrorOccurred(fmt.Sprintf("unable to get system registries: %q", err))
}
var imageResults []iopodman.ImageSearch
var imageResults []iopodman.ImageSearchResult
for _, reg := range registries {
results, err := docker.SearchRegistry(getContext(), sc, reg, name, int(limit))
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
@ -426,7 +424,7 @@ func (i *LibpodAPI) SearchImage(call iopodman.VarlinkCall, name string, limit in
return call.ReplyErrorOccurred(err.Error())
}
for _, result := range results {
i := iopodman.ImageSearch{
i := iopodman.ImageSearchResult{
Description: result.Description,
Is_official: result.IsOfficial,
Is_automated: result.IsAutomated,
@ -436,7 +434,7 @@ func (i *LibpodAPI) SearchImage(call iopodman.VarlinkCall, name string, limit in
imageResults = append(imageResults, i)
}
}
return call.ReplySearchImage(imageResults)
return call.ReplySearchImages(imageResults)
}
// DeleteUnusedImages deletes any images that do not have containers associated with it.

View File

@ -3,6 +3,7 @@ package varlinkapi
import (
goruntime "runtime"
"strings"
"time"
"github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod"
@ -15,22 +16,14 @@ func (i *LibpodAPI) GetVersion(call iopodman.VarlinkCall) error {
return err
}
return call.ReplyGetVersion(iopodman.Version{
Remote_api_version: versionInfo.RemoteAPIVersion,
Version: versionInfo.Version,
Go_version: versionInfo.GoVersion,
Git_commit: versionInfo.GitCommit,
Built: versionInfo.Built,
Os_arch: versionInfo.OsArch,
})
}
// Ping returns a simple string "OK" response for clients to make sure
// the service is working.
func (i *LibpodAPI) Ping(call iopodman.VarlinkCall) error {
return call.ReplyPing(iopodman.StringResponse{
Message: "OK",
})
return call.ReplyGetVersion(
versionInfo.Version,
versionInfo.GoVersion,
versionInfo.GitCommit,
time.Unix(versionInfo.Built, 0).Format(time.RFC3339),
versionInfo.OsArch,
versionInfo.RemoteAPIVersion,
)
}
// GetInfo returns details about the podman host and its stores

View File

@ -15,7 +15,7 @@ func getContext() context.Context {
return context.TODO()
}
func makeListContainer(containerID string, batchInfo shared.BatchContainerStruct) iopodman.ListContainerData {
func makeListContainer(containerID string, batchInfo shared.BatchContainerStruct) iopodman.Container {
var (
mounts []iopodman.ContainerMount
ports []iopodman.ContainerPortMappings
@ -56,12 +56,12 @@ func makeListContainer(containerID string, batchInfo shared.BatchContainerStruct
Ipc: ns.IPC,
}
lc := iopodman.ListContainerData{
lc := iopodman.Container{
Id: containerID,
Image: batchInfo.ConConfig.RootfsImageName,
Imageid: batchInfo.ConConfig.RootfsImageID,
Command: batchInfo.ConConfig.Spec.Process.Args,
Createdat: batchInfo.ConConfig.CreatedTime.String(),
Createdat: batchInfo.ConConfig.CreatedTime.Format(time.RFC3339),
Runningfor: time.Since(batchInfo.ConConfig.CreatedTime).String(),
Status: batchInfo.ConState.String(),
Ports: ports,
@ -107,7 +107,7 @@ func makeListPod(pod *libpod.Pod, batchInfo shared.PsOptions) (iopodman.ListPodD
listPodsContainers = append(listPodsContainers, makeListPodContainers(ctr.ID(), batchInfo))
}
listPod := iopodman.ListPodData{
Createdat: pod.CreatedTime().String(),
Createdat: pod.CreatedTime().Format(time.RFC3339),
Id: pod.ID(),
Name: pod.Name(),
Status: status,