Generate varlink API documentation automatically

Using varlink's idl parser, we generate API documentation for the podman
API relying on the .varlink file as the source.

Signed-off-by: baude <bbaude@redhat.com>

Closes: #734
Approved by: baude
This commit is contained in:
baude 2018-05-07 17:09:11 -05:00 committed by Atomic Bot
parent 21ebdb558c
commit 25263558f1
18 changed files with 4125 additions and 1534 deletions

624
API.md Executable file
View File

@ -0,0 +1,624 @@
## Index
[func ListImages() ImageInList](#ListImages)
[func PushImage(name: string, tag: string, tlsverify: bool) string](#PushImage)
[func TagImage(name: string, tagged: string) string](#TagImage)
[func GetContainer(name: string) ListContainerData](#GetContainer)
[func CreateContainer() NotImplemented](#CreateContainer)
[func GetContainerLogs(name: string) []string](#GetContainerLogs)
[func KillContainer(name: string, signal: int) string](#KillContainer)
[func UnpauseContainer(name: string) string](#UnpauseContainer)
[func AttachToContainer() NotImplemented](#AttachToContainer)
[func BuildImage() NotImplemented](#BuildImage)
[func RemoveImage(name: string, force: bool) string](#RemoveImage)
[func ListContainers() ListContainerData](#ListContainers)
[func ResizeContainerTty() NotImplemented](#ResizeContainerTty)
[func UpdateContainer() NotImplemented](#UpdateContainer)
[func RenameContainer() NotImplemented](#RenameContainer)
[func SearchImage(name: string, limit: int) ImageSearch](#SearchImage)
[func StartContainer() NotImplemented](#StartContainer)
[func StopContainer(name: string, timeout: int) string](#StopContainer)
[func RestartContainer(name: string, timeout: int) string](#RestartContainer)
[func DeleteUnusedImages() []string](#DeleteUnusedImages)
[func Ping() StringResponse](#Ping)
[func GetVersion() Version](#GetVersion)
[func InspectContainer(name: string) string](#InspectContainer)
[func ListContainerChanges(name: string) ContainerChanges](#ListContainerChanges)
[func ExportImage(name: string, destination: string, compress: bool) string](#ExportImage)
[func CreateFromContainer() NotImplemented](#CreateFromContainer)
[func RemoveContainer(name: string, force: bool) string](#RemoveContainer)
[func CreateImage() NotImplemented](#CreateImage)
[func InspectImage(name: string) string](#InspectImage)
[func HistoryImage(name: string) ImageHistory](#HistoryImage)
[func ExportContainer(name: string, path: string) string](#ExportContainer)
[func WaitContainer(name: string) int](#WaitContainer)
[func ImportImage(source: string, reference: string, message: string, changes: []string) string](#ImportImage)
[func PullImage(name: string) string](#PullImage)
[func DeleteStoppedContainers() []string](#DeleteStoppedContainers)
[func ListContainerProcesses(name: string, opts: []string) []string](#ListContainerProcesses)
[func GetContainerStats(name: string) ContainerStats](#GetContainerStats)
[func PauseContainer(name: string) string](#PauseContainer)
[type ContainerMount](#ContainerMount)
[type ImageHistory](#ImageHistory)
[type ImageSearch](#ImageSearch)
[type StringResponse](#StringResponse)
[type ContainerChanges](#ContainerChanges)
[type ImageInList](#ImageInList)
[type ListContainerData](#ListContainerData)
[type ContainerStats](#ContainerStats)
[type ContainerPortMappings](#ContainerPortMappings)
[type Version](#Version)
[type NotImplemented](#NotImplemented)
[type ContainerNameSpace](#ContainerNameSpace)
[error ErrorOccurred](#ErrorOccurred)
[error RuntimeError](#RuntimeError)
[error ImageNotFound](#ImageNotFound)
[error ContainerNotFound](#ContainerNotFound)
## Methods
### <a name="ListImages"></a>func ListImages
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method ListImages() [ImageInList](#ImageInList)</div>
ListImages returns an array of ImageInList structures which provide basic information about
an image currenly in storage. See also [InspectImage](InspectImage).
### <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>
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. 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.
### <a name="TagImage"></a>func TagImage
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method TagImage(name: [string](https://godoc.org/builtin#string), tagged: [string](https://godoc.org/builtin#string)) [string](https://godoc.org/builtin#string)</div>
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.
### <a name="GetContainer"></a>func GetContainer
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method GetContainer(name: [string](https://godoc.org/builtin#string)) [ListContainerData](#ListContainerData)</div>
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).
### <a name="CreateContainer"></a>func CreateContainer
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method CreateContainer() [NotImplemented](#NotImplemented)</div>
This method has not been implemented yet.
### <a name="GetContainerLogs"></a>func GetContainerLogs
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method GetContainerLogs(name: [string](https://godoc.org/builtin#string)) [[]string](#[]string)</div>
GetContainerLogs takes a name or ID of a container and returns the logs of that container.
If the container cannot be found, a [ContainerNotFound](#ContainerNotFound) error will be returned.
The container logs are returned as an array of strings. GetContainerLogs will honor the streaming
capability of varlink if the client invokes it.
### <a name="KillContainer"></a>func KillContainer
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method KillContainer(name: [string](https://godoc.org/builtin#string), signal: [int](https://godoc.org/builtin#int)) [string](https://godoc.org/builtin#string)</div>
KillContainer takes the name or ID of a container as well as a signal to be applied to the container. Once the
container has been killed, the container's ID is returned. If the container cannot be found, a
[ContainerNotFound](#ContainerNotFound) error is returned. See also [StopContainer](StopContainer).
### <a name="UnpauseContainer"></a>func UnpauseContainer
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method UnpauseContainer(name: [string](https://godoc.org/builtin#string)) [string](https://godoc.org/builtin#string)</div>
UnpauseContainer takes the name or ID of container and unpauses a paused container. If the container cannot be
found, a [ContainerNotFound](#ContainerNotFound) error will be returned; otherwise the ID of the container is returned.
See also [PauseContainer](PauseContainer).
### <a name="AttachToContainer"></a>func AttachToContainer
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method AttachToContainer() [NotImplemented](#NotImplemented)</div>
This method has not be implemented yet.
### <a name="BuildImage"></a>func BuildImage
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method BuildImage() [NotImplemented](#NotImplemented)</div>
This function is not implemented yet.
### <a name="RemoveImage"></a>func RemoveImage
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method RemoveImage(name: [string](https://godoc.org/builtin#string), force: [bool](https://godoc.org/builtin#bool)) [string](https://godoc.org/builtin#string)</div>
RemoveImage takes the name or ID of an image as well as a booleon that determines if containers using that image
should be deleted. If the image cannot be found, an [ImageNotFound](#ImageNotFound) error will be returned. The
ID of the removed image is returned when complete. See also [DeleteUnusedImages](DeleteUnusedImages).
#### Example
~~~
varlink call -m unix:/run/io.projectatomic.podman/io.projectatomic.podman.RemoveImage '{"name": "registry.fedoraproject.org/fedora", "force": true}'
{
"image": "426866d6fa419873f97e5cbd320eeb22778244c1dfffa01c944db3114f55772e"
}
~~~
### <a name="ListContainers"></a>func ListContainers
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method ListContainers() [ListContainerData](#ListContainerData)</div>
ListContainers returns a list of containers in no particular order. There are
returned as an array of ListContainerData structs. See also [GetContainer](#GetContainer).
### <a name="ResizeContainerTty"></a>func ResizeContainerTty
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method ResizeContainerTty() [NotImplemented](#NotImplemented)</div>
This method has not be implemented yet.
### <a name="UpdateContainer"></a>func UpdateContainer
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method UpdateContainer() [NotImplemented](#NotImplemented)</div>
This method has not be implemented yet.
### <a name="RenameContainer"></a>func RenameContainer
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method RenameContainer() [NotImplemented](#NotImplemented)</div>
This method has not be implemented yet.
### <a name="SearchImage"></a>func SearchImage
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method SearchImage(name: [string](https://godoc.org/builtin#string), limit: [int](https://godoc.org/builtin#int)) [ImageSearch](#ImageSearch)</div>
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.
### <a name="StartContainer"></a>func StartContainer
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method StartContainer() [NotImplemented](#NotImplemented)</div>
This method has not be implemented yet.
### <a name="StopContainer"></a>func StopContainer
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method StopContainer(name: [string](https://godoc.org/builtin#string), timeout: [int](https://godoc.org/builtin#int)) [string](https://godoc.org/builtin#string)</div>
StopContainer stops a container given a timeout. It takes the name or ID of a container as well as a
timeout value. The timeout value the time before a forceable stop to the container is applied. It
returns the container ID once stopped. If the container cannot be found, a [ContainerNotFound](#ContainerNotFound)
error will be returned instead. See also [KillContainer](KillContainer).
#### Error
~~~
$ varlink call -m unix:/run/io.projectatomic.podman/io.projectatomic.podman.StopContainer '{"name": "135d71b9495f", "timeout": 5}'
{
"container": "135d71b9495f7c3967f536edad57750bfdb569336cd107d8aabab45565ffcfb6"
}
~~~
### <a name="RestartContainer"></a>func RestartContainer
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method RestartContainer(name: [string](https://godoc.org/builtin#string), timeout: [int](https://godoc.org/builtin#int)) [string](https://godoc.org/builtin#string)</div>
RestartContainer will restart a running container given a container name or ID and timeout value. The timeout
value is the time before a forceable stop is used to stop the container. If the container cannot be found by
name or ID, a [ContainerNotFound](#ContainerNotFound) error will be returned; otherwise, the ID of the
container will be returned.
### <a name="DeleteUnusedImages"></a>func DeleteUnusedImages
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method DeleteUnusedImages() [[]string](#[]string)</div>
DeleteUnusedImages deletes any images not associated with a container. The IDs of the deleted images are returned
in a string array.
### <a name="Ping"></a>func Ping
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method Ping() [StringResponse](#StringResponse)</div>
Ping provides a response for developers to ensure their varlink setup is working.
#### Example
~~~
$ varlink call -m unix:/run/io.projectatomic.podman/io.projectatomic.podman.Ping
{
"ping": {
"message": "OK"
}
}
~~~
### <a name="GetVersion"></a>func GetVersion
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method GetVersion() [Version](#Version)</div>
GetVersion returns a Version structure describing the libpod setup on their
system.
### <a name="InspectContainer"></a>func InspectContainer
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method InspectContainer(name: [string](https://godoc.org/builtin#string)) [string](https://godoc.org/builtin#string)</div>
InspectContainer data takes a name or ID of a container returns the inspection
data in string format. You can then serialize the string into JSON. A [ContainerNotFound](#ContainerNotFound)
error will be returned if the container cannot be found. See also [InspectImage](#InspectImage).
### <a name="ListContainerChanges"></a>func ListContainerChanges
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method ListContainerChanges(name: [string](https://godoc.org/builtin#string)) [ContainerChanges](#ContainerChanges)</div>
ListContainerChanges takes a name or ID of a container and returns changes between the container and
its base image. It returns a struct of changed, deleted, and added path names. If the
container cannot be found, a [ContainerNotFound](#ContainerNotFound) error will be returned.
### <a name="ExportImage"></a>func ExportImage
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method ExportImage(name: [string](https://godoc.org/builtin#string), destination: [string](https://godoc.org/builtin#string), compress: [bool](https://godoc.org/builtin#bool)) [string](https://godoc.org/builtin#string)</div>
ExportImage takes the name or ID of an image and exports it to a destination like a tarball. There is also
a booleon option to force compression. Upon completion, the ID of the image is returned. If the image cannot
be found in local storage, an [ImageNotFound](#ImageNotFound) error will be returned. See also [ImportImage](ImportImage).
### <a name="CreateFromContainer"></a>func CreateFromContainer
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method CreateFromContainer() [NotImplemented](#NotImplemented)</div>
This method is not implemented.
### <a name="RemoveContainer"></a>func RemoveContainer
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method RemoveContainer(name: [string](https://godoc.org/builtin#string), force: [bool](https://godoc.org/builtin#bool)) [string](https://godoc.org/builtin#string)</div>
RemoveContainer takes requires the name or ID of container as well a boolean representing whether a running
container can be stopped and removed. Upon sucessful removal of the container, its ID is returned. If the
container cannot be found by name or ID, an [ContainerNotFound](#ContainerNotFound) error will be returned.
#### Error
~~~
$ varlink call -m unix:/run/io.projectatomic.podman/io.projectatomic.podman.RemoveContainer '{"name": "62f4fd98cb57"}'
{
"container": "62f4fd98cb57f529831e8f90610e54bba74bd6f02920ffb485e15376ed365c20"
}
~~~
### <a name="CreateImage"></a>func CreateImage
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method CreateImage() [NotImplemented](#NotImplemented)</div>
This function is not implemented yet.
### <a name="InspectImage"></a>func InspectImage
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method InspectImage(name: [string](https://godoc.org/builtin#string)) [string](https://godoc.org/builtin#string)</div>
InspectImage takes the name or ID of an image and returns a string respresentation of data associated with the
mage. You must serialize the string into JSON to use it further. An [ImageNotFound](#ImageNotFound) error will
be returned if the image cannot be found.
### <a name="HistoryImage"></a>func HistoryImage
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method HistoryImage(name: [string](https://godoc.org/builtin#string)) [ImageHistory](#ImageHistory)</div>
HistoryImage takes the name or ID of an image and returns information about its history and layers. The returned
history is in the form of an array of ImageHistory structures. If the image cannot be found, an
[ImageNotFound](#ImageNotFound) error is returned.
### <a name="ExportContainer"></a>func ExportContainer
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method ExportContainer(name: [string](https://godoc.org/builtin#string), path: [string](https://godoc.org/builtin#string)) [string](https://godoc.org/builtin#string)</div>
ExportContainer creates an image from a container. It takes the name or ID of a container and a
path representing the target tarfile. If the container cannot be found, a [ContainerNotFound](#ContainerNotFound)
error will be returned.
The return value is the written tarfile.
### <a name="WaitContainer"></a>func WaitContainer
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method WaitContainer(name: [string](https://godoc.org/builtin#string)) [int](https://godoc.org/builtin#int)</div>
WaitContainer takes the name of ID of a container and waits until the container stops. Upon stopping, the return
code of the container is returned. If the container container cannot be found by ID or name,
a [ContainerNotFound](#ContainerNotFound) error is returned.
### <a name="ImportImage"></a>func ImportImage
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method ImportImage(source: [string](https://godoc.org/builtin#string), reference: [string](https://godoc.org/builtin#string), message: [string](https://godoc.org/builtin#string), changes: [[]string](#[]string)) [string](https://godoc.org/builtin#string)</div>
ImportImage imports an image from a source (like tarball) into local storage. The image can have additional
descriptions added to it using the message and changes options. See also [ExportImage](ExportImage).
### <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>
PullImage pulls an image from a repository to local storage. After the pull is successful, the ID of the image
is returned.
#### Example
~~~
$ varlink call -m unix:/run/io.projectatomic.podman/io.projectatomic.podman.PullImage '{"name": "registry.fedoraproject.org/fedora"}'
{
"id": "426866d6fa419873f97e5cbd320eeb22778244c1dfffa01c944db3114f55772e"
}
~~~
### <a name="DeleteStoppedContainers"></a>func DeleteStoppedContainers
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method DeleteStoppedContainers() [[]string](#[]string)</div>
DeleteStoppedContainers will delete all containers that are not running. It will return a list the deleted
container IDs. See also [RemoveContainer](RemoveContainer).
### <a name="ListContainerProcesses"></a>func ListContainerProcesses
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method ListContainerProcesses(name: [string](https://godoc.org/builtin#string), opts: [[]string](#[]string)) [[]string](#[]string)</div>
ListContainerProcesses takes a name or ID of a container and returns the processes
running inside the container as array of strings. It will accept an array of string
arguements that represent ps options. If the container cannot be found, a [ContainerNotFound](#ContainerNotFound)
error will be returned.
#### Example
~~~
$ varlink call -m unix:/run/io.projectatomic.podman/io.projectatomic.podman.ListContainerProcesses '{"name": "135d71b9495f", "opts": []}'
{
"container": [
" UID PID PPID C STIME TTY TIME CMD",
" 0 21220 21210 0 09:05 pts/0 00:00:00 /bin/sh",
" 0 21232 21220 0 09:05 pts/0 00:00:00 top",
" 0 21284 21220 0 09:05 pts/0 00:00:00 vi /etc/hosts"
]
}
~~~
### <a name="GetContainerStats"></a>func GetContainerStats
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method GetContainerStats(name: [string](https://godoc.org/builtin#string)) [ContainerStats](#ContainerStats)</div>
GetContainerStats takes the name or ID of a container and returns a single ContainerStats structure which
contains attributes like memory and cpu usage. If the container cannot be found, a
[ContainerNotFound](#ContainerNotFound) error will be returned.
#### Example
~~~
$ varlink call -m unix:/run/io.projectatomic.podman/io.projectatomic.podman.GetContainerStats '{"name": "c33e4164f384"}'
{
"container": {
"block_input": 0,
"block_output": 0,
"cpu": 2.571123918839990154678e-08,
"cpu_nano": 49037378,
"id": "c33e4164f384aa9d979072a63319d66b74fd7a128be71fa68ede24f33ec6cfee",
"mem_limit": 33080606720,
"mem_perc": 2.166828456524753747370e-03,
"mem_usage": 716800,
"name": "competent_wozniak",
"net_input": 768,
"net_output": 5910,
"pids": 1,
"system_nano": 10000000
}
}
~~~
### <a name="PauseContainer"></a>func PauseContainer
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method PauseContainer(name: [string](https://godoc.org/builtin#string)) [string](https://godoc.org/builtin#string)</div>
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.
See also [UnpauseContainer](UnpauseContainer).
## Types
### <a name="ContainerMount"></a>type ContainerMount
ContainerMount describes the struct for mounts in a container
destination [string](https://godoc.org/builtin#string)
type [string](https://godoc.org/builtin#string)
source [string](https://godoc.org/builtin#string)
options [[]string](#[]string)
### <a name="ImageHistory"></a>type ImageHistory
ImageHistory describes the returned structure from ImageHistory.
id [string](https://godoc.org/builtin#string)
created [string](https://godoc.org/builtin#string)
createdBy [string](https://godoc.org/builtin#string)
tags [[]string](#[]string)
size [int](https://godoc.org/builtin#int)
comment [string](https://godoc.org/builtin#string)
### <a name="ImageSearch"></a>type ImageSearch
ImageSearch is the returned structure for SearchImage. It is returned
in arrary form.
description [string](https://godoc.org/builtin#string)
is_official [bool](https://godoc.org/builtin#bool)
is_automated [bool](https://godoc.org/builtin#bool)
name [string](https://godoc.org/builtin#string)
star_count [int](https://godoc.org/builtin#int)
### <a name="StringResponse"></a>type StringResponse
message [string](https://godoc.org/builtin#string)
### <a name="ContainerChanges"></a>type ContainerChanges
ContainerChanges describes the return struct for ListContainerChanges
changed [[]string](#[]string)
added [[]string](#[]string)
deleted [[]string](#[]string)
### <a name="ImageInList"></a>type ImageInList
ImageInList describes the structure that is returned in
ListImages.
id [string](https://godoc.org/builtin#string)
parentId [string](https://godoc.org/builtin#string)
repoTags [[]string](#[]string)
repoDigests [[]string](#[]string)
created [string](https://godoc.org/builtin#string)
size [int](https://godoc.org/builtin#int)
virtualSize [int](https://godoc.org/builtin#int)
containers [int](https://godoc.org/builtin#int)
labels [map[string]](#map[string])
### <a name="ListContainerData"></a>type ListContainerData
ListContainer is the returned struct for an individual container
id [string](https://godoc.org/builtin#string)
image [string](https://godoc.org/builtin#string)
imageid [string](https://godoc.org/builtin#string)
command [[]string](#[]string)
createdat [string](https://godoc.org/builtin#string)
runningfor [string](https://godoc.org/builtin#string)
status [string](https://godoc.org/builtin#string)
ports [ContainerPortMappings](#ContainerPortMappings)
rootfssize [int](https://godoc.org/builtin#int)
rwsize [int](https://godoc.org/builtin#int)
names [string](https://godoc.org/builtin#string)
labels [map[string]](#map[string])
mounts [ContainerMount](#ContainerMount)
containerrunning [bool](https://godoc.org/builtin#bool)
namespaces [ContainerNameSpace](#ContainerNameSpace)
### <a name="ContainerStats"></a>type ContainerStats
ContainerStats is the return struct for the stats of a container
id [string](https://godoc.org/builtin#string)
name [string](https://godoc.org/builtin#string)
cpu [float](https://golang.org/src/builtin/builtin.go#L58)
cpu_nano [int](https://godoc.org/builtin#int)
system_nano [int](https://godoc.org/builtin#int)
mem_usage [int](https://godoc.org/builtin#int)
mem_limit [int](https://godoc.org/builtin#int)
mem_perc [float](https://golang.org/src/builtin/builtin.go#L58)
net_input [int](https://godoc.org/builtin#int)
net_output [int](https://godoc.org/builtin#int)
block_output [int](https://godoc.org/builtin#int)
block_input [int](https://godoc.org/builtin#int)
pids [int](https://godoc.org/builtin#int)
### <a name="ContainerPortMappings"></a>type ContainerPortMappings
ContainerPortMappings describes the struct for portmappings in an existing container
host_port [string](https://godoc.org/builtin#string)
host_ip [string](https://godoc.org/builtin#string)
protocol [string](https://godoc.org/builtin#string)
container_port [string](https://godoc.org/builtin#string)
### <a name="Version"></a>type Version
Version is the structure returned by GetVersion
version [string](https://godoc.org/builtin#string)
go_version [string](https://godoc.org/builtin#string)
git_commit [string](https://godoc.org/builtin#string)
built [int](https://godoc.org/builtin#int)
os_arch [string](https://godoc.org/builtin#string)
### <a name="NotImplemented"></a>type NotImplemented
comment [string](https://godoc.org/builtin#string)
### <a name="ContainerNameSpace"></a>type ContainerNameSpace
ContainerNamespace describes the namespace structure for an existing container
user [string](https://godoc.org/builtin#string)
uts [string](https://godoc.org/builtin#string)
pidns [string](https://godoc.org/builtin#string)
pid [string](https://godoc.org/builtin#string)
cgroup [string](https://godoc.org/builtin#string)
net [string](https://godoc.org/builtin#string)
mnt [string](https://godoc.org/builtin#string)
ipc [string](https://godoc.org/builtin#string)
## Errors
### <a name="ErrorOccurred"></a>type ErrorOccurred
ErrorOccurred is a generic error for an error that occurs during the execution. The actual error message
is includes as part of the error's text.
### <a name="RuntimeError"></a>type RuntimeError
RuntimeErrors generally means a runtime could not be found or gotten.
### <a name="ImageNotFound"></a>type ImageNotFound
ImageNotFound means the image could not be found by the provided name or ID in local storage.
### <a name="ContainerNotFound"></a>type ContainerNotFound
ContainerNotFound means the container could not be found by the provided name or ID in local storage.

View File

@ -87,7 +87,7 @@ test/copyimg/copyimg: .gopathok $(wildcard test/copyimg/*.go)
test/checkseccomp/checkseccomp: .gopathok $(wildcard test/checkseccomp/*.go)
$(GO) build $(LDFLAGS) -tags "$(BUILDTAGS) containers_image_ostree_stub" -o $@ $(PROJECT)/test/checkseccomp
podman: .gopathok $(shell hack/find-godeps.sh $(GOPKGDIR) cmd/podman $(PROJECT)) varlink_generate
podman: .gopathok $(shell hack/find-godeps.sh $(GOPKGDIR) cmd/podman $(PROJECT)) varlink_generate varlink_api_generate
$(GO) build -i $(LDFLAGS_PODMAN) -tags "$(BUILDTAGS)" -o bin/$@ $(PROJECT)/cmd/podman
clean:
@ -251,6 +251,7 @@ install.tools: .install.gitvalidation .install.gometalinter .install.md2man
fi
varlink_generate: .gopathok cmd/podman/varlink/ioprojectatomicpodman.go
varlink_api_generate: .gopathok API.md
.PHONY: install.libseccomp.sudo
install.libseccomp.sudo:
@ -262,6 +263,9 @@ install.libseccomp.sudo:
cmd/podman/varlink/ioprojectatomicpodman.go: cmd/podman/varlink/io.projectatomic.podman.varlink
$(GO) generate ./cmd/podman/varlink/...
API.md: cmd/podman/varlink/io.projectatomic.podman.varlink
$(GO) generate ./docs/...
validate: gofmt .gitvalidation
.PHONY: \

View File

@ -47,6 +47,9 @@ showing the commands in use.
Useful information for ops and dev transfer as it relates to infrastructure that utilizes Podman. This page
includes tables showing Docker commands and their Podman equivalent commands.
**[Podman API](/API.md)**
Documentation on the Podman API using varlink.
**[Tutorials](docs/tutorials)**
Tutorials on the Podman utility.

View File

@ -18,6 +18,12 @@ type NotImplemented (
type StringResponse (
message: string
)
# ContainerChanges describes the return struct for ListContainerChanges
type ContainerChanges (
changed: []string,
added: []string,
deleted: []string
)
# ImageInList describes the structure that is returned in
# ListImages.
@ -117,54 +123,254 @@ type ContainerNameSpace (
ipc: string
)
# System
# Ping provides a response for developers to ensure their varlink setup is working.
# #### Example
# ~~~
# $ varlink call -m unix:/run/io.projectatomic.podman/io.projectatomic.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)
# Containers
# 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)
# 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)
# This method has not been implemented yet.
method CreateContainer() -> (notimplemented: NotImplemented)
# InspectContainer data takes a name or ID of a container returns the inspection
# data in string format. You can then serialize the string into JSON. A [ContainerNotFound](#ContainerNotFound)
# error will be returned if the container cannot be found. See also [InspectImage](#InspectImage).
method InspectContainer(name: string) -> (container: string)
# ListContainerProcesses takes a name or ID of a container and returns the processes
# running inside the container as array of strings. It will accept an array of string
# arguements that represent ps options. If the container cannot be found, a [ContainerNotFound](#ContainerNotFound)
# error will be returned.
# #### Example
# ~~~
# $ varlink call -m unix:/run/io.projectatomic.podman/io.projectatomic.podman.ListContainerProcesses '{"name": "135d71b9495f", "opts": []}'
# {
# "container": [
# " UID PID PPID C STIME TTY TIME CMD",
# " 0 21220 21210 0 09:05 pts/0 00:00:00 /bin/sh",
# " 0 21232 21220 0 09:05 pts/0 00:00:00 top",
# " 0 21284 21220 0 09:05 pts/0 00:00:00 vi /etc/hosts"
# ]
# }
# ~~~
method ListContainerProcesses(name: string, opts: []string) -> (container: []string)
# GetContainerLogs takes a name or ID of a container and returns the logs of that container.
# If the container cannot be found, a [ContainerNotFound](#ContainerNotFound) error will be returned.
# The container logs are returned as an array of strings. GetContainerLogs will honor the streaming
# capability of varlink if the client invokes it.
method GetContainerLogs(name: string) -> (container: []string)
method ListContainerChanges(name: string) -> (container: [string]string)
# ListContainerChanges takes a name or ID of a container and returns changes between the container and
# its base image. It returns a struct of changed, deleted, and added path names. If the
# container cannot be found, a [ContainerNotFound](#ContainerNotFound) error will be returned.
method ListContainerChanges(name: string) -> (container: ContainerChanges)
# ExportContainer creates an image from a container. It takes the name or ID of a container and a
# path representing the target tarfile. If the container cannot be found, a [ContainerNotFound](#ContainerNotFound)
# error will be returned.
# The return value is the written tarfile.
method ExportContainer(name: string, path: string) -> (tarfile: string)
# GetContainerStats takes the name or ID of a container and returns a single ContainerStats structure which
# contains attributes like memory and cpu usage. If the container cannot be found, a
# [ContainerNotFound](#ContainerNotFound) error will be returned.
# #### Example
# ~~~
# $ varlink call -m unix:/run/io.projectatomic.podman/io.projectatomic.podman.GetContainerStats '{"name": "c33e4164f384"}'
# {
# "container": {
# "block_input": 0,
# "block_output": 0,
# "cpu": 2.571123918839990154678e-08,
# "cpu_nano": 49037378,
# "id": "c33e4164f384aa9d979072a63319d66b74fd7a128be71fa68ede24f33ec6cfee",
# "mem_limit": 33080606720,
# "mem_perc": 2.166828456524753747370e-03,
# "mem_usage": 716800,
# "name": "competent_wozniak",
# "net_input": 768,
# "net_output": 5910,
# "pids": 1,
# "system_nano": 10000000
# }
# }
# ~~~
method GetContainerStats(name: string) -> (container: ContainerStats)
# This method has not be implemented yet.
method ResizeContainerTty() -> (notimplemented: NotImplemented)
# This method has not be implemented yet.
method StartContainer() -> (notimplemented: NotImplemented)
# StopContainer stops a container given a timeout. It takes the name or ID of a container as well as a
# timeout value. The timeout value the time before a forceable stop to the container is applied. It
# returns the container ID once stopped. If the container cannot be found, a [ContainerNotFound](#ContainerNotFound)
# error will be returned instead. See also [KillContainer](KillContainer).
# #### Error
# ~~~
# $ varlink call -m unix:/run/io.projectatomic.podman/io.projectatomic.podman.StopContainer '{"name": "135d71b9495f", "timeout": 5}'
# {
# "container": "135d71b9495f7c3967f536edad57750bfdb569336cd107d8aabab45565ffcfb6"
# }
# ~~~
method StopContainer(name: string, timeout: int) -> (container: string)
# RestartContainer will restart a running container given a container name or ID and timeout value. The timeout
# value is the time before a forceable stop is used to stop the container. If the container cannot be found by
# name or ID, a [ContainerNotFound](#ContainerNotFound) error will be returned; otherwise, the ID of the
# container will be returned.
method RestartContainer(name: string, timeout: int) -> (container: string)
# KillContainer takes the name or ID of a container as well as a signal to be applied to the container. Once the
# container has been killed, the container's ID is returned. If the container cannot be found, a
# [ContainerNotFound](#ContainerNotFound) error is returned. See also [StopContainer](StopContainer).
method KillContainer(name: string, signal: int) -> (container: string)
# This method has not be implemented yet.
method UpdateContainer() -> (notimplemented: NotImplemented)
# This method has not be implemented yet.
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.
# See also [UnpauseContainer](UnpauseContainer).
method PauseContainer(name: string) -> (container: string)
# UnpauseContainer takes the name or ID of container and unpauses a paused container. If the container cannot be
# found, a [ContainerNotFound](#ContainerNotFound) error will be returned; otherwise the ID of the container is returned.
# See also [PauseContainer](PauseContainer).
method UnpauseContainer(name: string) -> (container: string)
# This method has not be implemented yet.
method AttachToContainer() -> (notimplemented: NotImplemented)
# WaitContainer takes the name of ID of a container and waits until the container stops. Upon stopping, the return
# code of the container is returned. If the container container cannot be found by ID or name,
# a [ContainerNotFound](#ContainerNotFound) error is returned.
method WaitContainer(name: string) -> (exitcode: int)
# RemoveContainer takes requires the name or ID of container as well a boolean representing whether a running
# container can be stopped and removed. Upon sucessful removal of the container, its ID is returned. If the
# container cannot be found by name or ID, an [ContainerNotFound](#ContainerNotFound) error will be returned.
# #### Error
# ~~~
# $ varlink call -m unix:/run/io.projectatomic.podman/io.projectatomic.podman.RemoveContainer '{"name": "62f4fd98cb57"}'
# {
# "container": "62f4fd98cb57f529831e8f90610e54bba74bd6f02920ffb485e15376ed365c20"
# }
# ~~~
method RemoveContainer(name: string, force: bool) -> (container: string)
# DeleteStoppedContainers will delete all containers that are not running. It will return a list the deleted
# container IDs. See also [RemoveContainer](RemoveContainer).
method DeleteStoppedContainers() -> (containers: []string)
# Images
# ListImages returns an array of ImageInList structures which provide basic information about
# an image currenly in storage. See also [InspectImage](InspectImage).
method ListImages() -> (images: []ImageInList)
# This function is not implemented yet.
method BuildImage() -> (notimplemented: NotImplemented)
# This function is not implemented yet.
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
# be returned if the image cannot be found.
method InspectImage(name: string) -> (image: string)
# HistoryImage takes the name or ID of an image and returns information about its history and layers. The returned
# history is in the form of an array of ImageHistory structures. If the image cannot be found, an
# [ImageNotFound](#ImageNotFound) error is returned.
method HistoryImage(name: string) -> (history: []ImageHistory)
method PushImage(name: string, tag: string, tlsverify: bool) -> ()
method TagImage(name: string, tagged: string) -> ()
# 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. 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)
# 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.
method TagImage(name: string, tagged: string) -> (image: string)
# RemoveImage takes the name or ID of an image as well as a booleon that determines if containers using that image
# should be deleted. If the image cannot be found, an [ImageNotFound](#ImageNotFound) error will be returned. The
# ID of the removed image is returned when complete. See also [DeleteUnusedImages](DeleteUnusedImages).
# #### Example
# ~~~
# varlink call -m unix:/run/io.projectatomic.podman/io.projectatomic.podman.RemoveImage '{"name": "registry.fedoraproject.org/fedora", "force": true}'
# {
# "image": "426866d6fa419873f97e5cbd320eeb22778244c1dfffa01c944db3114f55772e"
# }
# ~~~
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)
# DeleteUnusedImages deletes any images not associated with a container. The IDs of the deleted images are returned
# in a string array.
method DeleteUnusedImages() -> (images: []string)
# This method is not implemented.
method CreateFromContainer() -> (notimplemented: NotImplemented)
# ImportImage imports an image from a source (like tarball) into local storage. The image can have additional
# descriptions added to it using the message and changes options. See also [ExportImage](ExportImage).
method ImportImage(source: string, reference: string, message: string, changes: []string) -> (image: string)
method ExportImage(name: string, destination: string, compress: bool) -> ()
# ExportImage takes the name or ID of an image and exports it to a destination like a tarball. There is also
# a booleon option to force compression. Upon completion, the ID of the image is returned. If the image cannot
# be found in local storage, an [ImageNotFound](#ImageNotFound) error will be returned. See also [ImportImage](ImportImage).
method ExportImage(name: string, destination: string, compress: bool) -> (image: string)
# PullImage pulls an image from a repository to local storage. After the pull is successful, the ID of the image
# is returned.
# #### Example
# ~~~
# $ varlink call -m unix:/run/io.projectatomic.podman/io.projectatomic.podman.PullImage '{"name": "registry.fedoraproject.org/fedora"}'
# {
# "id": "426866d6fa419873f97e5cbd320eeb22778244c1dfffa01c944db3114f55772e"
# }
# ~~~
method PullImage(name: string) -> (id: string)
# Something failed
error ActionFailed (reason: string)
# ImageNotFound means the image could not be found by the provided name or ID in local storage.
error ImageNotFound (name: string)
# ContainerNotFound means the container could not be found by the provided name or ID in local storage.
error ContainerNotFound (name: string)
# ErrorOccurred is a generic error for an error that occurs during the execution. The actual error message
# is includes as part of the error's text.
error ErrorOccurred (reason: string)
# RuntimeErrors generally means a runtime could not be found or gotten.
error RuntimeError (reason: string)

File diff suppressed because it is too large Load Diff

3
docs/generate.go Normal file
View File

@ -0,0 +1,3 @@
package docs
//go:generate go run varlink/apidoc.go ../cmd/podman/varlink/io.projectatomic.podman.varlink ../API.md

248
docs/varlink/apidoc.go Normal file
View File

@ -0,0 +1,248 @@
package main
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"strings"
"github.com/varlink/go/varlink/idl"
)
func readFileToString(path string) (string, error) {
content, err := ioutil.ReadFile(path)
if err != nil {
return "", err
}
return string(content), nil
}
func exit(err error) {
fmt.Println(err.Error())
os.Exit(1)
}
func typeToString(input *idl.Type) string {
switch input.Kind {
case idl.TypeString:
return "string"
case idl.TypeBool:
return "bool"
case idl.TypeFloat:
return "float"
case idl.TypeArray:
result := input.ElementType.Alias
if result == "" {
return fmt.Sprintf("[]%s", typeToString(input.ElementType))
}
return result
case idl.TypeAlias:
return input.Alias
case idl.TypeMap:
return "map[string]"
case idl.TypeInt:
return "int"
}
return ""
}
func typeToLink(input string) string {
switch input {
case "string":
return "https://godoc.org/builtin#string"
case "int":
return "https://godoc.org/builtin#int"
case "bool":
return "https://godoc.org/builtin#bool"
case "float":
return "https://golang.org/src/builtin/builtin.go#L58"
default:
return fmt.Sprintf("#%s", input)
}
}
type funcArgs struct {
paramName string
paramKind string
}
type funcDescriber struct {
Name string
inputParams []funcArgs
returnParams []funcArgs
doc string
}
type typeAttrs struct {
Name string
AttrType string
}
type typeDescriber struct {
Name string
doc string
Attrs []typeAttrs
}
type err struct {
Name string
doc string
}
// collects defined types in the idl
func getTypes(tidl *idl.IDL) []typeDescriber {
var types []typeDescriber
for _, x := range tidl.Aliases {
i := typeDescriber{
Name: x.Name,
doc: x.Doc,
}
ta := []typeAttrs{}
for _, y := range x.Type.Fields {
result := typeToString(y.Type)
ta = append(ta, typeAttrs{Name: y.Name, AttrType: result})
}
i.Attrs = ta
types = append(types, i)
}
return types
}
// collects defined methods in the idl
func getMethods(midl *idl.IDL) []funcDescriber {
var methods []funcDescriber
for _, t := range midl.Methods {
m := funcDescriber{
Name: t.Name,
doc: t.Doc,
}
fa := []funcArgs{}
fo := []funcArgs{}
for _, i := range t.In.Fields {
fa = append(fa, funcArgs{paramName: i.Name, paramKind: typeToString(i.Type)})
}
for _, f := range t.Out.Fields {
fo = append(fo, funcArgs{paramName: f.Name, paramKind: typeToString(f.Type)})
}
m.inputParams = fa
m.returnParams = fo
methods = append(methods, m)
}
return methods
}
// collects defined errors in the idl
func getErrors(midl *idl.IDL) []err {
var errors []err
for _, e := range midl.Errors {
myError := err{
Name: e.Name,
doc: e.Doc,
}
errors = append(errors, myError)
}
return errors
}
// generates the index for the top of the markdown page
func generateIndex(methods []funcDescriber, types []typeDescriber, errors []err, b bytes.Buffer) bytes.Buffer {
for _, method := range methods {
var inArgs []string
var outArgs []string
for _, inArg := range method.inputParams {
inArgs = append(inArgs, fmt.Sprintf("%s: %s", inArg.paramName, inArg.paramKind))
}
for _, outArg := range method.returnParams {
outArgs = append(outArgs, fmt.Sprintf("%s", outArg.paramKind))
}
b.WriteString(fmt.Sprintf("\n[func %s(%s) %s](#%s)\n", method.Name, strings.Join(inArgs, ", "), strings.Join(outArgs, ", "), method.Name))
}
for _, t := range types {
b.WriteString(fmt.Sprintf("[type %s](#%s)\n\n", t.Name, t.Name))
}
for _, e := range errors {
b.WriteString(fmt.Sprintf("[error %s](#%s)\n\n", e.Name, e.Name))
}
return b
}
// performs the output for defined methods
func generateFuncDescriptions(methods []funcDescriber, b bytes.Buffer) bytes.Buffer {
for _, method := range methods {
b.WriteString(fmt.Sprintf("### <a name=\"%s\"></a>func %s\n", method.Name, method.Name))
var inArgs []string
var outArgs []string
for _, inArg := range method.inputParams {
inArgs = append(inArgs, fmt.Sprintf("%s: [%s](%s)", inArg.paramName, inArg.paramKind, typeToLink(inArg.paramKind)))
}
for _, outArg := range method.returnParams {
outArgs = append(outArgs, fmt.Sprintf("[%s](%s)", outArg.paramKind, typeToLink(outArg.paramKind)))
}
b.WriteString(fmt.Sprintf("<div style=\"background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;\">\n\nmethod %s(%s) %s</div>", method.Name, strings.Join(inArgs, ", "), strings.Join(outArgs, ", ")))
b.WriteString("\n")
b.WriteString(method.doc)
b.WriteString("\n")
}
return b
}
// performs the output for defined types/structs
func generateTypeDescriptions(types []typeDescriber, b bytes.Buffer) bytes.Buffer {
for _, t := range types {
b.WriteString(fmt.Sprintf("### <a name=\"%s\"></a>type %s\n", t.Name, t.Name))
b.WriteString(fmt.Sprintf("\n%s\n", t.doc))
for _, i := range t.Attrs {
b.WriteString(fmt.Sprintf("\n%s [%s](%s)\n", i.Name, i.AttrType, typeToLink(i.AttrType)))
}
}
return b
}
// performs the output for defined errors
func generateErrorDescriptions(errors []err, b bytes.Buffer) bytes.Buffer {
for _, e := range errors {
b.WriteString(fmt.Sprintf("### <a name=\"%s\"></a>type %s\n", e.Name, e.Name))
b.WriteString(fmt.Sprintf("\n%s\n", e.doc))
}
return b
}
func main() {
args := os.Args
if len(args) < 2 {
exit(fmt.Errorf("you must provide an input and output path"))
}
varlinkFile := args[1]
mdFile := args[2]
varlinkInput, err := readFileToString(varlinkFile)
if err != nil {
exit(err)
}
varlinkInput = strings.TrimRight(varlinkInput, "\n")
// Run the idl parser
midl, err := idl.New(varlinkInput)
if err != nil {
exit(err)
}
// Collect up the info from the idl
methods := getMethods(midl)
types := getTypes(midl)
errors := getErrors(midl)
out := bytes.Buffer{}
out.WriteString("## Index\n")
out = generateIndex(methods, types, errors, out)
out.WriteString("## Methods\n")
out = generateFuncDescriptions(methods, out)
out.WriteString("## Types\n")
out = generateTypeDescriptions(types, out)
out.WriteString("## Errors\n")
out = generateErrorDescriptions(errors, out)
ioutil.WriteFile(mdFile, out.Bytes(), 0755)
}

View File

@ -9,6 +9,7 @@ import (
"syscall"
"time"
"github.com/containers/storage/pkg/archive"
"github.com/pkg/errors"
"github.com/projectatomic/libpod/cmd/podman/batchcontainer"
"github.com/projectatomic/libpod/cmd/podman/libpodruntime"
@ -195,12 +196,18 @@ func (i *LibpodAPI) ListContainerChanges(call ioprojectatomicpodman.VarlinkCall,
if err != nil {
return call.ReplyErrorOccurred(err.Error())
}
m := make(map[string]string)
result := ioprojectatomicpodman.ContainerChanges{}
for _, change := range changes {
m[change.Path] = change.Kind.String()
switch change.Kind {
case archive.ChangeModify:
result.Changed = append(result.Changed, change.Path)
case archive.ChangeDelete:
result.Deleted = append(result.Deleted, change.Path)
case archive.ChangeAdd:
result.Added = append(result.Added, change.Path)
}
}
return call.ReplyListContainerChanges(m)
return call.ReplyListContainerChanges(result)
}
// ExportContainer ...

View File

@ -140,7 +140,7 @@ func (i *LibpodAPI) PushImage(call ioprojectatomicpodman.VarlinkCall, name, tag
if err := newImage.PushImage(getContext(), destname, "", "", "", nil, false, so, &dockerRegistryOptions); err != nil {
return call.ReplyErrorOccurred(err.Error())
}
return call.ReplyPushImage()
return call.ReplyPushImage(newImage.ID())
}
// TagImage accepts an image name and tag as strings and tags an image in the local store.
@ -156,7 +156,7 @@ func (i *LibpodAPI) TagImage(call ioprojectatomicpodman.VarlinkCall, name, tag s
if err := newImage.TagImage(tag); err != nil {
return call.ReplyErrorOccurred(err.Error())
}
return call.ReplyTagImage()
return call.ReplyTagImage(newImage.ID())
}
// RemoveImage accepts a image name or ID as a string and force bool to determine if it should
@ -275,7 +275,7 @@ func (i *LibpodAPI) ExportImage(call ioprojectatomicpodman.VarlinkCall, name, de
if err := newImage.PushImage(getContext(), destination, "", "", "", nil, compress, image.SigningOptions{}, &image.DockerRegistryOptions{}); err != nil {
return call.ReplyErrorOccurred(err.Error())
}
return call.ReplyExportImage()
return call.ReplyExportImage(newImage.ID())
}
// PullImage pulls an image from a registry to the image store.

View File

@ -0,0 +1,619 @@
package main
import (
"crypto/rand"
"encoding/json"
"flag"
"fmt"
"github.com/varlink/go/cmd/varlink-go-certification/orgvarlinkcertification"
"github.com/varlink/go/varlink"
"io"
"math"
"os"
"strconv"
"sync"
"time"
)
func run_client(address string) {
c, err := varlink.NewConnection(address)
if err != nil {
fmt.Println("Failed to connect")
return
}
defer c.Close()
client_id, err := orgvarlinkcertification.Start().Call(c)
if err != nil {
fmt.Println("Start() failed")
return
}
fmt.Printf("Start: '%v'\n", client_id)
b1, err := orgvarlinkcertification.Test01().Call(c, client_id)
if err != nil {
fmt.Println("Test01() failed")
return
}
fmt.Printf("Test01: '%v'\n", b1)
i2, err := orgvarlinkcertification.Test02().Call(c, client_id, b1)
if err != nil {
fmt.Println("Test02() failed")
return
}
fmt.Printf("Test02: '%v'\n", i2)
f3, err := orgvarlinkcertification.Test03().Call(c, client_id, i2)
if err != nil {
fmt.Println("Test03() failed")
return
}
fmt.Printf("Test03: '%v'\n", f3)
s4, err := orgvarlinkcertification.Test04().Call(c, client_id, f3)
if err != nil {
fmt.Println("Test04() failed")
return
}
fmt.Printf("Test04: '%v'\n", s4)
b5, i5, f5, s5, err := orgvarlinkcertification.Test05().Call(c, client_id, s4)
if err != nil {
fmt.Println("Test05() failed")
return
}
fmt.Printf("Test05: '%v'\n", b5)
o6, err := orgvarlinkcertification.Test06().Call(c, client_id, b5, i5, f5, s5)
if err != nil {
fmt.Println("Test06() failed")
return
}
fmt.Printf("Test06: '%v'\n", o6)
m7, err := orgvarlinkcertification.Test07().Call(c, client_id, o6)
if err != nil {
fmt.Println("Test07() failed")
return
}
fmt.Printf("Test07: '%v'\n", m7)
m8, err := orgvarlinkcertification.Test08().Call(c, client_id, m7)
if err != nil {
fmt.Println("Test08() failed")
return
}
fmt.Printf("Test08: '%v'\n", m8)
t9, err := orgvarlinkcertification.Test09().Call(c, client_id, m8)
if err != nil {
fmt.Println("Test09() failed")
return
}
fmt.Printf("Test09: '%v'\n", t9)
receive10, err := orgvarlinkcertification.Test10().Send(c, varlink.More, client_id, t9)
if err != nil {
fmt.Println("Test10() failed")
return
}
fmt.Println("Test10() Send:")
var a10 []string
for {
s10, flags10, err := receive10()
if err != nil {
fmt.Println("Test10() receive failed")
return
}
a10 = append(a10, s10)
fmt.Printf(" Receive: '%v'\n", s10)
if flags10&varlink.Continues == 0 {
break
}
}
fmt.Printf("Test10: '%v'\n", a10)
_, err = orgvarlinkcertification.Test11().Send(c, varlink.Oneway, client_id, a10)
if err != nil {
fmt.Println("Test11() failed")
return
}
fmt.Println("Test11: ''")
end, err := orgvarlinkcertification.End().Call(c, client_id)
if err != nil {
fmt.Println("End() failed")
return
}
fmt.Printf("End: '%v'\n", end)
}
// Service
type client struct {
id string
time time.Time
}
type test struct {
orgvarlinkcertification.VarlinkInterface
mutex sync.Mutex
clients map[string]*client
}
func (t *test) Client(id string) *client {
t.mutex.Lock()
defer t.mutex.Unlock()
return t.clients[id]
}
func (t *test) NewClient() *client {
id128 := make([]byte, 16)
io.ReadFull(rand.Reader, id128)
id128[8] = id128[8]&^0xc0 | 0x80
id128[6] = id128[6]&^0xf0 | 0x40
uuid := fmt.Sprintf("%x-%x-%x-%x-%x", id128[0:4], id128[4:6], id128[6:8], id128[8:10], id128[10:])
t.mutex.Lock()
defer t.mutex.Unlock()
// Garbage-collect old clients
for key, client := range t.clients {
if time.Since(client.time).Minutes() > 1 {
delete(t.clients, key)
}
}
if len(t.clients) > 100 {
return nil
}
c := client{
id: uuid,
time: time.Now(),
}
t.clients[uuid] = &c
return &c
}
func (t *test) RemoveClient(id string) {
t.mutex.Lock()
defer t.mutex.Unlock()
delete(t.clients, id)
}
func (t *test) Start(c orgvarlinkcertification.VarlinkCall) error {
return c.ReplyStart(t.NewClient().id)
}
func (t *test) Test01(c orgvarlinkcertification.VarlinkCall, client_id_ string) error {
if t.Client(client_id_) == nil {
return c.ReplyClientIdError()
}
return c.ReplyTest01(true)
}
func (t *test) Test02(c orgvarlinkcertification.VarlinkCall, client_id_ string, bool_ bool) error {
if t.Client(client_id_) == nil {
return c.ReplyClientIdError()
}
if !bool_ {
return c.ReplyCertificationError(nil, nil)
}
return c.ReplyTest02(1)
}
func (t *test) Test03(c orgvarlinkcertification.VarlinkCall, client_id_ string, int_ int64) error {
if t.Client(client_id_) == nil {
return c.ReplyClientIdError()
}
if int_ != 1 {
return c.ReplyCertificationError(nil, nil)
}
return c.ReplyTest03(1.0)
}
func (t *test) Test04(c orgvarlinkcertification.VarlinkCall, client_id_ string, float_ float64) error {
if t.Client(client_id_) == nil {
return c.ReplyClientIdError()
}
if float_ != 1.0 {
return c.ReplyCertificationError(nil, nil)
}
return c.ReplyTest04("ping")
}
func (t *test) Test05(c orgvarlinkcertification.VarlinkCall, client_id_ string, string_ string) error {
if t.Client(client_id_) == nil {
return c.ReplyClientIdError()
}
if string_ != "ping" {
return c.ReplyCertificationError(nil, nil)
}
return c.ReplyTest05(false, 2, math.Pi, "a lot of string")
}
func (t *test) Test06(c orgvarlinkcertification.VarlinkCall, client_id_ string, bool_ bool, int_ int64, float_ float64, string_ string) error {
if t.Client(client_id_) == nil {
return c.ReplyClientIdError()
}
if bool_ {
return c.ReplyCertificationError(nil, nil)
}
if int_ != 2 {
return c.ReplyCertificationError(nil, nil)
}
if float_ != math.Pi {
return c.ReplyCertificationError(nil, nil)
}
if string_ != "a lot of string" {
return c.ReplyCertificationError(nil, nil)
}
s := struct {
Bool bool
Int int64
Float float64
String string
}{
Bool: false,
Int: 2,
Float: math.Pi,
String: "a lot of string",
}
return c.ReplyTest06(s)
}
func (t *test) Test07(c orgvarlinkcertification.VarlinkCall, client_id_ string, struct_ struct {
Bool bool
Int int64
Float float64
String string
}) error {
if t.Client(client_id_) == nil {
return c.ReplyClientIdError()
}
if struct_.Bool {
return c.ReplyCertificationError(nil, nil)
}
if struct_.Int != 2 {
return c.ReplyCertificationError(nil, nil)
}
if struct_.Float != math.Pi {
return c.ReplyCertificationError(nil, nil)
}
if struct_.String != "a lot of string" {
return c.ReplyCertificationError(nil, nil)
}
m := map[string]string{
"bar": "Bar",
"foo": "Foo",
}
return c.ReplyTest07(m)
}
func (t *test) Test08(c orgvarlinkcertification.VarlinkCall, client_id_ string, map_ map[string]string) error {
if t.Client(client_id_) == nil {
return c.ReplyClientIdError()
}
if len(map_) != 2 {
return c.ReplyCertificationError(nil, nil)
}
if map_["bar"] != "Bar" {
return c.ReplyCertificationError(nil, nil)
}
if map_["foo"] != "Foo" {
return c.ReplyCertificationError(nil, nil)
}
m := map[string]struct{}{
"one": {},
"two": {},
"three": {},
}
return c.ReplyTest08(m)
}
func (t *test) Test09(c orgvarlinkcertification.VarlinkCall, client_id_ string, set_ map[string]struct{}) error {
if t.Client(client_id_) == nil {
return c.ReplyClientIdError()
}
if len(set_) != 3 {
return c.ReplyCertificationError(nil, nil)
}
_, ok := set_["one"]
if !ok {
return c.ReplyCertificationError(nil, nil)
}
_, ok = set_["two"]
if !ok {
return c.ReplyCertificationError(nil, nil)
}
_, ok = set_["three"]
if !ok {
return c.ReplyCertificationError(nil, nil)
}
m := orgvarlinkcertification.MyType{
Object: json.RawMessage(`{"method": "org.varlink.certification.Test09", "parameters": {"map": {"foo": "Foo", "bar": "Bar"}}}`),
Enum: "two",
Struct: struct {
First int64 `json:"first"`
Second string `json:"second"`
}{First: 1, Second: "2"},
Array: []string{"one", "two", "three"},
Dictionary: map[string]string{"foo": "Foo", "bar": "Bar"},
Stringset: map[string]struct{}{"one": {}, "two": {}, "three": {}},
Nullable: nil,
Nullable_array_struct: nil,
Interface: orgvarlinkcertification.Interface{
Foo: &[]*map[string]string{
nil,
&map[string]string{"Foo": "foo", "Bar": "bar"},
nil,
&map[string]string{"one": "foo", "two": "bar"},
},
Anon: struct {
Foo bool `json:"foo"`
Bar bool `json:"bar"`
}{Foo: true, Bar: false},
},
}
return c.ReplyTest09(m)
}
func (t *test) Test10(c orgvarlinkcertification.VarlinkCall, client_id_ string, mytype_ orgvarlinkcertification.MyType) error {
if t.Client(client_id_) == nil {
return c.ReplyClientIdError()
}
var o struct {
Method string `json:"method"`
Parameters struct {
Map map[string]string `json:"map"`
} `json:"parameters"`
}
err := json.Unmarshal(mytype_.Object, &o)
if err != nil {
return err
}
if o.Method != "org.varlink.certification.Test09" {
return c.ReplyCertificationError(nil, nil)
}
if len(o.Parameters.Map) != 2 {
return c.ReplyCertificationError(nil, nil)
}
if o.Parameters.Map["bar"] != "Bar" {
return c.ReplyCertificationError(nil, nil)
}
if o.Parameters.Map["foo"] != "Foo" {
return c.ReplyCertificationError(nil, nil)
}
if mytype_.Enum != "two" {
return c.ReplyCertificationError(nil, nil)
}
if mytype_.Struct.First != 1 {
return c.ReplyCertificationError(nil, nil)
}
if mytype_.Struct.Second != "2" {
return c.ReplyCertificationError(nil, nil)
}
if len(mytype_.Array) != 3 {
return c.ReplyCertificationError(nil, nil)
}
if mytype_.Array[0] != "one" && mytype_.Array[1] != "two" && mytype_.Array[2] != "three" {
return c.ReplyCertificationError(nil, nil)
}
if len(mytype_.Dictionary) != 2 {
return c.ReplyCertificationError(nil, nil)
}
if mytype_.Dictionary["bar"] != "Bar" {
return c.ReplyCertificationError(nil, nil)
}
if mytype_.Dictionary["foo"] != "Foo" {
return c.ReplyCertificationError(nil, nil)
}
if len(mytype_.Stringset) != 3 {
return c.ReplyCertificationError(nil, nil)
}
_, ok := mytype_.Stringset["one"]
if !ok {
return c.ReplyCertificationError(nil, nil)
}
_, ok = mytype_.Stringset["two"]
if !ok {
return c.ReplyCertificationError(nil, nil)
}
_, ok = mytype_.Stringset["three"]
if !ok {
return c.ReplyCertificationError(nil, nil)
}
if mytype_.Nullable != nil {
return c.ReplyCertificationError(nil, nil)
}
if mytype_.Nullable_array_struct != nil {
return c.ReplyCertificationError(nil, nil)
}
i := *mytype_.Interface.Foo
if len(i) != 4 {
return c.ReplyCertificationError(nil, nil)
}
if i[0] != nil {
return c.ReplyCertificationError(nil, nil)
}
if len(*i[1]) != 2 {
return c.ReplyCertificationError(nil, nil)
}
if (*i[1])["Foo"] != "foo" {
return c.ReplyCertificationError(nil, nil)
}
if (*i[1])["Bar"] != "bar" {
return c.ReplyCertificationError(nil, nil)
}
if i[2] != nil {
return c.ReplyCertificationError(nil, nil)
}
if len(*i[3]) != 2 {
return c.ReplyCertificationError(nil, nil)
}
if (*i[3])["one"] != "foo" {
return c.ReplyCertificationError(nil, nil)
}
if (*i[3])["two"] != "bar" {
return c.ReplyCertificationError(nil, nil)
}
if !mytype_.Interface.Anon.Foo {
return c.ReplyCertificationError(nil, nil)
}
if mytype_.Interface.Anon.Bar {
return c.ReplyCertificationError(nil, nil)
}
if !c.WantsMore() {
return c.ReplyCertificationError(nil, nil)
}
for i := 1; i <= 10; i++ {
c.Continues = i < 10
err := c.ReplyTest10("Reply number " + strconv.Itoa(i))
if err != nil {
return err
}
}
return nil
}
func (t *test) Test11(c orgvarlinkcertification.VarlinkCall, client_id_ string, last_more_replies_ []string) error {
if t.Client(client_id_) == nil {
return c.ReplyClientIdError()
}
if len(last_more_replies_) != 10 {
return c.ReplyCertificationError(nil, nil)
}
if !c.IsOneway() {
return c.ReplyCertificationError(nil, nil)
}
for i := 1; i <= 10; i++ {
if last_more_replies_[i] != "Reply number "+strconv.Itoa(i) {
return c.ReplyCertificationError(nil, nil)
}
}
return c.ReplyTest11()
}
func (t *test) End(c orgvarlinkcertification.VarlinkCall, client_id_ string) error {
if t.Client(client_id_) == nil {
return c.ReplyClientIdError()
}
t.RemoveClient(client_id_)
return c.ReplyEnd(true)
}
func run_server(address string) {
t := test{
clients: make(map[string]*client),
}
s, err := varlink.NewService(
"Varlink",
"Certification",
"1",
"https://github.com/varlink/go",
)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
s.RegisterInterface(orgvarlinkcertification.VarlinkNew(&t))
err = s.Listen(address, 0)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func main() {
var address string
var client bool
flag.StringVar(&address, "varlink", "", "Varlink address")
flag.BoolVar(&client, "client", false, "Run as client")
flag.Parse()
if address == "" {
flag.Usage()
os.Exit(1)
}
if client {
run_client(address)
return
}
run_server(address)
}

View File

@ -0,0 +1,3 @@
package orgvarlinkcertification
//go:generate go run ../../varlink-go-interface-generator/main.go org.varlink.certification.varlink

View File

@ -0,0 +1,89 @@
# Interface to test varlink implementations against.
# First you write a varlink client calling:
# Start, Test01, Test02, …, Test09, End
# The return value of the previous call should be the argument of the next call.
# Then you test this client against well known servers like python or rust from
# https://github.com/varlink/
#
# Next you write a varlink server providing the same service as the well known ones.
# Now run your client against it and run well known clients like python or rust
# from https://github.com/varlink/ against your server. If all works out, then
# your new language bindings should be varlink certified.
interface org.varlink.certification
type Interface (
foo: ?[]?[string](foo, bar, baz),
anon: (foo: bool, bar: bool)
)
type MyType (
object: object,
enum: (one, two, three),
struct: (first: int, second: string),
array: []string,
dictionary: [string]string,
stringset: [string](),
nullable: ?string,
nullable_array_struct: ?[](first: int, second: string),
interface: Interface
)
method Start() -> (client_id: string)
method Test01(client_id: string) -> (bool: bool)
method Test02(client_id: string, bool: bool) -> (int: int)
method Test03(client_id: string, int: int) -> (float: float)
method Test04(client_id: string, float: float) -> (string: string)
method Test05(client_id: string, string: string) -> (
bool: bool,
int: int,
float: float,
string: string
)
method Test06(
client_id: string,
bool: bool,
int: int,
float: float,
string: string
) -> (
struct: (
bool: bool,
int: int,
float: float,
string: string
)
)
method Test07(
client_id: string,
struct: (
bool: bool,
int: int,
float: float,
string: string
)
) -> (map: [string]string)
method Test08(client_id: string, map: [string]string) -> (set: [string]())
method Test09(client_id: string, set: [string]()) -> (mytype: MyType)
# returns more than one reply with "continues"
method Test10(client_id: string, mytype: MyType) -> (string: string)
method Test11(
client_id: string,
last_more_replies: []string
) -> ()
method End(client_id: string) -> (all_ok: bool)
error ClientIdError ()
error CertificationError (wants: object, got: object)

View File

@ -95,14 +95,51 @@ func generateTemplate(description string) (string, []byte, error) {
b.WriteString("\n\n")
}
b.WriteString("// Client method calls and reply readers\n")
b.WriteString("// Client method calls\n")
for _, m := range midl.Methods {
b.WriteString("func " + m.Name + "(c__ *varlink.Connection, more__ bool, oneway__ bool")
b.WriteString("type " + m.Name + "_methods struct{}\n")
b.WriteString("func " + m.Name + "() " + m.Name + "_methods { return " + m.Name + "_methods{} }\n\n")
b.WriteString("func (m " + m.Name + "_methods) Call(c *varlink.Connection")
for _, field := range m.In.Fields {
b.WriteString(", " + field.Name + "_ ")
b.WriteString(", " + field.Name + "_in_ ")
writeType(&b, field.Type, false, 1)
}
b.WriteString(") error {\n")
b.WriteString(") (")
for _, field := range m.Out.Fields {
b.WriteString(field.Name + "_out_ ")
writeType(&b, field.Type, false, 1)
b.WriteString(", ")
}
b.WriteString("err_ error) {\n")
b.WriteString("receive, err_ := m.Send(c, 0")
for _, field := range m.In.Fields {
b.WriteString(", " + field.Name + "_in_ ")
}
b.WriteString(")\n")
b.WriteString("if err_ != nil {\n" +
"\treturn\n" +
"}\n")
b.WriteString("\t")
for _, field := range m.Out.Fields {
b.WriteString(field.Name + "_out_ ")
b.WriteString(", ")
}
b.WriteString("_, err_ = receive()\n")
b.WriteString("\treturn\n" +
"}\n\n")
b.WriteString("func (m " + m.Name + "_methods) Send(c *varlink.Connection, flags uint64")
for _, field := range m.In.Fields {
b.WriteString(", " + field.Name + "_in_ ")
writeType(&b, field.Type, false, 1)
}
b.WriteString(") (func() (")
for _, field := range m.Out.Fields {
writeType(&b, field.Type, false, 1)
b.WriteString(", ")
}
b.WriteString("uint64, error), error) {\n")
if len(m.In.Fields) > 0 {
b.WriteString("\tvar in ")
writeType(&b, m.In, true, 1)
@ -112,58 +149,57 @@ func generateTemplate(description string) (string, []byte, error) {
case idl.TypeStruct, idl.TypeArray, idl.TypeMap:
b.WriteString("\tin." + strings.Title(field.Name) + " = ")
writeType(&b, field.Type, true, 1)
b.WriteString("(" + field.Name + "_)\n")
b.WriteString("(" + field.Name + "_in_)\n")
default:
b.WriteString("\tin." + strings.Title(field.Name) + " = " + field.Name + "_\n")
b.WriteString("\tin." + strings.Title(field.Name) + " = " + field.Name + "_in_\n")
}
}
b.WriteString("\treturn c__.Send(\"" + midl.Name + "." + m.Name + "\", in, more__, oneway__)\n" +
"}\n\n")
b.WriteString("\treceive, err := c.Send(\"" + midl.Name + "." + m.Name + "\", in, flags)\n")
} else {
b.WriteString("\treturn c__.Send(\"" + midl.Name + "." + m.Name + "\", nil, more__, oneway__)\n" +
"}\n\n")
b.WriteString("\treceive, err := c.Send(\"" + midl.Name + "." + m.Name + "\", nil, flags)\n")
}
b.WriteString("func Read" + m.Name + "_(c__ *varlink.Connection")
b.WriteString("if err != nil {\n" +
"\treturn nil, err\n" +
"}\n")
b.WriteString("\treturn func() (")
for _, field := range m.Out.Fields {
b.WriteString(", " + field.Name + "_ *")
writeType(&b, field.Type, false, 1)
b.WriteString(field.Name + "_out_ ")
writeType(&b, field.Type, false, 3)
b.WriteString(", ")
}
b.WriteString(") (bool, error) {\n")
b.WriteString("flags uint64, err error) {\n")
if len(m.Out.Fields) > 0 {
b.WriteString("\tvar out ")
writeType(&b, m.Out, true, 1)
b.WriteString("\t\tvar out ")
writeType(&b, m.Out, true, 2)
b.WriteString("\n")
b.WriteString("\tcontinues_, err := c__.Receive(&out)\n")
b.WriteString("\t\tflags, err = receive(&out)\n")
} else {
b.WriteString("\tcontinues_, err := c__.Receive(nil)\n")
b.WriteString("\t\tflags, err = receive(nil)\n")
}
b.WriteString("\tif err != nil {\n" +
"\t\treturn false, err\n" +
"\t}\n")
b.WriteString("\t\tif err != nil {\n" +
"\t\t\treturn\n" +
"\t\t}\n")
for _, field := range m.Out.Fields {
b.WriteString("\tif " + field.Name + "_ != nil {\n")
b.WriteString("\t\t" + field.Name + "_out_ = ")
switch field.Type.Kind {
case idl.TypeStruct, idl.TypeArray, idl.TypeMap:
b.WriteString("\t\t*" + field.Name + "_ = ")
writeType(&b, field.Type, false, 2)
b.WriteString(" (out." + strings.Title(field.Name) + ")\n")
b.WriteString("(out." + strings.Title(field.Name) + ")\n")
default:
b.WriteString("\t\t*" + field.Name + "_ = out." + strings.Title(field.Name) + "\n")
b.WriteString("out." + strings.Title(field.Name) + "\n")
}
b.WriteString("\t}\n")
}
b.WriteString("\treturn continues_, nil\n" +
"}\n\n")
b.WriteString("\t\treturn\n" +
"\t}, nil\n")
b.WriteString("}\n\n")
}
b.WriteString("// Service interface with all methods\n")
b.WriteString("type " + pkgname + "Interface interface {\n")
for _, m := range midl.Methods {
b.WriteString("\t" + m.Name + "(c__ VarlinkCall")
b.WriteString("\t" + m.Name + "(c VarlinkCall")
for _, field := range m.In.Fields {
b.WriteString(", " + field.Name + "_ ")
writeType(&b, field.Type, false, 1)
@ -177,7 +213,7 @@ func generateTemplate(description string) (string, []byte, error) {
b.WriteString("// Reply methods for all varlink errors\n")
for _, e := range midl.Errors {
b.WriteString("func (c__ *VarlinkCall) Reply" + e.Name + "(")
b.WriteString("func (c *VarlinkCall) Reply" + e.Name + "(")
for i, field := range e.Type.Fields {
if i > 0 {
b.WriteString(", ")
@ -201,16 +237,16 @@ func generateTemplate(description string) (string, []byte, error) {
b.WriteString("\tout." + strings.Title(field.Name) + " = " + field.Name + "_\n")
}
}
b.WriteString("\treturn c__.ReplyError(\"" + midl.Name + "." + e.Name + "\", &out)\n")
b.WriteString("\treturn c.ReplyError(\"" + midl.Name + "." + e.Name + "\", &out)\n")
} else {
b.WriteString("\treturn c__.ReplyError(\"" + midl.Name + "." + e.Name + "\", nil)\n")
b.WriteString("\treturn c.ReplyError(\"" + midl.Name + "." + e.Name + "\", nil)\n")
}
b.WriteString("}\n\n")
}
b.WriteString("// Reply methods for all varlink methods\n")
for _, m := range midl.Methods {
b.WriteString("func (c__ *VarlinkCall) Reply" + m.Name + "(")
b.WriteString("func (c *VarlinkCall) Reply" + m.Name + "(")
for i, field := range m.Out.Fields {
if i > 0 {
b.WriteString(", ")
@ -234,27 +270,27 @@ func generateTemplate(description string) (string, []byte, error) {
b.WriteString("\tout." + strings.Title(field.Name) + " = " + field.Name + "_\n")
}
}
b.WriteString("\treturn c__.Reply(&out)\n")
b.WriteString("\treturn c.Reply(&out)\n")
} else {
b.WriteString("\treturn c__.Reply(nil)\n")
b.WriteString("\treturn c.Reply(nil)\n")
}
b.WriteString("}\n\n")
}
b.WriteString("// Dummy methods for all varlink methods\n")
b.WriteString("// Dummy implementations for all varlink methods\n")
for _, m := range midl.Methods {
b.WriteString("func (s__ *VarlinkInterface) " + m.Name + "(c__ VarlinkCall")
b.WriteString("func (s *VarlinkInterface) " + m.Name + "(c VarlinkCall")
for _, field := range m.In.Fields {
b.WriteString(", " + field.Name + "_ ")
writeType(&b, field.Type, false, 1)
}
b.WriteString(") error {\n" +
"\treturn c__.ReplyMethodNotImplemented(\"" + m.Name + "\")\n" +
"\treturn c.ReplyMethodNotImplemented(\"" + midl.Name + "." + m.Name + "\")\n" +
"}\n\n")
}
b.WriteString("// Method call dispatcher\n")
b.WriteString("func (s__ *VarlinkInterface) VarlinkDispatch(call varlink.Call, methodname string) error {\n" +
b.WriteString("func (s *VarlinkInterface) VarlinkDispatch(call varlink.Call, methodname string) error {\n" +
"\tswitch methodname {\n")
for _, m := range midl.Methods {
b.WriteString("\tcase \"" + m.Name + "\":\n")
@ -266,7 +302,7 @@ func generateTemplate(description string) (string, []byte, error) {
"\t\tif err != nil {\n" +
"\t\t\treturn call.ReplyInvalidParameter(\"parameters\")\n" +
"\t\t}\n")
b.WriteString("\t\treturn s__." + pkgname + "Interface." + m.Name + "(VarlinkCall{call}")
b.WriteString("\t\treturn s." + pkgname + "Interface." + m.Name + "(VarlinkCall{call}")
if len(m.In.Fields) > 0 {
for _, field := range m.In.Fields {
switch field.Type.Kind {
@ -282,7 +318,7 @@ func generateTemplate(description string) (string, []byte, error) {
}
b.WriteString(")\n")
} else {
b.WriteString("\t\treturn s__." + pkgname + "Interface." + m.Name + "(VarlinkCall{call})\n")
b.WriteString("\t\treturn s." + pkgname + "Interface." + m.Name + "(VarlinkCall{call})\n")
}
b.WriteString("\n")
}
@ -292,11 +328,11 @@ func generateTemplate(description string) (string, []byte, error) {
"}\n\n")
b.WriteString("// Varlink interface name\n")
b.WriteString("func (s__ *VarlinkInterface) VarlinkGetName() string {\n" +
b.WriteString("func (s *VarlinkInterface) VarlinkGetName() string {\n" +
"\treturn `" + midl.Name + "`\n" + "}\n\n")
b.WriteString("// Varlink interface description\n")
b.WriteString("func (s__ *VarlinkInterface) VarlinkGetDescription() string {\n" +
b.WriteString("func (s *VarlinkInterface) VarlinkGetDescription() string {\n" +
"\treturn `" + midl.Description + "\n`\n}\n\n")
b.WriteString("// Service interface\n")

View File

@ -21,9 +21,9 @@ func (c *Call) WantsMore() bool {
return c.in.More
}
// IsOneShot indicate that the calling client does not expect a reply.
func (c *Call) IsOneShot() bool {
return c.in.OneShot
// IsOneway indicate that the calling client does not expect a reply.
func (c *Call) IsOneway() bool {
return c.in.Oneway
}
// GetParameters retrieves the method call parameters.
@ -35,7 +35,7 @@ func (c *Call) GetParameters(p interface{}) error {
}
func (c *Call) sendMessage(r *serviceReply) error {
if c.in.OneShot {
if c.in.Oneway {
return nil
}

View File

@ -7,6 +7,15 @@ import (
"strings"
)
// Message flags for Send(). More indicates that the client accepts more than one method
// reply to this call. Oneway requests, that the service must not send a method reply to
// this call. Continues indicates that the service will send more than one reply.
const (
More = 1 << iota
Oneway = 1 << iota
Continues = 1 << iota
)
// Error is a varlink error returned from a method call.
type Error struct {
Name string
@ -26,8 +35,10 @@ type Connection struct {
writer *bufio.Writer
}
// Send sends a method call.
func (c *Connection) Send(method string, parameters interface{}, more bool, oneway bool) error {
// Send sends a method call. It returns a receive() function which is called to retrieve the method reply.
// If Send() is called with the `More`flag and the receive() function carries the `Continues` flag, receive()
// can be called multiple times to retrieve multiple replies.
func (c *Connection) Send(method string, parameters interface{}, flags uint64) (func(interface{}) (uint64, error), error) {
type call struct {
Method string `json:"method"`
Parameters interface{} `json:"parameters,omitempty"`
@ -35,8 +46,8 @@ func (c *Connection) Send(method string, parameters interface{}, more bool, onew
Oneway bool `json:"oneway,omitempty"`
}
if more && oneway {
return &Error{
if (flags&More != 0) && (flags&Oneway != 0) {
return nil, &Error{
Name: "org.varlink.InvalidParameter",
Parameters: "oneway",
}
@ -45,64 +56,73 @@ func (c *Connection) Send(method string, parameters interface{}, more bool, onew
m := call{
Method: method,
Parameters: parameters,
More: more,
Oneway: oneway,
More: flags&More != 0,
Oneway: flags&Oneway != 0,
}
b, err := json.Marshal(m)
if err != nil {
return err
return nil, err
}
b = append(b, 0)
_, err = c.writer.Write(b)
if err != nil {
return err
return nil, err
}
return c.writer.Flush()
}
// Receive receives a method reply.
func (c *Connection) Receive(parameters interface{}) (bool, error) {
type reply struct {
Parameters *json.RawMessage `json:"parameters"`
Continues bool `json:"continues"`
Error string `json:"error"`
}
out, err := c.reader.ReadBytes('\x00')
err = c.writer.Flush()
if err != nil {
return false, err
return nil, err
}
var m reply
err = json.Unmarshal(out[:len(out)-1], &m)
if err != nil {
return false, err
}
if m.Error != "" {
return false, &Error{
Name: m.Error,
Parameters: m.Parameters,
receive := func(out_parameters interface{}) (uint64, error) {
type reply struct {
Parameters *json.RawMessage `json:"parameters"`
Continues bool `json:"continues"`
Error string `json:"error"`
}
out, err := c.reader.ReadBytes('\x00')
if err != nil {
return 0, err
}
var m reply
err = json.Unmarshal(out[:len(out)-1], &m)
if err != nil {
return 0, err
}
if m.Error != "" {
err = &Error{
Name: m.Error,
Parameters: m.Parameters,
}
return 0, err
}
if m.Parameters != nil {
json.Unmarshal(*m.Parameters, out_parameters)
}
if m.Continues {
return Continues, nil
}
return 0, nil
}
if parameters != nil && m.Parameters != nil {
return m.Continues, json.Unmarshal(*m.Parameters, parameters)
}
return m.Continues, nil
return receive, nil
}
// Call sends a method call and returns the result of the call.
func (c *Connection) Call(method string, parameters interface{}, result interface{}) error {
err := c.Send(method, &parameters, false, false)
// Call sends a method call and returns the method reply.
func (c *Connection) Call(method string, parameters interface{}, out_parameters interface{}) error {
receive, err := c.Send(method, &parameters, 0)
if err != nil {
return err
}
_, err = c.Receive(result)
_, err = receive(out_parameters)
return err
}

View File

@ -58,6 +58,7 @@ type Method struct {
// Error represents an error defined in the interface description.
type Error struct {
Name string
Doc string
Type *Type
}
@ -393,6 +394,7 @@ func (p *parser) readError(idl *IDL) (*Error, error) {
e := &Error{}
p.advance()
e.Doc = p.lastComment.String()
e.Name = p.readTypeName()
if e.Name == "" {
return nil, fmt.Errorf("missing error name")

View File

@ -23,7 +23,7 @@ type serviceCall struct {
Method string `json:"method"`
Parameters *json.RawMessage `json:"parameters,omitempty"`
More bool `json:"more,omitempty"`
OneShot bool `json:"oneshot,omitempty"`
Oneway bool `json:"oneway,omitempty"`
}
type serviceReply struct {

View File

@ -140,7 +140,7 @@ func (s *VarlinkInterface) VarlinkDispatch(call Call, methodname string) error {
if !call.WantsMore() {
return fmt.Errorf("More flag not passed")
}
if call.IsOneShot() {
if call.IsOneway() {
return fmt.Errorf("OneShot flag set")
}
call.Continues = true