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) test/checkseccomp/checkseccomp: .gopathok $(wildcard test/checkseccomp/*.go)
$(GO) build $(LDFLAGS) -tags "$(BUILDTAGS) containers_image_ostree_stub" -o $@ $(PROJECT)/test/checkseccomp $(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 $(GO) build -i $(LDFLAGS_PODMAN) -tags "$(BUILDTAGS)" -o bin/$@ $(PROJECT)/cmd/podman
clean: clean:
@ -251,6 +251,7 @@ install.tools: .install.gitvalidation .install.gometalinter .install.md2man
fi fi
varlink_generate: .gopathok cmd/podman/varlink/ioprojectatomicpodman.go varlink_generate: .gopathok cmd/podman/varlink/ioprojectatomicpodman.go
varlink_api_generate: .gopathok API.md
.PHONY: install.libseccomp.sudo .PHONY: install.libseccomp.sudo
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 cmd/podman/varlink/ioprojectatomicpodman.go: cmd/podman/varlink/io.projectatomic.podman.varlink
$(GO) generate ./cmd/podman/varlink/... $(GO) generate ./cmd/podman/varlink/...
API.md: cmd/podman/varlink/io.projectatomic.podman.varlink
$(GO) generate ./docs/...
validate: gofmt .gitvalidation validate: gofmt .gitvalidation
.PHONY: \ .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 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. 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](docs/tutorials)**
Tutorials on the Podman utility. Tutorials on the Podman utility.

View File

@ -18,6 +18,12 @@ type NotImplemented (
type StringResponse ( type StringResponse (
message: string 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 # ImageInList describes the structure that is returned in
# ListImages. # ListImages.
@ -117,54 +123,254 @@ type ContainerNameSpace (
ipc: string 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) method Ping() -> (ping: StringResponse)
# GetVersion returns a Version structure describing the libpod setup on their
# system.
method GetVersion() -> (version: Version) 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) 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) method GetContainer(name: string) -> (container: ListContainerData)
# This method has not been implemented yet.
method CreateContainer() -> (notimplemented: NotImplemented) 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) 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) 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 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) 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) method GetContainerStats(name: string) -> (container: ContainerStats)
# This method has not be implemented yet.
method ResizeContainerTty() -> (notimplemented: NotImplemented) method ResizeContainerTty() -> (notimplemented: NotImplemented)
# This method has not be implemented yet.
method StartContainer() -> (notimplemented: NotImplemented) 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) 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) 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) 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.
# See also [UnpauseContainer](UnpauseContainer).
method PauseContainer(name: string) -> (container: string) 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) method UnpauseContainer(name: string) -> (container: string)
# This method has not be implemented yet.
method AttachToContainer() -> (notimplemented: NotImplemented) 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) 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) 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) 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) method ListImages() -> (images: []ImageInList)
# This function is not implemented yet.
method BuildImage() -> (notimplemented: NotImplemented) method BuildImage() -> (notimplemented: NotImplemented)
# 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
# be returned if the image cannot be found.
method InspectImage(name: string) -> (image: string) 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 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) 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) 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) method DeleteUnusedImages() -> (images: []string)
# This method is not implemented.
method CreateFromContainer() -> (notimplemented: NotImplemented) 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 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) method PullImage(name: string) -> (id: string)
# Something failed # ImageNotFound means the image could not be found by the provided name or ID in local storage.
error ActionFailed (reason: string)
error ImageNotFound (name: string) 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) 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) error ErrorOccurred (reason: string)
# RuntimeErrors generally means a runtime could not be found or gotten.
error RuntimeError (reason: string) 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" "syscall"
"time" "time"
"github.com/containers/storage/pkg/archive"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/projectatomic/libpod/cmd/podman/batchcontainer" "github.com/projectatomic/libpod/cmd/podman/batchcontainer"
"github.com/projectatomic/libpod/cmd/podman/libpodruntime" "github.com/projectatomic/libpod/cmd/podman/libpodruntime"
@ -195,12 +196,18 @@ func (i *LibpodAPI) ListContainerChanges(call ioprojectatomicpodman.VarlinkCall,
if err != nil { if err != nil {
return call.ReplyErrorOccurred(err.Error()) return call.ReplyErrorOccurred(err.Error())
} }
result := ioprojectatomicpodman.ContainerChanges{}
m := make(map[string]string)
for _, change := range changes { 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 ... // 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 { if err := newImage.PushImage(getContext(), destname, "", "", "", nil, false, so, &dockerRegistryOptions); err != nil {
return call.ReplyErrorOccurred(err.Error()) 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. // 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 { if err := newImage.TagImage(tag); err != nil {
return call.ReplyErrorOccurred(err.Error()) 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 // 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 { if err := newImage.PushImage(getContext(), destination, "", "", "", nil, compress, image.SigningOptions{}, &image.DockerRegistryOptions{}); err != nil {
return call.ReplyErrorOccurred(err.Error()) return call.ReplyErrorOccurred(err.Error())
} }
return call.ReplyExportImage() return call.ReplyExportImage(newImage.ID())
} }
// PullImage pulls an image from a registry to the image store. // 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("\n\n")
} }
b.WriteString("// Client method calls and reply readers\n") b.WriteString("// Client method calls\n")
for _, m := range midl.Methods { 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 { for _, field := range m.In.Fields {
b.WriteString(", " + field.Name + "_ ") b.WriteString(", " + field.Name + "_in_ ")
writeType(&b, field.Type, false, 1) 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 { if len(m.In.Fields) > 0 {
b.WriteString("\tvar in ") b.WriteString("\tvar in ")
writeType(&b, m.In, true, 1) writeType(&b, m.In, true, 1)
@ -112,58 +149,57 @@ func generateTemplate(description string) (string, []byte, error) {
case idl.TypeStruct, idl.TypeArray, idl.TypeMap: case idl.TypeStruct, idl.TypeArray, idl.TypeMap:
b.WriteString("\tin." + strings.Title(field.Name) + " = ") b.WriteString("\tin." + strings.Title(field.Name) + " = ")
writeType(&b, field.Type, true, 1) writeType(&b, field.Type, true, 1)
b.WriteString("(" + field.Name + "_)\n") b.WriteString("(" + field.Name + "_in_)\n")
default: 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" + b.WriteString("\treceive, err := c.Send(\"" + midl.Name + "." + m.Name + "\", in, flags)\n")
"}\n\n")
} else { } else {
b.WriteString("\treturn c__.Send(\"" + midl.Name + "." + m.Name + "\", nil, more__, oneway__)\n" + b.WriteString("\treceive, err := c.Send(\"" + midl.Name + "." + m.Name + "\", nil, flags)\n")
"}\n\n")
} }
b.WriteString("if err != nil {\n" +
b.WriteString("func Read" + m.Name + "_(c__ *varlink.Connection") "\treturn nil, err\n" +
"}\n")
b.WriteString("\treturn func() (")
for _, field := range m.Out.Fields { for _, field := range m.Out.Fields {
b.WriteString(", " + field.Name + "_ *") b.WriteString(field.Name + "_out_ ")
writeType(&b, field.Type, false, 1) 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 { if len(m.Out.Fields) > 0 {
b.WriteString("\tvar out ") b.WriteString("\t\tvar out ")
writeType(&b, m.Out, true, 1) writeType(&b, m.Out, true, 2)
b.WriteString("\n") b.WriteString("\n")
b.WriteString("\tcontinues_, err := c__.Receive(&out)\n") b.WriteString("\t\tflags, err = receive(&out)\n")
} else { } else {
b.WriteString("\tcontinues_, err := c__.Receive(nil)\n") b.WriteString("\t\tflags, err = receive(nil)\n")
} }
b.WriteString("\tif err != nil {\n" + b.WriteString("\t\tif err != nil {\n" +
"\t\treturn false, err\n" + "\t\t\treturn\n" +
"\t}\n") "\t\t}\n")
for _, field := range m.Out.Fields { for _, field := range m.Out.Fields {
b.WriteString("\tif " + field.Name + "_ != nil {\n") b.WriteString("\t\t" + field.Name + "_out_ = ")
switch field.Type.Kind { switch field.Type.Kind {
case idl.TypeStruct, idl.TypeArray, idl.TypeMap: case idl.TypeStruct, idl.TypeArray, idl.TypeMap:
b.WriteString("\t\t*" + field.Name + "_ = ")
writeType(&b, field.Type, false, 2) writeType(&b, field.Type, false, 2)
b.WriteString(" (out." + strings.Title(field.Name) + ")\n") b.WriteString("(out." + strings.Title(field.Name) + ")\n")
default: 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("\t\treturn\n" +
b.WriteString("\treturn continues_, nil\n" + "\t}, nil\n")
"}\n\n") b.WriteString("}\n\n")
} }
b.WriteString("// Service interface with all methods\n") b.WriteString("// Service interface with all methods\n")
b.WriteString("type " + pkgname + "Interface interface {\n") b.WriteString("type " + pkgname + "Interface interface {\n")
for _, m := range midl.Methods { 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 { for _, field := range m.In.Fields {
b.WriteString(", " + field.Name + "_ ") b.WriteString(", " + field.Name + "_ ")
writeType(&b, field.Type, false, 1) 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") b.WriteString("// Reply methods for all varlink errors\n")
for _, e := range midl.Errors { 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 { for i, field := range e.Type.Fields {
if i > 0 { if i > 0 {
b.WriteString(", ") 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("\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 { } 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("}\n\n")
} }
b.WriteString("// Reply methods for all varlink methods\n") b.WriteString("// Reply methods for all varlink methods\n")
for _, m := range midl.Methods { 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 { for i, field := range m.Out.Fields {
if i > 0 { if i > 0 {
b.WriteString(", ") 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("\tout." + strings.Title(field.Name) + " = " + field.Name + "_\n")
} }
} }
b.WriteString("\treturn c__.Reply(&out)\n") b.WriteString("\treturn c.Reply(&out)\n")
} else { } else {
b.WriteString("\treturn c__.Reply(nil)\n") b.WriteString("\treturn c.Reply(nil)\n")
} }
b.WriteString("}\n\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 { 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 { for _, field := range m.In.Fields {
b.WriteString(", " + field.Name + "_ ") b.WriteString(", " + field.Name + "_ ")
writeType(&b, field.Type, false, 1) writeType(&b, field.Type, false, 1)
} }
b.WriteString(") error {\n" + b.WriteString(") error {\n" +
"\treturn c__.ReplyMethodNotImplemented(\"" + m.Name + "\")\n" + "\treturn c.ReplyMethodNotImplemented(\"" + midl.Name + "." + m.Name + "\")\n" +
"}\n\n") "}\n\n")
} }
b.WriteString("// Method call dispatcher\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") "\tswitch methodname {\n")
for _, m := range midl.Methods { for _, m := range midl.Methods {
b.WriteString("\tcase \"" + m.Name + "\":\n") b.WriteString("\tcase \"" + m.Name + "\":\n")
@ -266,7 +302,7 @@ func generateTemplate(description string) (string, []byte, error) {
"\t\tif err != nil {\n" + "\t\tif err != nil {\n" +
"\t\t\treturn call.ReplyInvalidParameter(\"parameters\")\n" + "\t\t\treturn call.ReplyInvalidParameter(\"parameters\")\n" +
"\t\t}\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 { if len(m.In.Fields) > 0 {
for _, field := range m.In.Fields { for _, field := range m.In.Fields {
switch field.Type.Kind { switch field.Type.Kind {
@ -282,7 +318,7 @@ func generateTemplate(description string) (string, []byte, error) {
} }
b.WriteString(")\n") b.WriteString(")\n")
} else { } 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") b.WriteString("\n")
} }
@ -292,11 +328,11 @@ func generateTemplate(description string) (string, []byte, error) {
"}\n\n") "}\n\n")
b.WriteString("// Varlink interface name\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") "\treturn `" + midl.Name + "`\n" + "}\n\n")
b.WriteString("// Varlink interface description\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") "\treturn `" + midl.Description + "\n`\n}\n\n")
b.WriteString("// Service interface\n") b.WriteString("// Service interface\n")

View File

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

View File

@ -7,6 +7,15 @@ import (
"strings" "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. // Error is a varlink error returned from a method call.
type Error struct { type Error struct {
Name string Name string
@ -26,8 +35,10 @@ type Connection struct {
writer *bufio.Writer writer *bufio.Writer
} }
// Send sends a method call. // Send sends a method call. It returns a receive() function which is called to retrieve the method reply.
func (c *Connection) Send(method string, parameters interface{}, more bool, oneway bool) error { // 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 { type call struct {
Method string `json:"method"` Method string `json:"method"`
Parameters interface{} `json:"parameters,omitempty"` 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"` Oneway bool `json:"oneway,omitempty"`
} }
if more && oneway { if (flags&More != 0) && (flags&Oneway != 0) {
return &Error{ return nil, &Error{
Name: "org.varlink.InvalidParameter", Name: "org.varlink.InvalidParameter",
Parameters: "oneway", Parameters: "oneway",
} }
@ -45,64 +56,73 @@ func (c *Connection) Send(method string, parameters interface{}, more bool, onew
m := call{ m := call{
Method: method, Method: method,
Parameters: parameters, Parameters: parameters,
More: more, More: flags&More != 0,
Oneway: oneway, Oneway: flags&Oneway != 0,
} }
b, err := json.Marshal(m) b, err := json.Marshal(m)
if err != nil { if err != nil {
return err return nil, err
} }
b = append(b, 0) b = append(b, 0)
_, err = c.writer.Write(b) _, err = c.writer.Write(b)
if err != nil { if err != nil {
return err return nil, err
} }
return c.writer.Flush() err = 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')
if err != nil { if err != nil {
return false, err return nil, err
} }
var m reply receive := func(out_parameters interface{}) (uint64, error) {
err = json.Unmarshal(out[:len(out)-1], &m) type reply struct {
if err != nil { Parameters *json.RawMessage `json:"parameters"`
return false, err Continues bool `json:"continues"`
} Error string `json:"error"`
if m.Error != "" {
return false, &Error{
Name: m.Error,
Parameters: m.Parameters,
} }
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 receive, nil
return m.Continues, json.Unmarshal(*m.Parameters, parameters)
}
return m.Continues, nil
} }
// Call sends a method call and returns the result of the call. // Call sends a method call and returns the method reply.
func (c *Connection) Call(method string, parameters interface{}, result interface{}) error { func (c *Connection) Call(method string, parameters interface{}, out_parameters interface{}) error {
err := c.Send(method, &parameters, false, false) receive, err := c.Send(method, &parameters, 0)
if err != nil { if err != nil {
return err return err
} }
_, err = c.Receive(result) _, err = receive(out_parameters)
return err return err
} }

View File

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

View File

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

View File

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