mirror of
https://github.com/containers/podman.git
synced 2025-06-20 09:03:43 +08:00
podman-remote create|run
add the ability to create and run containers via the podman-remote client. we now create an intermediate layer from the the create/run cli flags. the intermediate layer can be converted into a createconfig or into a varlink struct. Once transported, the varlink struct can be converted back to an intermediate layer and then to a createconfig. remote terminals are not supported yet. Signed-off-by: baude <bbaude@redhat.com>
This commit is contained in:
239
API.md
239
API.md
@ -27,6 +27,8 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in
|
|||||||
|
|
||||||
[func CreateContainer(create: Create) string](#CreateContainer)
|
[func CreateContainer(create: Create) string](#CreateContainer)
|
||||||
|
|
||||||
|
[func CreateFromCC(in: []string) string](#CreateFromCC)
|
||||||
|
|
||||||
[func CreatePod(create: PodCreate) string](#CreatePod)
|
[func CreatePod(create: PodCreate) string](#CreatePod)
|
||||||
|
|
||||||
[func DeleteStoppedContainers() []string](#DeleteStoppedContainers)
|
[func DeleteStoppedContainers() []string](#DeleteStoppedContainers)
|
||||||
@ -177,16 +179,10 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in
|
|||||||
|
|
||||||
[type Create](#Create)
|
[type Create](#Create)
|
||||||
|
|
||||||
[type CreateResourceConfig](#CreateResourceConfig)
|
|
||||||
|
|
||||||
[type DiffInfo](#DiffInfo)
|
[type DiffInfo](#DiffInfo)
|
||||||
|
|
||||||
[type Event](#Event)
|
[type Event](#Event)
|
||||||
|
|
||||||
[type IDMap](#IDMap)
|
|
||||||
|
|
||||||
[type IDMappingOptions](#IDMappingOptions)
|
|
||||||
|
|
||||||
[type Image](#Image)
|
[type Image](#Image)
|
||||||
|
|
||||||
[type ImageHistory](#ImageHistory)
|
[type ImageHistory](#ImageHistory)
|
||||||
@ -338,16 +334,12 @@ development of Podman only and generally should not be used.
|
|||||||
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
|
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
|
||||||
|
|
||||||
method CreateContainer(create: [Create](#Create)) [string](https://godoc.org/builtin#string)</div>
|
method CreateContainer(create: [Create](#Create)) [string](https://godoc.org/builtin#string)</div>
|
||||||
CreateContainer creates a new container from an image. It uses a [Create](#Create) type for input. The minimum
|
CreateContainer creates a new container from an image. It uses a [Create](#Create) type for input.
|
||||||
input required for CreateContainer is an image name. If the image name is not found, an [ImageNotFound](#ImageNotFound)
|
### <a name="CreateFromCC"></a>func CreateFromCC
|
||||||
error will be returned. Otherwise, the ID of the newly created container will be returned.
|
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
|
||||||
#### Example
|
|
||||||
~~~
|
method CreateFromCC(in: [[]string](#[]string)) [string](https://godoc.org/builtin#string)</div>
|
||||||
$ varlink call unix:/run/podman/io.podman/io.podman.CreateContainer '{"create": {"image": "alpine"}}'
|
This call is for the development of Podman only and should not be used.
|
||||||
{
|
|
||||||
"container": "8759dafbc0a4dc3bcfb57eeb72e4331eb73c5cc09ab968e65ce45b9ad5c4b6bb"
|
|
||||||
}
|
|
||||||
~~~
|
|
||||||
### <a name="CreatePod"></a>func CreatePod
|
### <a name="CreatePod"></a>func CreatePod
|
||||||
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
|
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
|
||||||
|
|
||||||
@ -1272,188 +1264,199 @@ block_input [int](https://godoc.org/builtin#int)
|
|||||||
pids [int](https://godoc.org/builtin#int)
|
pids [int](https://godoc.org/builtin#int)
|
||||||
### <a name="Create"></a>type Create
|
### <a name="Create"></a>type Create
|
||||||
|
|
||||||
Create is an input structure for creating containers. It closely resembles the
|
Create is an input structure for creating containers.
|
||||||
CreateConfig structure in libpod/pkg/spec.
|
|
||||||
|
|
||||||
args [[]string](#[]string)
|
args [[]string](#[]string)
|
||||||
|
|
||||||
cap_add [[]string](#[]string)
|
addHost [](#)
|
||||||
|
|
||||||
cap_drop [[]string](#[]string)
|
annotation [](#)
|
||||||
|
|
||||||
conmon_pidfile [string](https://godoc.org/builtin#string)
|
attach [](#)
|
||||||
|
|
||||||
cgroup_parent [string](https://godoc.org/builtin#string)
|
blkioWeight [](#)
|
||||||
|
|
||||||
command [[]string](#[]string)
|
blkioWeightDevice [](#)
|
||||||
|
|
||||||
detach [bool](https://godoc.org/builtin#bool)
|
capAdd [](#)
|
||||||
|
|
||||||
devices [[]string](#[]string)
|
capDrop [](#)
|
||||||
|
|
||||||
dns_opt [[]string](#[]string)
|
cgroupParent [](#)
|
||||||
|
|
||||||
dns_search [[]string](#[]string)
|
cidFile [](#)
|
||||||
|
|
||||||
dns_servers [[]string](#[]string)
|
conmonPidfile [](#)
|
||||||
|
|
||||||
entrypoint [[]string](#[]string)
|
command [](#)
|
||||||
|
|
||||||
env [map[string]](#map[string])
|
cpuPeriod [](#)
|
||||||
|
|
||||||
exposed_ports [[]string](#[]string)
|
cpuQuota [](#)
|
||||||
|
|
||||||
gidmap [[]string](#[]string)
|
cpuRtPeriod [](#)
|
||||||
|
|
||||||
group_add [[]string](#[]string)
|
cpuRtRuntime [](#)
|
||||||
|
|
||||||
host_add [[]string](#[]string)
|
cpuShares [](#)
|
||||||
|
|
||||||
hostname [string](https://godoc.org/builtin#string)
|
cpus [](#)
|
||||||
|
|
||||||
image [string](https://godoc.org/builtin#string)
|
cpuSetCpus [](#)
|
||||||
|
|
||||||
image_id [string](https://godoc.org/builtin#string)
|
cpuSetMems [](#)
|
||||||
|
|
||||||
init [bool](https://godoc.org/builtin#bool)
|
detach [](#)
|
||||||
|
|
||||||
init_path [string](https://godoc.org/builtin#string)
|
detachKeys [](#)
|
||||||
|
|
||||||
builtin_imgvolumes [[]string](#[]string)
|
device [](#)
|
||||||
|
|
||||||
id_mappings [IDMappingOptions](#IDMappingOptions)
|
deviceReadBps [](#)
|
||||||
|
|
||||||
image_volume_type [string](https://godoc.org/builtin#string)
|
deviceReadIops [](#)
|
||||||
|
|
||||||
interactive [bool](https://godoc.org/builtin#bool)
|
deviceWriteBps [](#)
|
||||||
|
|
||||||
ipc_mode [string](https://godoc.org/builtin#string)
|
deviceWriteIops [](#)
|
||||||
|
|
||||||
labels [map[string]](#map[string])
|
dns [](#)
|
||||||
|
|
||||||
log_driver [string](https://godoc.org/builtin#string)
|
dnsOpt [](#)
|
||||||
|
|
||||||
log_driver_opt [[]string](#[]string)
|
dnsSearch [](#)
|
||||||
|
|
||||||
name [string](https://godoc.org/builtin#string)
|
dnsServers [](#)
|
||||||
|
|
||||||
net_mode [string](https://godoc.org/builtin#string)
|
entrypoint [](#)
|
||||||
|
|
||||||
network [string](https://godoc.org/builtin#string)
|
env [](#)
|
||||||
|
|
||||||
pid_mode [string](https://godoc.org/builtin#string)
|
envFile [](#)
|
||||||
|
|
||||||
pod [string](https://godoc.org/builtin#string)
|
expose [](#)
|
||||||
|
|
||||||
privileged [bool](https://godoc.org/builtin#bool)
|
gidmap [](#)
|
||||||
|
|
||||||
publish [[]string](#[]string)
|
groupadd [](#)
|
||||||
|
|
||||||
publish_all [bool](https://godoc.org/builtin#bool)
|
healthcheckCommand [](#)
|
||||||
|
|
||||||
quiet [bool](https://godoc.org/builtin#bool)
|
healthcheckInterval [](#)
|
||||||
|
|
||||||
readonly_rootfs [bool](https://godoc.org/builtin#bool)
|
healthcheckRetries [](#)
|
||||||
|
|
||||||
resources [CreateResourceConfig](#CreateResourceConfig)
|
healthcheckStartPeriod [](#)
|
||||||
|
|
||||||
rm [bool](https://godoc.org/builtin#bool)
|
healthcheckTimeout [](#)
|
||||||
|
|
||||||
shm_dir [string](https://godoc.org/builtin#string)
|
hostname [](#)
|
||||||
|
|
||||||
stop_signal [int](https://godoc.org/builtin#int)
|
imageVolume [](#)
|
||||||
|
|
||||||
stop_timeout [int](https://godoc.org/builtin#int)
|
init [](#)
|
||||||
|
|
||||||
subuidmap [string](https://godoc.org/builtin#string)
|
initPath [](#)
|
||||||
|
|
||||||
subgidmap [string](https://godoc.org/builtin#string)
|
interactive [](#)
|
||||||
|
|
||||||
subuidname [string](https://godoc.org/builtin#string)
|
ip [](#)
|
||||||
|
|
||||||
subgidname [string](https://godoc.org/builtin#string)
|
ipc [](#)
|
||||||
|
|
||||||
sys_ctl [map[string]](#map[string])
|
kernelMemory [](#)
|
||||||
|
|
||||||
tmpfs [[]string](#[]string)
|
label [](#)
|
||||||
|
|
||||||
tty [bool](https://godoc.org/builtin#bool)
|
labelFile [](#)
|
||||||
|
|
||||||
uidmap [[]string](#[]string)
|
logDriver [](#)
|
||||||
|
|
||||||
userns_mode [string](https://godoc.org/builtin#string)
|
logOpt [](#)
|
||||||
|
|
||||||
user [string](https://godoc.org/builtin#string)
|
macAddress [](#)
|
||||||
|
|
||||||
uts_mode [string](https://godoc.org/builtin#string)
|
memory [](#)
|
||||||
|
|
||||||
volumes [[]string](#[]string)
|
memoryReservation [](#)
|
||||||
|
|
||||||
work_dir [string](https://godoc.org/builtin#string)
|
memorySwap [](#)
|
||||||
|
|
||||||
mount_label [string](https://godoc.org/builtin#string)
|
memorySwappiness [](#)
|
||||||
|
|
||||||
process_label [string](https://godoc.org/builtin#string)
|
name [](#)
|
||||||
|
|
||||||
no_new_privs [bool](https://godoc.org/builtin#bool)
|
net [](#)
|
||||||
|
|
||||||
apparmor_profile [string](https://godoc.org/builtin#string)
|
network [](#)
|
||||||
|
|
||||||
seccomp_profile_path [string](https://godoc.org/builtin#string)
|
noHosts [](#)
|
||||||
|
|
||||||
security_opts [[]string](#[]string)
|
oomKillDisable [](#)
|
||||||
### <a name="CreateResourceConfig"></a>type CreateResourceConfig
|
|
||||||
|
|
||||||
CreateResourceConfig is an input structure used to describe host attributes during
|
oomScoreAdj [](#)
|
||||||
container creation. It is only valid inside a [Create](#Create) type.
|
|
||||||
|
|
||||||
blkio_weight [int](https://godoc.org/builtin#int)
|
pid [](#)
|
||||||
|
|
||||||
blkio_weight_device [[]string](#[]string)
|
pidsLimit [](#)
|
||||||
|
|
||||||
cpu_period [int](https://godoc.org/builtin#int)
|
pod [](#)
|
||||||
|
|
||||||
cpu_quota [int](https://godoc.org/builtin#int)
|
privileged [](#)
|
||||||
|
|
||||||
cpu_rt_period [int](https://godoc.org/builtin#int)
|
publish [](#)
|
||||||
|
|
||||||
cpu_rt_runtime [int](https://godoc.org/builtin#int)
|
publishAll [](#)
|
||||||
|
|
||||||
cpu_shares [int](https://godoc.org/builtin#int)
|
quiet [](#)
|
||||||
|
|
||||||
cpus [float](https://golang.org/src/builtin/builtin.go#L58)
|
readonly [](#)
|
||||||
|
|
||||||
cpuset_cpus [string](https://godoc.org/builtin#string)
|
restart [](#)
|
||||||
|
|
||||||
cpuset_mems [string](https://godoc.org/builtin#string)
|
rm [](#)
|
||||||
|
|
||||||
device_read_bps [[]string](#[]string)
|
rootfs [](#)
|
||||||
|
|
||||||
device_read_iops [[]string](#[]string)
|
securityOpt [](#)
|
||||||
|
|
||||||
device_write_bps [[]string](#[]string)
|
shmSize [](#)
|
||||||
|
|
||||||
device_write_iops [[]string](#[]string)
|
stopSignal [](#)
|
||||||
|
|
||||||
disable_oomkiller [bool](https://godoc.org/builtin#bool)
|
stopTimeout [](#)
|
||||||
|
|
||||||
kernel_memory [int](https://godoc.org/builtin#int)
|
storageOpt [](#)
|
||||||
|
|
||||||
memory [int](https://godoc.org/builtin#int)
|
subuidname [](#)
|
||||||
|
|
||||||
memory_reservation [int](https://godoc.org/builtin#int)
|
subgidname [](#)
|
||||||
|
|
||||||
memory_swap [int](https://godoc.org/builtin#int)
|
sysctl [](#)
|
||||||
|
|
||||||
memory_swappiness [int](https://godoc.org/builtin#int)
|
systemd [](#)
|
||||||
|
|
||||||
oom_score_adj [int](https://godoc.org/builtin#int)
|
tmpfs [](#)
|
||||||
|
|
||||||
pids_limit [int](https://godoc.org/builtin#int)
|
tty [](#)
|
||||||
|
|
||||||
shm_size [int](https://godoc.org/builtin#int)
|
uidmap [](#)
|
||||||
|
|
||||||
ulimit [[]string](#[]string)
|
ulimit [](#)
|
||||||
|
|
||||||
|
user [](#)
|
||||||
|
|
||||||
|
userns [](#)
|
||||||
|
|
||||||
|
uts [](#)
|
||||||
|
|
||||||
|
mount [](#)
|
||||||
|
|
||||||
|
volume [](#)
|
||||||
|
|
||||||
|
volumesFrom [](#)
|
||||||
|
|
||||||
|
workDir [](#)
|
||||||
### <a name="DiffInfo"></a>type DiffInfo
|
### <a name="DiffInfo"></a>type DiffInfo
|
||||||
|
|
||||||
|
|
||||||
@ -1476,26 +1479,6 @@ status [string](https://godoc.org/builtin#string)
|
|||||||
time [string](https://godoc.org/builtin#string)
|
time [string](https://godoc.org/builtin#string)
|
||||||
|
|
||||||
type [string](https://godoc.org/builtin#string)
|
type [string](https://godoc.org/builtin#string)
|
||||||
### <a name="IDMap"></a>type IDMap
|
|
||||||
|
|
||||||
IDMap is used to describe user name spaces during container creation
|
|
||||||
|
|
||||||
container_id [int](https://godoc.org/builtin#int)
|
|
||||||
|
|
||||||
host_id [int](https://godoc.org/builtin#int)
|
|
||||||
|
|
||||||
size [int](https://godoc.org/builtin#int)
|
|
||||||
### <a name="IDMappingOptions"></a>type IDMappingOptions
|
|
||||||
|
|
||||||
IDMappingOptions is an input structure used to described ids during container creation.
|
|
||||||
|
|
||||||
host_uid_mapping [bool](https://godoc.org/builtin#bool)
|
|
||||||
|
|
||||||
host_gid_mapping [bool](https://godoc.org/builtin#bool)
|
|
||||||
|
|
||||||
uid_map [IDMap](#IDMap)
|
|
||||||
|
|
||||||
gid_map [IDMap](#IDMap)
|
|
||||||
### <a name="Image"></a>type Image
|
### <a name="Image"></a>type Image
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||||
"github.com/containers/libpod/libpod"
|
"github.com/containers/libpod/libpod"
|
||||||
|
"github.com/containers/libpod/pkg/adapter"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
@ -78,7 +79,7 @@ func attachCmd(c *cliconfig.AttachValues) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the container is in a pod, also set to recursively start dependencies
|
// If the container is in a pod, also set to recursively start dependencies
|
||||||
if err := startAttachCtr(ctr, os.Stdout, os.Stderr, inputStream, c.DetachKeys, c.SigProxy, false, ctr.PodID() != ""); err != nil && errors.Cause(err) != libpod.ErrDetach {
|
if err := adapter.StartAttachCtr(getContext(), ctr, os.Stdout, os.Stderr, inputStream, c.DetachKeys, c.SigProxy, false, ctr.PodID() != ""); err != nil && errors.Cause(err) != libpod.ErrDetach {
|
||||||
return errors.Wrapf(err, "error attaching to container %s", ctr.ID())
|
return errors.Wrapf(err, "error attaching to container %s", ctr.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
21
cmd/podman/cliconfig/defaults.go
Normal file
21
cmd/podman/cliconfig/defaults.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package cliconfig
|
||||||
|
|
||||||
|
const (
|
||||||
|
// DefaultSystemD value
|
||||||
|
DefaultSystemD bool = true
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// DefaultHealthCheckInterval default value
|
||||||
|
DefaultHealthCheckInterval = "30s"
|
||||||
|
// DefaultHealthCheckRetries default value
|
||||||
|
DefaultHealthCheckRetries uint = 3
|
||||||
|
// DefaultHealthCheckStartPeriod default value
|
||||||
|
DefaultHealthCheckStartPeriod = "0s"
|
||||||
|
// DefaultHealthCheckTimeout default value
|
||||||
|
DefaultHealthCheckTimeout = "30s"
|
||||||
|
// DefaultImageVolume default value
|
||||||
|
DefaultImageVolume = "bind"
|
||||||
|
// DefaultShmSize default value
|
||||||
|
DefaultShmSize = "65536k"
|
||||||
|
)
|
@ -13,7 +13,6 @@ func getMainCommands() []*cobra.Command {
|
|||||||
rootCommands := []*cobra.Command{
|
rootCommands := []*cobra.Command{
|
||||||
_attachCommand,
|
_attachCommand,
|
||||||
_commitCommand,
|
_commitCommand,
|
||||||
_createCommand,
|
|
||||||
_execCommand,
|
_execCommand,
|
||||||
_generateCommand,
|
_generateCommand,
|
||||||
_playCommand,
|
_playCommand,
|
||||||
@ -26,7 +25,6 @@ func getMainCommands() []*cobra.Command {
|
|||||||
_refreshCommand,
|
_refreshCommand,
|
||||||
_restartCommand,
|
_restartCommand,
|
||||||
_rmCommand,
|
_rmCommand,
|
||||||
_runCommand,
|
|
||||||
_searchCommand,
|
_searchCommand,
|
||||||
_startCommand,
|
_startCommand,
|
||||||
_statsCommand,
|
_statsCommand,
|
||||||
@ -56,7 +54,6 @@ func getContainerSubCommands() []*cobra.Command {
|
|||||||
_checkpointCommand,
|
_checkpointCommand,
|
||||||
_cleanupCommand,
|
_cleanupCommand,
|
||||||
_commitCommand,
|
_commitCommand,
|
||||||
_createCommand,
|
|
||||||
_execCommand,
|
_execCommand,
|
||||||
_exportCommand,
|
_exportCommand,
|
||||||
_killCommand,
|
_killCommand,
|
||||||
@ -68,7 +65,6 @@ func getContainerSubCommands() []*cobra.Command {
|
|||||||
_restartCommand,
|
_restartCommand,
|
||||||
_restoreCommand,
|
_restoreCommand,
|
||||||
_rmCommand,
|
_rmCommand,
|
||||||
_runCommand,
|
|
||||||
_runlabelCommand,
|
_runlabelCommand,
|
||||||
_startCommand,
|
_startCommand,
|
||||||
_statsCommand,
|
_statsCommand,
|
||||||
|
@ -294,19 +294,19 @@ func getCreateFlags(c *cliconfig.PodmanCommand) {
|
|||||||
"set a healthcheck command for the container ('none' disables the existing healthcheck)",
|
"set a healthcheck command for the container ('none' disables the existing healthcheck)",
|
||||||
)
|
)
|
||||||
createFlags.String(
|
createFlags.String(
|
||||||
"healthcheck-interval", "30s",
|
"healthcheck-interval", cliconfig.DefaultHealthCheckInterval,
|
||||||
"set an interval for the healthchecks (a value of disable results in no automatic timer setup)",
|
"set an interval for the healthchecks (a value of disable results in no automatic timer setup)",
|
||||||
)
|
)
|
||||||
createFlags.Uint(
|
createFlags.Uint(
|
||||||
"healthcheck-retries", 3,
|
"healthcheck-retries", cliconfig.DefaultHealthCheckRetries,
|
||||||
"the number of retries allowed before a healthcheck is considered to be unhealthy",
|
"the number of retries allowed before a healthcheck is considered to be unhealthy",
|
||||||
)
|
)
|
||||||
createFlags.String(
|
createFlags.String(
|
||||||
"healthcheck-start-period", "0s",
|
"healthcheck-start-period", cliconfig.DefaultHealthCheckStartPeriod,
|
||||||
"the initialization time needed for a container to bootstrap",
|
"the initialization time needed for a container to bootstrap",
|
||||||
)
|
)
|
||||||
createFlags.String(
|
createFlags.String(
|
||||||
"healthcheck-timeout", "30s",
|
"healthcheck-timeout", cliconfig.DefaultHealthCheckTimeout,
|
||||||
"the maximum time allowed to complete the healthcheck before an interval is considered failed",
|
"the maximum time allowed to complete the healthcheck before an interval is considered failed",
|
||||||
)
|
)
|
||||||
createFlags.StringP(
|
createFlags.StringP(
|
||||||
@ -314,7 +314,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) {
|
|||||||
"Set container hostname",
|
"Set container hostname",
|
||||||
)
|
)
|
||||||
createFlags.String(
|
createFlags.String(
|
||||||
"image-volume", "bind",
|
"image-volume", cliconfig.DefaultImageVolume,
|
||||||
"Tells podman how to handle the builtin image volumes. The options are: 'bind', 'tmpfs', or 'ignore'",
|
"Tells podman how to handle the builtin image volumes. The options are: 'bind', 'tmpfs', or 'ignore'",
|
||||||
)
|
)
|
||||||
createFlags.Bool(
|
createFlags.Bool(
|
||||||
@ -451,7 +451,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) {
|
|||||||
"Security Options (default [])",
|
"Security Options (default [])",
|
||||||
)
|
)
|
||||||
createFlags.String(
|
createFlags.String(
|
||||||
"shm-size", "65536k",
|
"shm-size", cliconfig.DefaultShmSize,
|
||||||
"Size of `/dev/shm`. The format is `<number><unit>`",
|
"Size of `/dev/shm`. The format is `<number><unit>`",
|
||||||
)
|
)
|
||||||
createFlags.String(
|
createFlags.String(
|
||||||
@ -480,7 +480,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) {
|
|||||||
"Sysctl options (default [])",
|
"Sysctl options (default [])",
|
||||||
)
|
)
|
||||||
createFlags.Bool(
|
createFlags.Bool(
|
||||||
"systemd", true,
|
"systemd", cliconfig.DefaultSystemD,
|
||||||
"Run container in systemd mode if the command executable is systemd or init",
|
"Run container in systemd mode if the command executable is systemd or init",
|
||||||
)
|
)
|
||||||
createFlags.StringSlice(
|
createFlags.StringSlice(
|
||||||
|
@ -53,8 +53,10 @@ var (
|
|||||||
_containerExistsCommand,
|
_containerExistsCommand,
|
||||||
_contInspectSubCommand,
|
_contInspectSubCommand,
|
||||||
_diffCommand,
|
_diffCommand,
|
||||||
|
_createCommand,
|
||||||
_listSubCommand,
|
_listSubCommand,
|
||||||
_logsCommand,
|
_logsCommand,
|
||||||
|
_runCommand,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -4,8 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
"github.com/containers/libpod/pkg/adapter"
|
||||||
"github.com/containers/libpod/cmd/podman/shared"
|
|
||||||
"github.com/opentracing/opentracing-go"
|
"github.com/opentracing/opentracing-go"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@ -52,18 +51,17 @@ func createCmd(c *cliconfig.CreateValues) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "error creating libpod runtime")
|
return errors.Wrapf(err, "error creating libpod runtime")
|
||||||
}
|
}
|
||||||
defer runtime.Shutdown(false)
|
defer runtime.Shutdown(false)
|
||||||
|
|
||||||
ctr, _, err := shared.CreateContainer(getContext(), &c.PodmanCommand, runtime)
|
cid, err := runtime.CreateContainer(getContext(), c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
fmt.Printf("%s\n", cid)
|
||||||
fmt.Printf("%s\n", ctr.ID())
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ var (
|
|||||||
var mainCommands = []*cobra.Command{
|
var mainCommands = []*cobra.Command{
|
||||||
_buildCommand,
|
_buildCommand,
|
||||||
_diffCommand,
|
_diffCommand,
|
||||||
|
_createCommand,
|
||||||
_eventsCommand,
|
_eventsCommand,
|
||||||
_exportCommand,
|
_exportCommand,
|
||||||
_historyCommand,
|
_historyCommand,
|
||||||
@ -54,6 +55,7 @@ var mainCommands = []*cobra.Command{
|
|||||||
_pullCommand,
|
_pullCommand,
|
||||||
_pushCommand,
|
_pushCommand,
|
||||||
&_rmiCommand,
|
&_rmiCommand,
|
||||||
|
_runCommand,
|
||||||
_saveCommand,
|
_saveCommand,
|
||||||
_stopCommand,
|
_stopCommand,
|
||||||
_tagCommand,
|
_tagCommand,
|
||||||
|
@ -1,20 +1,10 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
"github.com/containers/libpod/pkg/adapter"
|
||||||
"github.com/containers/libpod/cmd/podman/shared"
|
|
||||||
"github.com/containers/libpod/libpod"
|
|
||||||
opentracing "github.com/opentracing/opentracing-go"
|
opentracing "github.com/opentracing/opentracing-go"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -57,143 +47,12 @@ func runCmd(c *cliconfig.RunValues) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "error creating libpod runtime")
|
return errors.Wrapf(err, "error creating libpod runtime")
|
||||||
}
|
}
|
||||||
defer runtime.Shutdown(false)
|
defer runtime.Shutdown(false)
|
||||||
|
|
||||||
ctr, createConfig, err := shared.CreateContainer(getContext(), &c.PodmanCommand, runtime)
|
exitCode, err = runtime.Run(getContext(), c, exitCode)
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
|
||||||
|
|
||||||
if logrus.GetLevel() == logrus.DebugLevel {
|
|
||||||
cgroupPath, err := ctr.CGroupPath()
|
|
||||||
if err == nil {
|
|
||||||
logrus.Debugf("container %q has CgroupParent %q", ctr.ID(), cgroupPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx := getContext()
|
|
||||||
// Handle detached start
|
|
||||||
if createConfig.Detach {
|
|
||||||
// if the container was created as part of a pod, also start its dependencies, if any.
|
|
||||||
if err := ctr.Start(ctx, c.IsSet("pod")); err != nil {
|
|
||||||
// This means the command did not exist
|
|
||||||
exitCode = 127
|
|
||||||
if strings.Index(err.Error(), "permission denied") > -1 {
|
|
||||||
exitCode = 126
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("%s\n", ctr.ID())
|
|
||||||
exitCode = 0
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
outputStream := os.Stdout
|
|
||||||
errorStream := os.Stderr
|
|
||||||
inputStream := os.Stdin
|
|
||||||
|
|
||||||
// If -i is not set, clear stdin
|
|
||||||
if !c.Bool("interactive") {
|
|
||||||
inputStream = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// If attach is set, clear stdin/stdout/stderr and only attach requested
|
|
||||||
if c.IsSet("attach") || c.IsSet("a") {
|
|
||||||
outputStream = nil
|
|
||||||
errorStream = nil
|
|
||||||
if !c.Bool("interactive") {
|
|
||||||
inputStream = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
attachTo := c.StringSlice("attach")
|
|
||||||
for _, stream := range attachTo {
|
|
||||||
switch strings.ToLower(stream) {
|
|
||||||
case "stdout":
|
|
||||||
outputStream = os.Stdout
|
|
||||||
case "stderr":
|
|
||||||
errorStream = os.Stderr
|
|
||||||
case "stdin":
|
|
||||||
inputStream = os.Stdin
|
|
||||||
default:
|
|
||||||
return errors.Wrapf(libpod.ErrInvalidArg, "invalid stream %q for --attach - must be one of stdin, stdout, or stderr", stream)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if the container was created as part of a pod, also start its dependencies, if any.
|
|
||||||
if err := startAttachCtr(ctr, outputStream, errorStream, inputStream, c.String("detach-keys"), c.Bool("sig-proxy"), true, c.IsSet("pod")); err != nil {
|
|
||||||
// We've manually detached from the container
|
|
||||||
// Do not perform cleanup, or wait for container exit code
|
|
||||||
// Just exit immediately
|
|
||||||
if errors.Cause(err) == libpod.ErrDetach {
|
|
||||||
exitCode = 0
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// This means the command did not exist
|
|
||||||
exitCode = 127
|
|
||||||
if strings.Index(err.Error(), "permission denied") > -1 {
|
|
||||||
exitCode = 126
|
|
||||||
}
|
|
||||||
if c.IsSet("rm") {
|
|
||||||
if deleteError := runtime.RemoveContainer(ctx, ctr, true, false); deleteError != nil {
|
|
||||||
logrus.Errorf("unable to remove container %s after failing to start and attach to it", ctr.ID())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if ecode, err := ctr.Wait(); err != nil {
|
|
||||||
if errors.Cause(err) == libpod.ErrNoSuchCtr {
|
|
||||||
// The container may have been removed
|
|
||||||
// Go looking for an exit file
|
|
||||||
rtc, err := runtime.GetConfig()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
ctrExitCode, err := readExitFile(rtc.TmpDir, ctr.ID())
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("Cannot get exit code: %v", err)
|
|
||||||
exitCode = 127
|
|
||||||
} else {
|
|
||||||
exitCode = ctrExitCode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
exitCode = int(ecode)
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.IsSet("rm") {
|
|
||||||
runtime.RemoveContainer(ctx, ctr, false, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read a container's exit file
|
|
||||||
func readExitFile(runtimeTmp, ctrID string) (int, error) {
|
|
||||||
exitFile := filepath.Join(runtimeTmp, "exits", fmt.Sprintf("%s-old", ctrID))
|
|
||||||
|
|
||||||
logrus.Debugf("Attempting to read container %s exit code from file %s", ctrID, exitFile)
|
|
||||||
|
|
||||||
// Check if it exists
|
|
||||||
if _, err := os.Stat(exitFile); err != nil {
|
|
||||||
return 0, errors.Wrapf(err, "error getting exit file for container %s", ctrID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// File exists, read it in and convert to int
|
|
||||||
statusStr, err := ioutil.ReadFile(exitFile)
|
|
||||||
if err != nil {
|
|
||||||
return 0, errors.Wrapf(err, "error reading exit file for container %s", ctrID)
|
|
||||||
}
|
|
||||||
|
|
||||||
exitCode, err := strconv.Atoi(string(statusStr))
|
|
||||||
if err != nil {
|
|
||||||
return 0, errors.Wrapf(err, "error parsing exit code for container %s", ctrID)
|
|
||||||
}
|
|
||||||
|
|
||||||
return exitCode, nil
|
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,8 @@ func getRuntimeSpec(c *cliconfig.PodmanCommand) (*spec.Spec, error) {
|
|||||||
createConfig, err := parseCreateOpts(c, runtime, "alpine", generateAlpineImageData())
|
createConfig, err := parseCreateOpts(c, runtime, "alpine", generateAlpineImageData())
|
||||||
*/
|
*/
|
||||||
ctx := getContext()
|
ctx := getContext()
|
||||||
createConfig, err := shared.ParseCreateOpts(ctx, c, nil, "alpine", generateAlpineImageData())
|
genericResults := shared.NewIntermediateLayer(c)
|
||||||
|
createConfig, err := shared.ParseCreateOpts(ctx, &genericResults, nil, "alpine", generateAlpineImageData())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containers/image/manifest"
|
"github.com/containers/image/manifest"
|
||||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
|
||||||
"github.com/containers/libpod/cmd/podman/shared/parse"
|
"github.com/containers/libpod/cmd/podman/shared/parse"
|
||||||
"github.com/containers/libpod/libpod"
|
"github.com/containers/libpod/libpod"
|
||||||
"github.com/containers/libpod/libpod/image"
|
"github.com/containers/libpod/libpod/image"
|
||||||
@ -34,12 +33,7 @@ import (
|
|||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// getContext returns a non-nil, empty context
|
func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod.Runtime) (*libpod.Container, *cc.CreateConfig, error) {
|
||||||
func getContext() context.Context {
|
|
||||||
return context.TODO()
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateContainer(ctx context.Context, c *cliconfig.PodmanCommand, runtime *libpod.Runtime) (*libpod.Container, *cc.CreateConfig, error) {
|
|
||||||
var (
|
var (
|
||||||
healthCheck *manifest.Schema2HealthConfig
|
healthCheck *manifest.Schema2HealthConfig
|
||||||
err error
|
err error
|
||||||
@ -221,7 +215,7 @@ func parseSecurityOpt(config *cc.CreateConfig, securityOpts []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func configureEntrypoint(c *cliconfig.PodmanCommand, data *inspect.ImageData) []string {
|
func configureEntrypoint(c *GenericCLIResults, data *inspect.ImageData) []string {
|
||||||
entrypoint := []string{}
|
entrypoint := []string{}
|
||||||
if c.IsSet("entrypoint") {
|
if c.IsSet("entrypoint") {
|
||||||
// Force entrypoint to ""
|
// Force entrypoint to ""
|
||||||
@ -241,7 +235,7 @@ func configureEntrypoint(c *cliconfig.PodmanCommand, data *inspect.ImageData) []
|
|||||||
return entrypoint
|
return entrypoint
|
||||||
}
|
}
|
||||||
|
|
||||||
func configurePod(c *cliconfig.PodmanCommand, runtime *libpod.Runtime, namespaces map[string]string, podName string) (map[string]string, error) {
|
func configurePod(c *GenericCLIResults, runtime *libpod.Runtime, namespaces map[string]string, podName string) (map[string]string, error) {
|
||||||
pod, err := runtime.LookupPod(podName)
|
pod, err := runtime.LookupPod(podName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return namespaces, err
|
return namespaces, err
|
||||||
@ -270,7 +264,7 @@ func configurePod(c *cliconfig.PodmanCommand, runtime *libpod.Runtime, namespace
|
|||||||
|
|
||||||
// Parses CLI options related to container creation into a config which can be
|
// Parses CLI options related to container creation into a config which can be
|
||||||
// parsed into an OCI runtime spec
|
// parsed into an OCI runtime spec
|
||||||
func ParseCreateOpts(ctx context.Context, c *cliconfig.PodmanCommand, runtime *libpod.Runtime, imageName string, data *inspect.ImageData) (*cc.CreateConfig, error) {
|
func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.Runtime, imageName string, data *inspect.ImageData) (*cc.CreateConfig, error) {
|
||||||
var (
|
var (
|
||||||
inputCommand, command []string
|
inputCommand, command []string
|
||||||
memoryLimit, memoryReservation, memorySwap, memoryKernel int64
|
memoryLimit, memoryReservation, memorySwap, memoryKernel int64
|
||||||
@ -353,14 +347,14 @@ func ParseCreateOpts(ctx context.Context, c *cliconfig.PodmanCommand, runtime *l
|
|||||||
|
|
||||||
tty := c.Bool("tty")
|
tty := c.Bool("tty")
|
||||||
|
|
||||||
if c.Flag("cpu-period").Changed && c.Flag("cpus").Changed {
|
if c.Changed("cpu-period") && c.Changed("cpus") {
|
||||||
return nil, errors.Errorf("--cpu-period and --cpus cannot be set together")
|
return nil, errors.Errorf("--cpu-period and --cpus cannot be set together")
|
||||||
}
|
}
|
||||||
if c.Flag("cpu-quota").Changed && c.Flag("cpus").Changed {
|
if c.Changed("cpu-quota") && c.Changed("cpus") {
|
||||||
return nil, errors.Errorf("--cpu-quota and --cpus cannot be set together")
|
return nil, errors.Errorf("--cpu-quota and --cpus cannot be set together")
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Bool("no-hosts") && c.Flag("add-host").Changed {
|
if c.Bool("no-hosts") && c.Changed("add-host") {
|
||||||
return nil, errors.Errorf("--no-hosts and --add-host cannot be set together")
|
return nil, errors.Errorf("--no-hosts and --add-host cannot be set together")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,7 +373,7 @@ func ParseCreateOpts(ctx context.Context, c *cliconfig.PodmanCommand, runtime *l
|
|||||||
// However, that also involves setting up security opts
|
// However, that also involves setting up security opts
|
||||||
// when the pod's namespace is integrated
|
// when the pod's namespace is integrated
|
||||||
namespaceNet := c.String("network")
|
namespaceNet := c.String("network")
|
||||||
if c.Flag("net").Changed {
|
if c.Changed("net") {
|
||||||
namespaceNet = c.String("net")
|
namespaceNet = c.String("net")
|
||||||
}
|
}
|
||||||
namespaces = map[string]string{
|
namespaces = map[string]string{
|
||||||
@ -548,7 +542,7 @@ func ParseCreateOpts(ctx context.Context, c *cliconfig.PodmanCommand, runtime *l
|
|||||||
|
|
||||||
// WORKING DIRECTORY
|
// WORKING DIRECTORY
|
||||||
workDir := "/"
|
workDir := "/"
|
||||||
if c.IsSet("workdir") || c.IsSet("w") {
|
if c.IsSet("workdir") {
|
||||||
workDir = c.String("workdir")
|
workDir = c.String("workdir")
|
||||||
} else if data != nil && data.Config.WorkingDir != "" {
|
} else if data != nil && data.Config.WorkingDir != "" {
|
||||||
workDir = data.Config.WorkingDir
|
workDir = data.Config.WorkingDir
|
||||||
@ -624,14 +618,12 @@ func ParseCreateOpts(ctx context.Context, c *cliconfig.PodmanCommand, runtime *l
|
|||||||
// This is done because cobra cannot have two aliased flags. So we have to check
|
// This is done because cobra cannot have two aliased flags. So we have to check
|
||||||
// both
|
// both
|
||||||
network := c.String("network")
|
network := c.String("network")
|
||||||
if c.Flag("net").Changed {
|
if c.Changed("net") {
|
||||||
network = c.String("net")
|
network = c.String("net")
|
||||||
}
|
}
|
||||||
|
|
||||||
var memorySwappiness int64
|
memorySwappiness := c.Int64("memory-swappiness")
|
||||||
if c.Flags().Lookup("memory-swappiness") != nil {
|
|
||||||
memorySwappiness, _ = c.Flags().GetInt64("memory-swappiness")
|
|
||||||
}
|
|
||||||
config := &cc.CreateConfig{
|
config := &cc.CreateConfig{
|
||||||
Runtime: runtime,
|
Runtime: runtime,
|
||||||
Annotations: annotations,
|
Annotations: annotations,
|
||||||
@ -719,7 +711,7 @@ func ParseCreateOpts(ctx context.Context, c *cliconfig.PodmanCommand, runtime *l
|
|||||||
WorkDir: workDir,
|
WorkDir: workDir,
|
||||||
Rootfs: rootfs,
|
Rootfs: rootfs,
|
||||||
VolumesFrom: c.StringSlice("volumes-from"),
|
VolumesFrom: c.StringSlice("volumes-from"),
|
||||||
Syslog: c.GlobalFlags.Syslog,
|
Syslog: c.Bool("syslog"),
|
||||||
}
|
}
|
||||||
if c.Bool("init") {
|
if c.Bool("init") {
|
||||||
initPath := c.String("init-path")
|
initPath := c.String("init-path")
|
||||||
@ -789,7 +781,7 @@ var defaultEnvVariables = map[string]string{
|
|||||||
"TERM": "xterm",
|
"TERM": "xterm",
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeHealthCheckFromCli(c *cliconfig.PodmanCommand) (*manifest.Schema2HealthConfig, error) {
|
func makeHealthCheckFromCli(c *GenericCLIResults) (*manifest.Schema2HealthConfig, error) {
|
||||||
inCommand := c.String("healthcheck-command")
|
inCommand := c.String("healthcheck-command")
|
||||||
inInterval := c.String("healthcheck-interval")
|
inInterval := c.String("healthcheck-interval")
|
||||||
inRetries := c.Uint("healthcheck-retries")
|
inRetries := c.Uint("healthcheck-retries")
|
||||||
|
465
cmd/podman/shared/intermediate.go
Normal file
465
cmd/podman/shared/intermediate.go
Normal file
@ -0,0 +1,465 @@
|
|||||||
|
package shared
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
attention
|
||||||
|
|
||||||
|
in this file you will see alot of struct duplication. this was done because people wanted a strongly typed
|
||||||
|
varlink mechanism. this resulted in us creating this intermediate layer that allows us to take the input
|
||||||
|
from the cli and make an intermediate layer which can be transferred as strongly typed structures over a varlink
|
||||||
|
interface.
|
||||||
|
|
||||||
|
we intentionally avoided heavy use of reflection here because we were concerned about performance impacts to the
|
||||||
|
non-varlink intermediate layer generation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// GenericCLIResult describes the overall interface for dealing with
|
||||||
|
// the create command cli in both local and remote uses
|
||||||
|
type GenericCLIResult interface {
|
||||||
|
IsSet() bool
|
||||||
|
Name() string
|
||||||
|
Value() interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CRStringSlice describes a string slice cli struct
|
||||||
|
type CRStringSlice struct {
|
||||||
|
Val []string
|
||||||
|
createResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// CRString describes a string cli struct
|
||||||
|
type CRString struct {
|
||||||
|
Val string
|
||||||
|
createResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// CRUint64 describes a uint64 cli struct
|
||||||
|
type CRUint64 struct {
|
||||||
|
Val uint64
|
||||||
|
createResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// CRFloat64 describes a float64 cli struct
|
||||||
|
type CRFloat64 struct {
|
||||||
|
Val float64
|
||||||
|
createResult
|
||||||
|
}
|
||||||
|
|
||||||
|
//CRBool describes a bool cli struct
|
||||||
|
type CRBool struct {
|
||||||
|
Val bool
|
||||||
|
createResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// CRInt64 describes an int64 cli struct
|
||||||
|
type CRInt64 struct {
|
||||||
|
Val int64
|
||||||
|
createResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// CRUint describes a uint cli struct
|
||||||
|
type CRUint struct {
|
||||||
|
Val uint
|
||||||
|
createResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// CRInt describes an int cli struct
|
||||||
|
type CRInt struct {
|
||||||
|
Val int
|
||||||
|
createResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// CRStringArray describes a stringarray cli struct
|
||||||
|
type CRStringArray struct {
|
||||||
|
Val []string
|
||||||
|
createResult
|
||||||
|
}
|
||||||
|
|
||||||
|
type createResult struct {
|
||||||
|
Flag string
|
||||||
|
Changed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenericCLIResults in the intermediate object between the cobra cli
|
||||||
|
// and createconfig
|
||||||
|
type GenericCLIResults struct {
|
||||||
|
results map[string]GenericCLIResult
|
||||||
|
InputArgs []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet returns a bool if the flag was changed
|
||||||
|
func (f GenericCLIResults) IsSet(flag string) bool {
|
||||||
|
r := f.findResult(flag)
|
||||||
|
if r == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return r.IsSet()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the value of the cli flag
|
||||||
|
func (f GenericCLIResults) Value(flag string) interface{} {
|
||||||
|
r := f.findResult(flag)
|
||||||
|
if r == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return r.Value()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f GenericCLIResults) findResult(flag string) GenericCLIResult {
|
||||||
|
val, ok := f.results[flag]
|
||||||
|
if ok {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
logrus.Errorf("unable to find flag %s", flag)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bool is a wrapper to get a bool value from GenericCLIResults
|
||||||
|
func (f GenericCLIResults) Bool(flag string) bool {
|
||||||
|
r := f.findResult(flag)
|
||||||
|
if r == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return r.Value().(bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
// String is a wrapper to get a string value from GenericCLIResults
|
||||||
|
func (f GenericCLIResults) String(flag string) string {
|
||||||
|
r := f.findResult(flag)
|
||||||
|
if r == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return r.Value().(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint is a wrapper to get an uint value from GenericCLIResults
|
||||||
|
func (f GenericCLIResults) Uint(flag string) uint {
|
||||||
|
r := f.findResult(flag)
|
||||||
|
if r == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return r.Value().(uint)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringSlice is a wrapper to get a stringslice value from GenericCLIResults
|
||||||
|
func (f GenericCLIResults) StringSlice(flag string) []string {
|
||||||
|
r := f.findResult(flag)
|
||||||
|
if r == nil {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
return r.Value().([]string)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringArray is a wrapper to get a stringslice value from GenericCLIResults
|
||||||
|
func (f GenericCLIResults) StringArray(flag string) []string {
|
||||||
|
r := f.findResult(flag)
|
||||||
|
if r == nil {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
return r.Value().([]string)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint64 is a wrapper to get an uint64 value from GenericCLIResults
|
||||||
|
func (f GenericCLIResults) Uint64(flag string) uint64 {
|
||||||
|
r := f.findResult(flag)
|
||||||
|
if r == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return r.Value().(uint64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64 is a wrapper to get an int64 value from GenericCLIResults
|
||||||
|
func (f GenericCLIResults) Int64(flag string) int64 {
|
||||||
|
r := f.findResult(flag)
|
||||||
|
if r == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return r.Value().(int64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int is a wrapper to get an int value from GenericCLIResults
|
||||||
|
func (f GenericCLIResults) Int(flag string) int {
|
||||||
|
r := f.findResult(flag)
|
||||||
|
if r == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return r.Value().(int)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64 is a wrapper to get an float64 value from GenericCLIResults
|
||||||
|
func (f GenericCLIResults) Float64(flag string) float64 {
|
||||||
|
r := f.findResult(flag)
|
||||||
|
if r == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return r.Value().(float64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64 is a wrapper to get an float64 value from GenericCLIResults
|
||||||
|
func (f GenericCLIResults) Changed(flag string) bool {
|
||||||
|
r := f.findResult(flag)
|
||||||
|
if r == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return r.IsSet()
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet ...
|
||||||
|
func (c CRStringSlice) IsSet() bool { return c.Changed }
|
||||||
|
|
||||||
|
// Name ...
|
||||||
|
func (c CRStringSlice) Name() string { return c.Flag }
|
||||||
|
|
||||||
|
// Value ...
|
||||||
|
func (c CRStringSlice) Value() interface{} { return c.Val }
|
||||||
|
|
||||||
|
// IsSet ...
|
||||||
|
func (c CRString) IsSet() bool { return c.Changed }
|
||||||
|
|
||||||
|
// Name ...
|
||||||
|
func (c CRString) Name() string { return c.Flag }
|
||||||
|
|
||||||
|
// Value ...
|
||||||
|
func (c CRString) Value() interface{} { return c.Val }
|
||||||
|
|
||||||
|
// IsSet ...
|
||||||
|
func (c CRUint64) IsSet() bool { return c.Changed }
|
||||||
|
|
||||||
|
// Name ...
|
||||||
|
func (c CRUint64) Name() string { return c.Flag }
|
||||||
|
|
||||||
|
// Value ...
|
||||||
|
func (c CRUint64) Value() interface{} { return c.Val }
|
||||||
|
|
||||||
|
// IsSet ...
|
||||||
|
func (c CRFloat64) IsSet() bool { return c.Changed }
|
||||||
|
|
||||||
|
// Name ...
|
||||||
|
func (c CRFloat64) Name() string { return c.Flag }
|
||||||
|
|
||||||
|
// Value ...
|
||||||
|
func (c CRFloat64) Value() interface{} { return c.Val }
|
||||||
|
|
||||||
|
// IsSet ...
|
||||||
|
func (c CRBool) IsSet() bool { return c.Changed }
|
||||||
|
|
||||||
|
// Name ...
|
||||||
|
func (c CRBool) Name() string { return c.Flag }
|
||||||
|
|
||||||
|
// Value ...
|
||||||
|
func (c CRBool) Value() interface{} { return c.Val }
|
||||||
|
|
||||||
|
// IsSet ...
|
||||||
|
func (c CRInt64) IsSet() bool { return c.Changed }
|
||||||
|
|
||||||
|
// Name ...
|
||||||
|
func (c CRInt64) Name() string { return c.Flag }
|
||||||
|
|
||||||
|
// Value ...
|
||||||
|
func (c CRInt64) Value() interface{} { return c.Val }
|
||||||
|
|
||||||
|
// IsSet ...
|
||||||
|
func (c CRUint) IsSet() bool { return c.Changed }
|
||||||
|
|
||||||
|
// Name ...
|
||||||
|
func (c CRUint) Name() string { return c.Flag }
|
||||||
|
|
||||||
|
// Value ...
|
||||||
|
func (c CRUint) Value() interface{} { return c.Val }
|
||||||
|
|
||||||
|
// IsSet ...
|
||||||
|
func (c CRInt) IsSet() bool { return c.Changed }
|
||||||
|
|
||||||
|
// Name ...
|
||||||
|
func (c CRInt) Name() string { return c.Flag }
|
||||||
|
|
||||||
|
// Value ...
|
||||||
|
func (c CRInt) Value() interface{} { return c.Val }
|
||||||
|
|
||||||
|
// IsSet ...
|
||||||
|
func (c CRStringArray) IsSet() bool { return c.Changed }
|
||||||
|
|
||||||
|
// Name ...
|
||||||
|
func (c CRStringArray) Name() string { return c.Flag }
|
||||||
|
|
||||||
|
// Value ...
|
||||||
|
func (c CRStringArray) Value() interface{} { return c.Val }
|
||||||
|
|
||||||
|
func newCreateResult(c *cliconfig.PodmanCommand, flag string) createResult {
|
||||||
|
return createResult{
|
||||||
|
Flag: flag,
|
||||||
|
Changed: c.IsSet(flag),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCRStringSlice(c *cliconfig.PodmanCommand, flag string) CRStringSlice {
|
||||||
|
return CRStringSlice{
|
||||||
|
Val: c.StringSlice(flag),
|
||||||
|
createResult: newCreateResult(c, flag),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCRString(c *cliconfig.PodmanCommand, flag string) CRString {
|
||||||
|
return CRString{
|
||||||
|
Val: c.String(flag),
|
||||||
|
createResult: newCreateResult(c, flag),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCRUint64(c *cliconfig.PodmanCommand, flag string) CRUint64 {
|
||||||
|
return CRUint64{
|
||||||
|
Val: c.Uint64(flag),
|
||||||
|
createResult: newCreateResult(c, flag),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCRFloat64(c *cliconfig.PodmanCommand, flag string) CRFloat64 {
|
||||||
|
return CRFloat64{
|
||||||
|
Val: c.Float64(flag),
|
||||||
|
createResult: newCreateResult(c, flag),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCRBool(c *cliconfig.PodmanCommand, flag string) CRBool {
|
||||||
|
return CRBool{
|
||||||
|
Val: c.Bool(flag),
|
||||||
|
createResult: newCreateResult(c, flag),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCRInt64(c *cliconfig.PodmanCommand, flag string) CRInt64 {
|
||||||
|
return CRInt64{
|
||||||
|
Val: c.Int64(flag),
|
||||||
|
createResult: newCreateResult(c, flag),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCRUint(c *cliconfig.PodmanCommand, flag string) CRUint {
|
||||||
|
return CRUint{
|
||||||
|
Val: c.Uint(flag),
|
||||||
|
createResult: newCreateResult(c, flag),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCRInt(c *cliconfig.PodmanCommand, flag string) CRInt {
|
||||||
|
return CRInt{
|
||||||
|
Val: c.Int(flag),
|
||||||
|
createResult: newCreateResult(c, flag),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCRStringArray(c *cliconfig.PodmanCommand, flag string) CRStringArray {
|
||||||
|
return CRStringArray{
|
||||||
|
Val: c.StringArray(flag),
|
||||||
|
createResult: newCreateResult(c, flag),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewIntermediateLayer creates a GenericCLIResults from a create or run cli-command
|
||||||
|
func NewIntermediateLayer(c *cliconfig.PodmanCommand) GenericCLIResults {
|
||||||
|
m := make(map[string]GenericCLIResult)
|
||||||
|
|
||||||
|
m["add-host"] = newCRStringSlice(c, "add-host")
|
||||||
|
m["annotation"] = newCRStringSlice(c, "annotation")
|
||||||
|
m["attach"] = newCRStringSlice(c, "attach")
|
||||||
|
m["blkio-weight"] = newCRString(c, "blkio-weight")
|
||||||
|
m["blkio-weight-device"] = newCRStringSlice(c, "blkio-weight-device")
|
||||||
|
m["cap-add"] = newCRStringSlice(c, "cap-add")
|
||||||
|
m["cap-drop"] = newCRStringSlice(c, "cap-drop")
|
||||||
|
m["cgroup-parent"] = newCRString(c, "cgroup-parent")
|
||||||
|
m["cidfile"] = newCRString(c, "cidfile")
|
||||||
|
m["conmon-pidfile"] = newCRString(c, "conmon-pidfile")
|
||||||
|
m["cpu-period"] = newCRUint64(c, "cpu-period")
|
||||||
|
m["cpu-quota"] = newCRInt64(c, "cpu-quota")
|
||||||
|
m["cpu-rt-period"] = newCRUint64(c, "cpu-rt-period")
|
||||||
|
m["cpu-rt-runtime"] = newCRInt64(c, "cpu-rt-runtime")
|
||||||
|
m["cpu-shares"] = newCRUint64(c, "cpu-shares")
|
||||||
|
m["cpus"] = newCRFloat64(c, "cpus")
|
||||||
|
m["cpuset-cpus"] = newCRString(c, "cpuset-cpus")
|
||||||
|
m["cpuset-mems"] = newCRString(c, "cpuset-mems")
|
||||||
|
m["detach"] = newCRBool(c, "detach")
|
||||||
|
m["detach-keys"] = newCRString(c, "detach-keys")
|
||||||
|
m["device"] = newCRStringSlice(c, "device")
|
||||||
|
m["device-read-bps"] = newCRStringSlice(c, "device-read-bps")
|
||||||
|
m["device-read-iops"] = newCRStringSlice(c, "device-read-iops")
|
||||||
|
m["device-write-bps"] = newCRStringSlice(c, "device-write-bps")
|
||||||
|
m["device-write-iops"] = newCRStringSlice(c, "device-write-iops")
|
||||||
|
m["dns"] = newCRStringSlice(c, "dns")
|
||||||
|
m["dns-opt"] = newCRStringSlice(c, "dns-opt")
|
||||||
|
m["dns-search"] = newCRStringSlice(c, "dns-search")
|
||||||
|
m["entrypoint"] = newCRString(c, "entrypoint")
|
||||||
|
m["env"] = newCRStringArray(c, "env")
|
||||||
|
m["env-file"] = newCRStringSlice(c, "env-file")
|
||||||
|
m["expose"] = newCRStringSlice(c, "expose")
|
||||||
|
m["gidmap"] = newCRStringSlice(c, "gidmap")
|
||||||
|
m["group-add"] = newCRStringSlice(c, "group-add")
|
||||||
|
m["help"] = newCRBool(c, "help")
|
||||||
|
m["healthcheck-command"] = newCRString(c, "healthcheck-command")
|
||||||
|
m["healthcheck-interval"] = newCRString(c, "healthcheck-interval")
|
||||||
|
m["healthcheck-retries"] = newCRUint(c, "healthcheck-retries")
|
||||||
|
m["healthcheck-start-period"] = newCRString(c, "healthcheck-start-period")
|
||||||
|
m["healthcheck-timeout"] = newCRString(c, "healthcheck-timeout")
|
||||||
|
m["hostname"] = newCRString(c, "hostname")
|
||||||
|
m["image-volume"] = newCRString(c, "image-volume")
|
||||||
|
m["init"] = newCRBool(c, "init")
|
||||||
|
m["init-path"] = newCRString(c, "init-path")
|
||||||
|
m["interactive"] = newCRBool(c, "interactive")
|
||||||
|
m["ip"] = newCRString(c, "ip")
|
||||||
|
m["ipc"] = newCRString(c, "ipc")
|
||||||
|
m["kernel-memory"] = newCRString(c, "kernel-memory")
|
||||||
|
m["label"] = newCRStringArray(c, "label")
|
||||||
|
m["label-file"] = newCRStringSlice(c, "label-file")
|
||||||
|
m["log-driver"] = newCRString(c, "log-driver")
|
||||||
|
m["log-opt"] = newCRStringSlice(c, "log-opt")
|
||||||
|
m["mac-address"] = newCRString(c, "mac-address")
|
||||||
|
m["memory"] = newCRString(c, "memory")
|
||||||
|
m["memory-reservation"] = newCRString(c, "memory-reservation")
|
||||||
|
m["memory-swap"] = newCRString(c, "memory-swap")
|
||||||
|
m["memory-swappiness"] = newCRInt64(c, "memory-swappiness")
|
||||||
|
m["name"] = newCRString(c, "name")
|
||||||
|
m["net"] = newCRString(c, "net")
|
||||||
|
m["network"] = newCRString(c, "network")
|
||||||
|
m["no-hosts"] = newCRBool(c, "no-hosts")
|
||||||
|
m["oom-kill-disable"] = newCRBool(c, "oom-kill-disable")
|
||||||
|
m["oom-score-adj"] = newCRInt(c, "oom-score-adj")
|
||||||
|
m["pid"] = newCRString(c, "pid")
|
||||||
|
m["pids-limit"] = newCRInt64(c, "pids-limit")
|
||||||
|
m["pod"] = newCRString(c, "pod")
|
||||||
|
m["privileged"] = newCRBool(c, "privileged")
|
||||||
|
m["publish"] = newCRStringSlice(c, "publish")
|
||||||
|
m["publish-all"] = newCRBool(c, "publish-all")
|
||||||
|
m["quiet"] = newCRBool(c, "quiet")
|
||||||
|
m["read-only"] = newCRBool(c, "read-only")
|
||||||
|
m["restart"] = newCRString(c, "restart")
|
||||||
|
m["rm"] = newCRBool(c, "rm")
|
||||||
|
m["rootfs"] = newCRBool(c, "rootfs")
|
||||||
|
m["security-opt"] = newCRStringArray(c, "security-opt")
|
||||||
|
m["shm-size"] = newCRString(c, "shm-size")
|
||||||
|
m["stop-signal"] = newCRString(c, "stop-signal")
|
||||||
|
m["stop-timeout"] = newCRUint(c, "stop-timeout")
|
||||||
|
m["storage-opt"] = newCRStringSlice(c, "storage-opt")
|
||||||
|
m["subgidname"] = newCRString(c, "subgidname")
|
||||||
|
m["subuidname"] = newCRString(c, "subuidname")
|
||||||
|
m["sysctl"] = newCRStringSlice(c, "sysctl")
|
||||||
|
m["systemd"] = newCRBool(c, "systemd")
|
||||||
|
m["tmpfs"] = newCRStringSlice(c, "tmpfs")
|
||||||
|
m["tty"] = newCRBool(c, "tty")
|
||||||
|
m["uidmap"] = newCRStringSlice(c, "uidmap")
|
||||||
|
m["ulimit"] = newCRStringSlice(c, "ulimit")
|
||||||
|
m["user"] = newCRString(c, "user")
|
||||||
|
m["userns"] = newCRString(c, "userns")
|
||||||
|
m["uts"] = newCRString(c, "uts")
|
||||||
|
m["mount"] = newCRStringArray(c, "mount")
|
||||||
|
m["volume"] = newCRStringArray(c, "volume")
|
||||||
|
m["volumes-from"] = newCRStringSlice(c, "volumes-from")
|
||||||
|
m["workdir"] = newCRString(c, "workdir")
|
||||||
|
// global flag
|
||||||
|
m["trace"] = newCRBool(c, "trace")
|
||||||
|
m["syslog"] = newCRBool(c, "syslog")
|
||||||
|
|
||||||
|
return GenericCLIResults{m, c.InputArgs}
|
||||||
|
}
|
70
cmd/podman/shared/intermediate_novarlink.go
Normal file
70
cmd/podman/shared/intermediate_novarlink.go
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
// +build !varlink
|
||||||
|
// +build !remoteclient
|
||||||
|
|
||||||
|
package shared
|
||||||
|
|
||||||
|
/*
|
||||||
|
attention
|
||||||
|
|
||||||
|
in this file you will see alot of struct duplication. this was done because people wanted a strongly typed
|
||||||
|
varlink mechanism. this resulted in us creating this intermediate layer that allows us to take the input
|
||||||
|
from the cli and make an intermediate layer which can be transferred as strongly typed structures over a varlink
|
||||||
|
interface.
|
||||||
|
|
||||||
|
we intentionally avoided heavy use of reflection here because we were concerned about performance impacts to the
|
||||||
|
non-varlink intermediate layer generation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ToString wrapper for build without varlink
|
||||||
|
func (c CRStringSlice) ToVarlink() interface{} {
|
||||||
|
var v interface{}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToString wrapper for build without varlink
|
||||||
|
func (c CRString) ToVarlink() interface{} {
|
||||||
|
var v interface{}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToString wrapper for build without varlink
|
||||||
|
func (c CRBool) ToVarlink() interface{} {
|
||||||
|
var v interface{}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToString wrapper for build without varlink
|
||||||
|
func (c CRUint64) ToVarlink() interface{} {
|
||||||
|
var v interface{}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToString wrapper for build without varlink
|
||||||
|
func (c CRInt64) ToVarlink() interface{} {
|
||||||
|
var v interface{}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToString wrapper for build without varlink
|
||||||
|
func (c CRFloat64) ToVarlink() interface{} {
|
||||||
|
var v interface{}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToString wrapper for build without varlink
|
||||||
|
func (c CRUint) ToVarlink() interface{} {
|
||||||
|
var v interface{}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToString wrapper for build without varlink
|
||||||
|
func (c CRStringArray) ToVarlink() interface{} {
|
||||||
|
var v interface{}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToString wrapper for build without varlink
|
||||||
|
func (c CRInt) ToVarlink() interface{} {
|
||||||
|
var v interface{}
|
||||||
|
return v
|
||||||
|
}
|
427
cmd/podman/shared/intermediate_varlink.go
Normal file
427
cmd/podman/shared/intermediate_varlink.go
Normal file
@ -0,0 +1,427 @@
|
|||||||
|
// +build varlink remoteclient
|
||||||
|
|
||||||
|
package shared
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||||
|
"github.com/containers/libpod/cmd/podman/varlink"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StringSliceToPtr converts a genericcliresult value into a *[]string
|
||||||
|
func StringSliceToPtr(g GenericCLIResult) *[]string {
|
||||||
|
if !g.IsSet() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
newT := g.Value().([]string)
|
||||||
|
return &newT
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToPtr converts a genericcliresult value into a *string
|
||||||
|
func StringToPtr(g GenericCLIResult) *string {
|
||||||
|
if !g.IsSet() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
newT := g.Value().(string)
|
||||||
|
return &newT
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolToPtr converts a genericcliresult value into a *bool
|
||||||
|
func BoolToPtr(g GenericCLIResult) *bool {
|
||||||
|
if !g.IsSet() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
newT := g.Value().(bool)
|
||||||
|
return &newT
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnyIntToInt64Ptr converts a genericcliresult value into an *int64
|
||||||
|
func AnyIntToInt64Ptr(g GenericCLIResult) *int64 {
|
||||||
|
if !g.IsSet() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var newT int64
|
||||||
|
switch g.Value().(type) {
|
||||||
|
case int:
|
||||||
|
newT = int64(g.Value().(int))
|
||||||
|
case int64:
|
||||||
|
newT = g.Value().(int64)
|
||||||
|
case uint64:
|
||||||
|
newT = int64(g.Value().(uint64))
|
||||||
|
case uint:
|
||||||
|
newT = int64(g.Value().(uint))
|
||||||
|
default:
|
||||||
|
panic(errors.Errorf("invalid int type"))
|
||||||
|
}
|
||||||
|
return &newT
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64ToPtr converts a genericcliresult into a *float64
|
||||||
|
func Float64ToPtr(g GenericCLIResult) *float64 {
|
||||||
|
if !g.IsSet() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
newT := g.Value().(float64)
|
||||||
|
return &newT
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeVarlink creates a varlink transportable struct from GenericCLIResults
|
||||||
|
func (g GenericCLIResults) MakeVarlink() iopodman.Create {
|
||||||
|
v := iopodman.Create{
|
||||||
|
Args: g.InputArgs,
|
||||||
|
AddHost: StringSliceToPtr(g.Find("add-host")),
|
||||||
|
Annotation: StringSliceToPtr(g.Find("annotation")),
|
||||||
|
Attach: StringSliceToPtr(g.Find("attach")),
|
||||||
|
BlkioWeight: StringToPtr(g.Find("blkio-weight")),
|
||||||
|
BlkioWeightDevice: StringSliceToPtr(g.Find("blkio-weight-device")),
|
||||||
|
CapAdd: StringSliceToPtr(g.Find("cap-add")),
|
||||||
|
CapDrop: StringSliceToPtr(g.Find("cap-drop")),
|
||||||
|
CgroupParent: StringToPtr(g.Find("cgroup-parent")),
|
||||||
|
CidFile: StringToPtr(g.Find("cidfile")),
|
||||||
|
ConmonPidfile: StringToPtr(g.Find("conmon-pidfile")),
|
||||||
|
CpuPeriod: AnyIntToInt64Ptr(g.Find("cpu-period")),
|
||||||
|
CpuQuota: AnyIntToInt64Ptr(g.Find("cpu-quota")),
|
||||||
|
CpuRtPeriod: AnyIntToInt64Ptr(g.Find("cpu-rt-period")),
|
||||||
|
CpuRtRuntime: AnyIntToInt64Ptr(g.Find("cpu-rt-runtime")),
|
||||||
|
CpuShares: AnyIntToInt64Ptr(g.Find("cpu-shares")),
|
||||||
|
Cpus: Float64ToPtr(g.Find("cpus")),
|
||||||
|
CpuSetCpus: StringToPtr(g.Find("cpuset-cpus")),
|
||||||
|
CpuSetMems: StringToPtr(g.Find("cpuset-mems")),
|
||||||
|
Detach: BoolToPtr(g.Find("detach")),
|
||||||
|
DetachKeys: StringToPtr(g.Find("detach-keys")),
|
||||||
|
Device: StringSliceToPtr(g.Find("device")),
|
||||||
|
DeviceReadBps: StringSliceToPtr(g.Find("device-read-bps")),
|
||||||
|
DeviceReadIops: StringSliceToPtr(g.Find("device-read-iops")),
|
||||||
|
DeviceWriteBps: StringSliceToPtr(g.Find("device-write-bps")),
|
||||||
|
DeviceWriteIops: StringSliceToPtr(g.Find("device-write-iops")),
|
||||||
|
Dns: StringSliceToPtr(g.Find("dns")),
|
||||||
|
DnsOpt: StringSliceToPtr(g.Find("dns-opt")),
|
||||||
|
DnsSearch: StringSliceToPtr(g.Find("dns-search")),
|
||||||
|
Entrypoint: StringToPtr(g.Find("entrypoint")),
|
||||||
|
Env: StringSliceToPtr(g.Find("env")),
|
||||||
|
EnvFile: StringSliceToPtr(g.Find("env-file")),
|
||||||
|
Expose: StringSliceToPtr(g.Find("expose")),
|
||||||
|
Gidmap: StringSliceToPtr(g.Find("gidmap")),
|
||||||
|
Groupadd: StringSliceToPtr(g.Find("group-add")),
|
||||||
|
HealthcheckCommand: StringToPtr(g.Find("healthcheck-command")),
|
||||||
|
HealthcheckInterval: StringToPtr(g.Find("healthcheck-interval")),
|
||||||
|
HealthcheckRetries: AnyIntToInt64Ptr(g.Find("healthcheck-retries")),
|
||||||
|
HealthcheckStartPeriod: StringToPtr(g.Find("healthcheck-start-period")),
|
||||||
|
HealthcheckTimeout: StringToPtr(g.Find("healthcheck-timeout")),
|
||||||
|
Hostname: StringToPtr(g.Find("hostname")),
|
||||||
|
ImageVolume: StringToPtr(g.Find("image-volume")),
|
||||||
|
Init: BoolToPtr(g.Find("init")),
|
||||||
|
InitPath: StringToPtr(g.Find("init-path")),
|
||||||
|
Interactive: BoolToPtr(g.Find("interactive")),
|
||||||
|
Ip: StringToPtr(g.Find("ip")),
|
||||||
|
Ipc: StringToPtr(g.Find("ipc")),
|
||||||
|
KernelMemory: StringToPtr(g.Find("kernel-memory")),
|
||||||
|
Label: StringSliceToPtr(g.Find("label")),
|
||||||
|
LabelFile: StringSliceToPtr(g.Find("label-file")),
|
||||||
|
LogDriver: StringToPtr(g.Find("log-driver")),
|
||||||
|
LogOpt: StringSliceToPtr(g.Find("log-opt")),
|
||||||
|
MacAddress: StringToPtr(g.Find("mac-address")),
|
||||||
|
Memory: StringToPtr(g.Find("memory")),
|
||||||
|
MemoryReservation: StringToPtr(g.Find("memory-reservation")),
|
||||||
|
MemorySwap: StringToPtr(g.Find("memory-swap")),
|
||||||
|
MemorySwappiness: AnyIntToInt64Ptr(g.Find("memory-swappiness")),
|
||||||
|
Name: StringToPtr(g.Find("name")),
|
||||||
|
Net: StringToPtr(g.Find("net")),
|
||||||
|
Network: StringToPtr(g.Find("network")),
|
||||||
|
OomKillDisable: BoolToPtr(g.Find("oom-kill-disable")),
|
||||||
|
OomScoreAdj: AnyIntToInt64Ptr(g.Find("oom-score-adj")),
|
||||||
|
Pid: StringToPtr(g.Find("pid")),
|
||||||
|
PidsLimit: AnyIntToInt64Ptr(g.Find("pids-limit")),
|
||||||
|
Pod: StringToPtr(g.Find("pod")),
|
||||||
|
Privileged: BoolToPtr(g.Find("privileged")),
|
||||||
|
Publish: StringSliceToPtr(g.Find("publish")),
|
||||||
|
PublishAll: BoolToPtr(g.Find("publish-all")),
|
||||||
|
Quiet: BoolToPtr(g.Find("quiet")),
|
||||||
|
Readonly: BoolToPtr(g.Find("read-only")),
|
||||||
|
Restart: StringToPtr(g.Find("restart")),
|
||||||
|
Rm: BoolToPtr(g.Find("rm")),
|
||||||
|
Rootfs: BoolToPtr(g.Find("rootfs")),
|
||||||
|
SecurityOpt: StringSliceToPtr(g.Find("security-opt")),
|
||||||
|
ShmSize: StringToPtr(g.Find("shm-size")),
|
||||||
|
StopSignal: StringToPtr(g.Find("stop-signal")),
|
||||||
|
StopTimeout: AnyIntToInt64Ptr(g.Find("stop-timeout")),
|
||||||
|
StorageOpt: StringSliceToPtr(g.Find("storage-opt")),
|
||||||
|
Subuidname: StringToPtr(g.Find("subuidname")),
|
||||||
|
Subgidname: StringToPtr(g.Find("subgidname")),
|
||||||
|
Sysctl: StringSliceToPtr(g.Find("sysctl")),
|
||||||
|
Systemd: BoolToPtr(g.Find("systemd")),
|
||||||
|
Tmpfs: StringSliceToPtr(g.Find("tmpfs")),
|
||||||
|
Tty: BoolToPtr(g.Find("tty")),
|
||||||
|
Uidmap: StringSliceToPtr(g.Find("uidmap")),
|
||||||
|
Ulimit: StringSliceToPtr(g.Find("ulimit")),
|
||||||
|
User: StringToPtr(g.Find("user")),
|
||||||
|
Userns: StringToPtr(g.Find("userns")),
|
||||||
|
Uts: StringToPtr(g.Find("uts")),
|
||||||
|
Mount: StringSliceToPtr(g.Find("mount")),
|
||||||
|
Volume: StringSliceToPtr(g.Find("volume")),
|
||||||
|
VolumesFrom: StringSliceToPtr(g.Find("volumes-from")),
|
||||||
|
WorkDir: StringToPtr(g.Find("workdir")),
|
||||||
|
}
|
||||||
|
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringSliceFromVarlink(v *[]string, flagName string, defaultValue *[]string) CRStringSlice {
|
||||||
|
cr := CRStringSlice{}
|
||||||
|
if v == nil {
|
||||||
|
cr.Val = []string{}
|
||||||
|
if defaultValue != nil {
|
||||||
|
cr.Val = *defaultValue
|
||||||
|
}
|
||||||
|
cr.Changed = false
|
||||||
|
} else {
|
||||||
|
cr.Val = *v
|
||||||
|
cr.Changed = true
|
||||||
|
}
|
||||||
|
cr.Flag = flagName
|
||||||
|
return cr
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringFromVarlink(v *string, flagName string, defaultValue *string) CRString {
|
||||||
|
cr := CRString{}
|
||||||
|
if v == nil {
|
||||||
|
cr.Val = ""
|
||||||
|
if defaultValue != nil {
|
||||||
|
cr.Val = *defaultValue
|
||||||
|
}
|
||||||
|
cr.Changed = false
|
||||||
|
} else {
|
||||||
|
cr.Val = *v
|
||||||
|
cr.Changed = true
|
||||||
|
}
|
||||||
|
cr.Flag = flagName
|
||||||
|
return cr
|
||||||
|
}
|
||||||
|
|
||||||
|
func boolFromVarlink(v *bool, flagName string, defaultValue bool) CRBool {
|
||||||
|
cr := CRBool{}
|
||||||
|
if v == nil {
|
||||||
|
// In case a cli bool default value is true
|
||||||
|
cr.Val = defaultValue
|
||||||
|
cr.Changed = false
|
||||||
|
} else {
|
||||||
|
fmt.Println(flagName, cr.Val)
|
||||||
|
cr.Val = *v
|
||||||
|
cr.Changed = true
|
||||||
|
}
|
||||||
|
cr.Flag = flagName
|
||||||
|
return cr
|
||||||
|
}
|
||||||
|
|
||||||
|
func uint64FromVarlink(v *int64, flagName string, defaultValue *uint64) CRUint64 {
|
||||||
|
cr := CRUint64{}
|
||||||
|
if v == nil {
|
||||||
|
cr.Val = 0
|
||||||
|
if defaultValue != nil {
|
||||||
|
cr.Val = *defaultValue
|
||||||
|
}
|
||||||
|
cr.Changed = false
|
||||||
|
} else {
|
||||||
|
cr.Val = uint64(*v)
|
||||||
|
cr.Changed = true
|
||||||
|
}
|
||||||
|
cr.Flag = flagName
|
||||||
|
return cr
|
||||||
|
}
|
||||||
|
|
||||||
|
func int64FromVarlink(v *int64, flagName string, defaultValue *int64) CRInt64 {
|
||||||
|
cr := CRInt64{}
|
||||||
|
if v == nil {
|
||||||
|
cr.Val = 0
|
||||||
|
if defaultValue != nil {
|
||||||
|
cr.Val = *defaultValue
|
||||||
|
}
|
||||||
|
cr.Changed = false
|
||||||
|
} else {
|
||||||
|
cr.Val = *v
|
||||||
|
cr.Changed = true
|
||||||
|
}
|
||||||
|
cr.Flag = flagName
|
||||||
|
return cr
|
||||||
|
}
|
||||||
|
|
||||||
|
func float64FromVarlink(v *float64, flagName string, defaultValue *float64) CRFloat64 {
|
||||||
|
cr := CRFloat64{}
|
||||||
|
if v == nil {
|
||||||
|
cr.Val = 0
|
||||||
|
if defaultValue != nil {
|
||||||
|
cr.Val = *defaultValue
|
||||||
|
}
|
||||||
|
cr.Changed = false
|
||||||
|
} else {
|
||||||
|
cr.Val = *v
|
||||||
|
cr.Changed = true
|
||||||
|
}
|
||||||
|
cr.Flag = flagName
|
||||||
|
return cr
|
||||||
|
}
|
||||||
|
|
||||||
|
func uintFromVarlink(v *int64, flagName string, defaultValue *uint) CRUint {
|
||||||
|
cr := CRUint{}
|
||||||
|
if v == nil {
|
||||||
|
cr.Val = 0
|
||||||
|
if defaultValue != nil {
|
||||||
|
cr.Val = *defaultValue
|
||||||
|
}
|
||||||
|
cr.Changed = false
|
||||||
|
} else {
|
||||||
|
cr.Val = uint(*v)
|
||||||
|
cr.Changed = true
|
||||||
|
}
|
||||||
|
cr.Flag = flagName
|
||||||
|
return cr
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringArrayFromVarlink(v *[]string, flagName string, defaultValue *[]string) CRStringArray {
|
||||||
|
cr := CRStringArray{}
|
||||||
|
if v == nil {
|
||||||
|
cr.Val = []string{}
|
||||||
|
if defaultValue != nil {
|
||||||
|
cr.Val = *defaultValue
|
||||||
|
}
|
||||||
|
cr.Changed = false
|
||||||
|
} else {
|
||||||
|
cr.Val = *v
|
||||||
|
cr.Changed = true
|
||||||
|
}
|
||||||
|
cr.Flag = flagName
|
||||||
|
return cr
|
||||||
|
}
|
||||||
|
|
||||||
|
func intFromVarlink(v *int64, flagName string, defaultValue *int) CRInt {
|
||||||
|
cr := CRInt{}
|
||||||
|
if v == nil {
|
||||||
|
if defaultValue != nil {
|
||||||
|
cr.Val = *defaultValue
|
||||||
|
}
|
||||||
|
cr.Val = 0
|
||||||
|
cr.Changed = false
|
||||||
|
} else {
|
||||||
|
cr.Val = int(*v)
|
||||||
|
cr.Changed = true
|
||||||
|
}
|
||||||
|
cr.Flag = flagName
|
||||||
|
return cr
|
||||||
|
}
|
||||||
|
|
||||||
|
// VarlinkCreateToGeneric creates a GenericCLIResults from the varlink create
|
||||||
|
// structure.
|
||||||
|
func VarlinkCreateToGeneric(opts iopodman.Create) GenericCLIResults {
|
||||||
|
|
||||||
|
// TODO | WARN
|
||||||
|
// We do not get a default network over varlink. Unlike the other default values for some cli
|
||||||
|
// elements, it seems it gets set to the default anyway.
|
||||||
|
|
||||||
|
m := make(map[string]GenericCLIResult)
|
||||||
|
m["add-host"] = stringSliceFromVarlink(opts.AddHost, "add-host", nil)
|
||||||
|
m["annotation"] = stringSliceFromVarlink(opts.Annotation, "annotation", nil)
|
||||||
|
m["attach"] = stringSliceFromVarlink(opts.Attach, "attach", nil)
|
||||||
|
m["blkio-weight"] = stringFromVarlink(opts.BlkioWeight, "blkio-weight", nil)
|
||||||
|
m["blkio-weight-device"] = stringSliceFromVarlink(opts.BlkioWeightDevice, "blkio-weight-device", nil)
|
||||||
|
m["cap-add"] = stringSliceFromVarlink(opts.CapAdd, "cap-add", nil)
|
||||||
|
m["cap-drop"] = stringSliceFromVarlink(opts.CapDrop, "cap-drop", nil)
|
||||||
|
m["cgroup-parent"] = stringFromVarlink(opts.CgroupParent, "cgroup-parent", nil)
|
||||||
|
m["cidfile"] = stringFromVarlink(opts.CidFile, "cidfile", nil)
|
||||||
|
m["conmon-pidfile"] = stringFromVarlink(opts.ConmonPidfile, "conmon-file", nil)
|
||||||
|
m["cpu-period"] = uint64FromVarlink(opts.CpuPeriod, "cpu-period", nil)
|
||||||
|
m["cpu-quota"] = int64FromVarlink(opts.CpuQuota, "quota", nil)
|
||||||
|
m["cpu-rt-period"] = uint64FromVarlink(opts.CpuRtPeriod, "cpu-rt-period", nil)
|
||||||
|
m["cpu-rt-runtime"] = int64FromVarlink(opts.CpuRtRuntime, "cpu-rt-quota", nil)
|
||||||
|
m["cpu-shares"] = uint64FromVarlink(opts.CpuShares, "cpu-shares", nil)
|
||||||
|
m["cpus"] = float64FromVarlink(opts.Cpus, "cpus", nil)
|
||||||
|
m["cpuset-cpus"] = stringFromVarlink(opts.CpuSetCpus, "cpuset-cpus", nil)
|
||||||
|
m["cpuset-mems"] = stringFromVarlink(opts.CpuSetMems, "cpuset-mems", nil)
|
||||||
|
m["detach"] = boolFromVarlink(opts.Detach, "detach", false)
|
||||||
|
m["detach-keys"] = stringFromVarlink(opts.DetachKeys, "detach-keys", nil)
|
||||||
|
m["device"] = stringSliceFromVarlink(opts.Device, "device", nil)
|
||||||
|
m["device-read-bps"] = stringSliceFromVarlink(opts.DeviceReadBps, "device-read-bps", nil)
|
||||||
|
m["device-read-iops"] = stringSliceFromVarlink(opts.DeviceReadIops, "device-read-iops", nil)
|
||||||
|
m["device-write-bps"] = stringSliceFromVarlink(opts.DeviceWriteBps, "write-device-bps", nil)
|
||||||
|
m["device-write-iops"] = stringSliceFromVarlink(opts.DeviceWriteIops, "write-device-iops", nil)
|
||||||
|
m["dns"] = stringSliceFromVarlink(opts.Dns, "dns", nil)
|
||||||
|
m["dns-opt"] = stringSliceFromVarlink(opts.DnsOpt, "dns-opt", nil)
|
||||||
|
m["dns-search"] = stringSliceFromVarlink(opts.DnsSearch, "dns-search", nil)
|
||||||
|
m["entrypoint"] = stringFromVarlink(opts.Entrypoint, "entrypoint", nil)
|
||||||
|
m["env"] = stringArrayFromVarlink(opts.Env, "env", nil)
|
||||||
|
m["env-file"] = stringSliceFromVarlink(opts.EnvFile, "env-file", nil)
|
||||||
|
m["expose"] = stringSliceFromVarlink(opts.Expose, "expose", nil)
|
||||||
|
m["gidmap"] = stringSliceFromVarlink(opts.Gidmap, "gidmap", nil)
|
||||||
|
m["group-add"] = stringSliceFromVarlink(opts.Groupadd, "group-add", nil)
|
||||||
|
m["healthcheck-command"] = stringFromVarlink(opts.HealthcheckCommand, "healthcheck-command", nil)
|
||||||
|
m["healthcheck-interval"] = stringFromVarlink(opts.HealthcheckInterval, "healthcheck-interval", &cliconfig.DefaultHealthCheckInterval)
|
||||||
|
m["healthcheck-retries"] = uintFromVarlink(opts.HealthcheckRetries, "healthcheck-retries", &cliconfig.DefaultHealthCheckRetries)
|
||||||
|
m["healthcheck-start-period"] = stringFromVarlink(opts.HealthcheckStartPeriod, "healthcheck-start-period", &cliconfig.DefaultHealthCheckStartPeriod)
|
||||||
|
m["healthcheck-timeout"] = stringFromVarlink(opts.HealthcheckTimeout, "healthcheck-timeout", &cliconfig.DefaultHealthCheckTimeout)
|
||||||
|
m["hostname"] = stringFromVarlink(opts.Hostname, "hostname", nil)
|
||||||
|
m["image-volume"] = stringFromVarlink(opts.ImageVolume, "image-volume", &cliconfig.DefaultImageVolume)
|
||||||
|
m["init"] = boolFromVarlink(opts.Init, "init", false)
|
||||||
|
m["init-path"] = stringFromVarlink(opts.InitPath, "init-path", nil)
|
||||||
|
m["interactive"] = boolFromVarlink(opts.Interactive, "interactive", false)
|
||||||
|
m["ip"] = stringFromVarlink(opts.Ip, "ip", nil)
|
||||||
|
m["ipc"] = stringFromVarlink(opts.Ipc, "ipc", nil)
|
||||||
|
m["kernel-memory"] = stringFromVarlink(opts.KernelMemory, "kernel-memory", nil)
|
||||||
|
m["label"] = stringArrayFromVarlink(opts.Label, "label", nil)
|
||||||
|
m["label-file"] = stringSliceFromVarlink(opts.LabelFile, "label-file", nil)
|
||||||
|
m["log-driver"] = stringFromVarlink(opts.LogDriver, "log-driver", nil)
|
||||||
|
m["log-opt"] = stringSliceFromVarlink(opts.LogOpt, "log-opt", nil)
|
||||||
|
m["mac-address"] = stringFromVarlink(opts.MacAddress, "mac-address", nil)
|
||||||
|
m["memory"] = stringFromVarlink(opts.Memory, "memory", nil)
|
||||||
|
m["memory-reservation"] = stringFromVarlink(opts.MemoryReservation, "memory-reservation", nil)
|
||||||
|
m["memory-swap"] = stringFromVarlink(opts.MemorySwap, "memory-swap", nil)
|
||||||
|
m["memory-swappiness"] = int64FromVarlink(opts.MemorySwappiness, "memory-swappiness", nil)
|
||||||
|
m["name"] = stringFromVarlink(opts.Name, "name", nil)
|
||||||
|
m["net"] = stringFromVarlink(opts.Net, "net", nil)
|
||||||
|
m["network"] = stringFromVarlink(opts.Network, "network", nil)
|
||||||
|
m["no-hosts"] = boolFromVarlink(opts.NoHosts, "no-hosts", false)
|
||||||
|
m["oom-kill-disable"] = boolFromVarlink(opts.OomKillDisable, "oon-kill-disable", false)
|
||||||
|
m["oom-score-adj"] = intFromVarlink(opts.OomScoreAdj, "oom-score-adj", nil)
|
||||||
|
m["pid"] = stringFromVarlink(opts.Pid, "pid", nil)
|
||||||
|
m["pids-limit"] = int64FromVarlink(opts.PidsLimit, "pids-limit", nil)
|
||||||
|
m["pod"] = stringFromVarlink(opts.Pod, "pod", nil)
|
||||||
|
m["privileged"] = boolFromVarlink(opts.Privileged, "privileged", false)
|
||||||
|
m["publish"] = stringSliceFromVarlink(opts.Publish, "publish", nil)
|
||||||
|
m["publish-all"] = boolFromVarlink(opts.PublishAll, "publish-all", false)
|
||||||
|
m["quiet"] = boolFromVarlink(opts.Quiet, "quiet", false)
|
||||||
|
m["read-only"] = boolFromVarlink(opts.Readonly, "read-only", false)
|
||||||
|
m["restart"] = stringFromVarlink(opts.Restart, "restart", nil)
|
||||||
|
m["rm"] = boolFromVarlink(opts.Rm, "rm", false)
|
||||||
|
m["rootfs"] = boolFromVarlink(opts.Rootfs, "rootfs", false)
|
||||||
|
m["security-opt"] = stringArrayFromVarlink(opts.SecurityOpt, "security-opt", nil)
|
||||||
|
m["shm-size"] = stringFromVarlink(opts.ShmSize, "shm-size", &cliconfig.DefaultShmSize)
|
||||||
|
m["stop-signal"] = stringFromVarlink(opts.StopSignal, "stop-signal", nil)
|
||||||
|
m["stop-timeout"] = uintFromVarlink(opts.StopTimeout, "stop-timeout", nil)
|
||||||
|
m["storage-opt"] = stringSliceFromVarlink(opts.StorageOpt, "storage-opt", nil)
|
||||||
|
m["subgidname"] = stringFromVarlink(opts.Subgidname, "subgidname", nil)
|
||||||
|
m["subuidname"] = stringFromVarlink(opts.Subuidname, "subuidname", nil)
|
||||||
|
m["sysctl"] = stringSliceFromVarlink(opts.Sysctl, "sysctl", nil)
|
||||||
|
m["systemd"] = boolFromVarlink(opts.Systemd, "systemd", cliconfig.DefaultSystemD)
|
||||||
|
m["tmpfs"] = stringSliceFromVarlink(opts.Tmpfs, "tmpfs", nil)
|
||||||
|
m["tty"] = boolFromVarlink(opts.Tty, "tty", false)
|
||||||
|
m["uidmap"] = stringSliceFromVarlink(opts.Uidmap, "uidmap", nil)
|
||||||
|
m["ulimit"] = stringSliceFromVarlink(opts.Ulimit, "ulimit", nil)
|
||||||
|
m["user"] = stringFromVarlink(opts.User, "user", nil)
|
||||||
|
m["userns"] = stringFromVarlink(opts.Userns, "userns", nil)
|
||||||
|
m["uts"] = stringFromVarlink(opts.Uts, "uts", nil)
|
||||||
|
m["mount"] = stringArrayFromVarlink(opts.Mount, "mount", nil)
|
||||||
|
m["volume"] = stringArrayFromVarlink(opts.Volume, "volume", nil)
|
||||||
|
m["volumes-from"] = stringSliceFromVarlink(opts.VolumesFrom, "volumes-from", nil)
|
||||||
|
m["workdir"] = stringFromVarlink(opts.WorkDir, "workdir", nil)
|
||||||
|
|
||||||
|
gcli := GenericCLIResults{m, opts.Args}
|
||||||
|
return gcli
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find returns a flag from a GenericCLIResults by name
|
||||||
|
func (g GenericCLIResults) Find(name string) GenericCLIResult {
|
||||||
|
result, ok := g.results[name]
|
||||||
|
if ok {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
panic(errors.Errorf("unable to find generic flag for varlink %s", name))
|
||||||
|
}
|
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||||
"github.com/containers/libpod/libpod"
|
"github.com/containers/libpod/libpod"
|
||||||
|
"github.com/containers/libpod/pkg/adapter"
|
||||||
opentracing "github.com/opentracing/opentracing-go"
|
opentracing "github.com/opentracing/opentracing-go"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@ -109,7 +110,7 @@ func startCmd(c *cliconfig.StartValues) error {
|
|||||||
|
|
||||||
// attach to the container and also start it not already running
|
// attach to the container and also start it not already running
|
||||||
// If the container is in a pod, also set to recursively start dependencies
|
// If the container is in a pod, also set to recursively start dependencies
|
||||||
err = startAttachCtr(ctr, os.Stdout, os.Stderr, inputStream, c.DetachKeys, sigProxy, !ctrRunning, ctr.PodID() != "")
|
err = adapter.StartAttachCtr(ctx, ctr, os.Stdout, os.Stderr, inputStream, c.DetachKeys, sigProxy, !ctrRunning, ctr.PodID() != "")
|
||||||
if errors.Cause(err) == libpod.ErrDetach {
|
if errors.Cause(err) == libpod.ErrDetach {
|
||||||
// User manually detached
|
// User manually detached
|
||||||
// Exit cleanly immediately
|
// Exit cleanly immediately
|
||||||
@ -133,7 +134,7 @@ func startCmd(c *cliconfig.StartValues) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ctrExitCode, err := readExitFile(rtc.TmpDir, ctr.ID())
|
ctrExitCode, err := adapter.ReadExitFile(rtc.TmpDir, ctr.ID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("Cannot get exit code: %v", err)
|
logrus.Errorf("Cannot get exit code: %v", err)
|
||||||
exitCode = 127
|
exitCode = 127
|
||||||
|
@ -1,205 +1,11 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
"os"
|
|
||||||
gosignal "os/signal"
|
|
||||||
|
|
||||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
|
||||||
"github.com/containers/libpod/libpod"
|
|
||||||
"github.com/docker/docker/pkg/signal"
|
|
||||||
"github.com/docker/docker/pkg/term"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"golang.org/x/crypto/ssh/terminal"
|
|
||||||
"k8s.io/client-go/tools/remotecommand"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type RawTtyFormatter struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start (if required) and attach to a container
|
|
||||||
func startAttachCtr(ctr *libpod.Container, stdout, stderr, stdin *os.File, detachKeys string, sigProxy bool, startContainer bool, recursive bool) error {
|
|
||||||
ctx := context.Background()
|
|
||||||
resize := make(chan remotecommand.TerminalSize)
|
|
||||||
|
|
||||||
haveTerminal := terminal.IsTerminal(int(os.Stdin.Fd()))
|
|
||||||
|
|
||||||
// Check if we are attached to a terminal. If we are, generate resize
|
|
||||||
// events, and set the terminal to raw mode
|
|
||||||
if haveTerminal && ctr.Spec().Process.Terminal {
|
|
||||||
logrus.Debugf("Handling terminal attach")
|
|
||||||
|
|
||||||
subCtx, cancel := context.WithCancel(ctx)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
resizeTty(subCtx, resize)
|
|
||||||
|
|
||||||
oldTermState, err := term.SaveState(os.Stdin.Fd())
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "unable to save terminal state")
|
|
||||||
}
|
|
||||||
|
|
||||||
logrus.SetFormatter(&RawTtyFormatter{})
|
|
||||||
term.SetRawTerminal(os.Stdin.Fd())
|
|
||||||
|
|
||||||
defer restoreTerminal(oldTermState)
|
|
||||||
}
|
|
||||||
|
|
||||||
streams := new(libpod.AttachStreams)
|
|
||||||
streams.OutputStream = stdout
|
|
||||||
streams.ErrorStream = stderr
|
|
||||||
streams.InputStream = stdin
|
|
||||||
streams.AttachOutput = true
|
|
||||||
streams.AttachError = true
|
|
||||||
streams.AttachInput = true
|
|
||||||
|
|
||||||
if stdout == nil {
|
|
||||||
logrus.Debugf("Not attaching to stdout")
|
|
||||||
streams.AttachOutput = false
|
|
||||||
}
|
|
||||||
if stderr == nil {
|
|
||||||
logrus.Debugf("Not attaching to stderr")
|
|
||||||
streams.AttachError = false
|
|
||||||
}
|
|
||||||
if stdin == nil {
|
|
||||||
logrus.Debugf("Not attaching to stdin")
|
|
||||||
streams.AttachInput = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if !startContainer {
|
|
||||||
if sigProxy {
|
|
||||||
ProxySignals(ctr)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctr.Attach(streams, detachKeys, resize)
|
|
||||||
}
|
|
||||||
|
|
||||||
attachChan, err := ctr.StartAndAttach(getContext(), streams, detachKeys, resize, recursive)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if sigProxy {
|
|
||||||
ProxySignals(ctr)
|
|
||||||
}
|
|
||||||
|
|
||||||
if stdout == nil && stderr == nil {
|
|
||||||
fmt.Printf("%s\n", ctr.ID())
|
|
||||||
}
|
|
||||||
|
|
||||||
err = <-attachChan
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "error attaching to container %s", ctr.ID())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// getResize returns a TerminalSize command matching stdin's current
|
|
||||||
// size on success, and nil on errors.
|
|
||||||
func getResize() *remotecommand.TerminalSize {
|
|
||||||
winsize, err := term.GetWinsize(os.Stdin.Fd())
|
|
||||||
if err != nil {
|
|
||||||
logrus.Warnf("Could not get terminal size %v", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return &remotecommand.TerminalSize{
|
|
||||||
Width: winsize.Width,
|
|
||||||
Height: winsize.Height,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper for prepareAttach - set up a goroutine to generate terminal resize events
|
|
||||||
func resizeTty(ctx context.Context, resize chan remotecommand.TerminalSize) {
|
|
||||||
sigchan := make(chan os.Signal, 1)
|
|
||||||
gosignal.Notify(sigchan, signal.SIGWINCH)
|
|
||||||
go func() {
|
|
||||||
defer close(resize)
|
|
||||||
// Update the terminal size immediately without waiting
|
|
||||||
// for a SIGWINCH to get the correct initial size.
|
|
||||||
resizeEvent := getResize()
|
|
||||||
for {
|
|
||||||
if resizeEvent == nil {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
case <-sigchan:
|
|
||||||
resizeEvent = getResize()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
case <-sigchan:
|
|
||||||
resizeEvent = getResize()
|
|
||||||
case resize <- *resizeEvent:
|
|
||||||
resizeEvent = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
func restoreTerminal(state *term.State) error {
|
|
||||||
logrus.SetFormatter(&logrus.TextFormatter{})
|
|
||||||
return term.RestoreTerminal(os.Stdin.Fd(), state)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *RawTtyFormatter) Format(entry *logrus.Entry) ([]byte, error) {
|
|
||||||
textFormatter := logrus.TextFormatter{}
|
|
||||||
bytes, err := textFormatter.Format(entry)
|
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
bytes = append(bytes, '\r')
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytes, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// For pod commands that have a latest and all flag, getPodsFromContext gets
|
|
||||||
// pods the user specifies. If there's an error before getting pods, the pods slice
|
|
||||||
// will be empty and error will be not nil. If an error occured after, the pod slice
|
|
||||||
// will hold all of the successful pods, and error will hold the last error.
|
|
||||||
// The remaining errors will be logged. On success, pods will hold all pods and
|
|
||||||
// error will be nil.
|
|
||||||
func getPodsFromContext(c *cliconfig.PodmanCommand, r *libpod.Runtime) ([]*libpod.Pod, error) {
|
|
||||||
args := c.InputArgs
|
|
||||||
var pods []*libpod.Pod
|
|
||||||
var lastError error
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if c.Bool("all") {
|
|
||||||
pods, err = r.GetAllPods()
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "unable to get running pods")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Bool("latest") {
|
|
||||||
pod, err := r.GetLatestPod()
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "unable to get latest pod")
|
|
||||||
}
|
|
||||||
pods = append(pods, pod)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, i := range args {
|
|
||||||
pod, err := r.LookupPod(i)
|
|
||||||
if err != nil {
|
|
||||||
if lastError != nil {
|
|
||||||
logrus.Errorf("%q", lastError)
|
|
||||||
}
|
|
||||||
lastError = errors.Wrapf(err, "unable to find pod %s", i)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
pods = append(pods, pod)
|
|
||||||
}
|
|
||||||
return pods, lastError
|
|
||||||
}
|
|
||||||
|
|
||||||
//printParallelOutput takes the map of parallel worker results and outputs them
|
//printParallelOutput takes the map of parallel worker results and outputs them
|
||||||
// to stdout
|
// to stdout
|
||||||
func printParallelOutput(m map[string]error, errCount int) error {
|
func printParallelOutput(m map[string]error, errCount int) error {
|
||||||
|
@ -225,117 +225,104 @@ type Sockets(
|
|||||||
control_socket: string
|
control_socket: string
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create is an input structure for creating containers. It closely resembles the
|
# Create is an input structure for creating containers.
|
||||||
# CreateConfig structure in libpod/pkg/spec.
|
|
||||||
type Create (
|
type Create (
|
||||||
args: []string,
|
args: []string,
|
||||||
cap_add: []string,
|
addHost: ?[]string,
|
||||||
cap_drop: []string,
|
annotation: ?[]string,
|
||||||
conmon_pidfile: string,
|
attach: ?[]string,
|
||||||
cgroup_parent: string,
|
blkioWeight: ?string,
|
||||||
command: []string,
|
blkioWeightDevice: ?[]string,
|
||||||
detach: bool,
|
capAdd: ?[]string,
|
||||||
devices: []string,
|
capDrop: ?[]string,
|
||||||
dns_opt: []string,
|
cgroupParent: ?string,
|
||||||
dns_search: []string,
|
cidFile: ?string,
|
||||||
dns_servers: []string,
|
conmonPidfile: ?string,
|
||||||
entrypoint: []string,
|
command: ?[]string,
|
||||||
env: [string]string,
|
cpuPeriod: ?int,
|
||||||
exposed_ports: []string,
|
cpuQuota: ?int,
|
||||||
gidmap: []string,
|
cpuRtPeriod: ?int,
|
||||||
group_add: []string,
|
cpuRtRuntime: ?int,
|
||||||
host_add: []string,
|
cpuShares: ?int,
|
||||||
hostname: string,
|
cpus: ?float,
|
||||||
image: string,
|
cpuSetCpus: ?string,
|
||||||
image_id: string,
|
cpuSetMems: ?string,
|
||||||
init: bool,
|
detach: ?bool,
|
||||||
init_path: string,
|
detachKeys: ?string,
|
||||||
builtin_imgvolumes: []string,
|
device: ?[]string,
|
||||||
id_mappings: IDMappingOptions,
|
deviceReadBps: ?[]string,
|
||||||
image_volume_type: string,
|
deviceReadIops: ?[]string,
|
||||||
interactive: bool,
|
deviceWriteBps: ?[]string,
|
||||||
ipc_mode: string,
|
deviceWriteIops: ?[]string,
|
||||||
labels: [string]string,
|
dns: ?[]string,
|
||||||
log_driver: string,
|
dnsOpt: ?[]string,
|
||||||
log_driver_opt: []string,
|
dnsSearch: ?[]string,
|
||||||
name: string,
|
dnsServers: ?[]string,
|
||||||
net_mode: string,
|
entrypoint: ?string,
|
||||||
network: string,
|
env: ?[]string,
|
||||||
pid_mode: string,
|
envFile: ?[]string,
|
||||||
pod: string,
|
expose: ?[]string,
|
||||||
privileged: bool,
|
gidmap: ?[]string,
|
||||||
publish: []string,
|
groupadd: ?[]string,
|
||||||
publish_all: bool,
|
healthcheckCommand: ?string,
|
||||||
quiet: bool,
|
healthcheckInterval: ?string,
|
||||||
readonly_rootfs: bool,
|
healthcheckRetries: ?int,
|
||||||
resources: CreateResourceConfig,
|
healthcheckStartPeriod: ?string,
|
||||||
rm: bool,
|
healthcheckTimeout:?string,
|
||||||
shm_dir: string,
|
hostname: ?string,
|
||||||
stop_signal: int,
|
imageVolume: ?string,
|
||||||
stop_timeout: int,
|
init: ?bool,
|
||||||
subuidmap: string,
|
initPath: ?string,
|
||||||
subgidmap: string,
|
interactive: ?bool,
|
||||||
subuidname: string,
|
ip: ?string,
|
||||||
subgidname: string,
|
ipc: ?string,
|
||||||
sys_ctl: [string]string,
|
kernelMemory: ?string,
|
||||||
tmpfs: []string,
|
label: ?[]string,
|
||||||
tty: bool,
|
labelFile: ?[]string,
|
||||||
uidmap: []string,
|
logDriver: ?string,
|
||||||
userns_mode: string,
|
logOpt: ?[]string,
|
||||||
user: string,
|
macAddress: ?string,
|
||||||
uts_mode: string,
|
memory: ?string,
|
||||||
volumes: []string,
|
memoryReservation: ?string,
|
||||||
work_dir: string,
|
memorySwap: ?string,
|
||||||
mount_label: string,
|
memorySwappiness: ?int,
|
||||||
process_label: string,
|
name: ?string,
|
||||||
no_new_privs: bool,
|
net: ?string,
|
||||||
apparmor_profile: string,
|
network: ?string,
|
||||||
seccomp_profile_path: string,
|
noHosts: ?bool,
|
||||||
security_opts: []string
|
oomKillDisable: ?bool,
|
||||||
)
|
oomScoreAdj: ?int,
|
||||||
|
pid: ?string,
|
||||||
# CreateResourceConfig is an input structure used to describe host attributes during
|
pidsLimit: ?int,
|
||||||
# container creation. It is only valid inside a [Create](#Create) type.
|
pod: ?string,
|
||||||
type CreateResourceConfig (
|
privileged: ?bool,
|
||||||
blkio_weight: int,
|
publish: ?[]string,
|
||||||
blkio_weight_device: []string,
|
publishAll: ?bool,
|
||||||
cpu_period: int,
|
quiet: ?bool,
|
||||||
cpu_quota: int,
|
readonly: ?bool,
|
||||||
cpu_rt_period: int,
|
restart: ?string,
|
||||||
cpu_rt_runtime: int,
|
rm: ?bool,
|
||||||
cpu_shares: int,
|
rootfs: ?bool,
|
||||||
cpus: float,
|
securityOpt: ?[]string,
|
||||||
cpuset_cpus: string,
|
shmSize: ?string,
|
||||||
cpuset_mems: string,
|
stopSignal: ?string,
|
||||||
device_read_bps: []string,
|
stopTimeout: ?int,
|
||||||
device_read_iops: []string,
|
storageOpt: ?[]string,
|
||||||
device_write_bps: []string,
|
subuidname: ?string,
|
||||||
device_write_iops: []string,
|
subgidname: ?string,
|
||||||
disable_oomkiller: bool,
|
sysctl: ?[]string,
|
||||||
kernel_memory: int,
|
systemd: ?bool,
|
||||||
memory: int,
|
tmpfs: ?[]string,
|
||||||
memory_reservation: int,
|
tty: ?bool,
|
||||||
memory_swap: int,
|
uidmap: ?[]string,
|
||||||
memory_swappiness: int,
|
ulimit: ?[]string,
|
||||||
oom_score_adj: int,
|
user: ?string,
|
||||||
pids_limit: int,
|
userns: ?string,
|
||||||
shm_size: int,
|
uts: ?string,
|
||||||
ulimit: []string
|
mount: ?[]string,
|
||||||
)
|
volume: ?[]string,
|
||||||
|
volumesFrom: ?[]string,
|
||||||
# IDMappingOptions is an input structure used to described ids during container creation.
|
workDir: ?string
|
||||||
type IDMappingOptions (
|
|
||||||
host_uid_mapping: bool,
|
|
||||||
host_gid_mapping: bool,
|
|
||||||
uid_map: IDMap,
|
|
||||||
gid_map: IDMap
|
|
||||||
)
|
|
||||||
|
|
||||||
# IDMap is used to describe user name spaces during container creation
|
|
||||||
type IDMap (
|
|
||||||
container_id: int,
|
|
||||||
host_id: int,
|
|
||||||
size: int
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# BuildOptions are are used to describe describe physical attributes of the build
|
# BuildOptions are are used to describe describe physical attributes of the build
|
||||||
@ -498,16 +485,7 @@ method GetContainer(id: string) -> (container: Container)
|
|||||||
# user environment, results might differ from what you expect.
|
# user environment, results might differ from what you expect.
|
||||||
method GetContainersByContext(all: bool, latest: bool, args: []string) -> (containers: []string)
|
method GetContainersByContext(all: bool, latest: bool, args: []string) -> (containers: []string)
|
||||||
|
|
||||||
# CreateContainer creates a new container from an image. It uses a [Create](#Create) type for input. The minimum
|
# CreateContainer creates a new container from an image. It uses a [Create](#Create) type for input.
|
||||||
# input required for CreateContainer is an image name. If the image name is not found, an [ImageNotFound](#ImageNotFound)
|
|
||||||
# error will be returned. Otherwise, the ID of the newly created container will be returned.
|
|
||||||
# #### Example
|
|
||||||
# ~~~
|
|
||||||
# $ varlink call unix:/run/podman/io.podman/io.podman.CreateContainer '{"create": {"image": "alpine"}}'
|
|
||||||
# {
|
|
||||||
# "container": "8759dafbc0a4dc3bcfb57eeb72e4331eb73c5cc09ab968e65ce45b9ad5c4b6bb"
|
|
||||||
# }
|
|
||||||
# ~~~
|
|
||||||
method CreateContainer(create: Create) -> (container: string)
|
method CreateContainer(create: Create) -> (container: string)
|
||||||
|
|
||||||
# InspectContainer data takes a name or ID of a container returns the inspection
|
# InspectContainer data takes a name or ID of a container returns the inspection
|
||||||
@ -1130,6 +1108,9 @@ method ContainerStateData(name: string) -> (config: string)
|
|||||||
# development of Podman only and generally should not be used.
|
# development of Podman only and generally should not be used.
|
||||||
method PodStateData(name: string) -> (config: string)
|
method PodStateData(name: string) -> (config: string)
|
||||||
|
|
||||||
|
# This call is for the development of Podman only and should not be used.
|
||||||
|
method CreateFromCC(in: []string) -> (id: string)
|
||||||
|
|
||||||
# Sendfile allows a remote client to send a file to the host
|
# Sendfile allows a remote client to send a file to the host
|
||||||
method SendFile(type: string, length: int) -> (file_handle: string)
|
method SendFile(type: string, length: int) -> (file_handle: string)
|
||||||
|
|
||||||
|
@ -5,12 +5,17 @@ package adapter
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||||
|
"github.com/containers/libpod/cmd/podman/shared"
|
||||||
"github.com/containers/libpod/libpod"
|
"github.com/containers/libpod/libpod"
|
||||||
"github.com/containers/libpod/pkg/adapter/shortcuts"
|
"github.com/containers/libpod/pkg/adapter/shortcuts"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -154,3 +159,148 @@ func (r *LocalRuntime) Log(c *cliconfig.LogsValues, options *libpod.LogOptions)
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateContainer creates a libpod container
|
||||||
|
func (r *LocalRuntime) CreateContainer(ctx context.Context, c *cliconfig.CreateValues) (string, error) {
|
||||||
|
results := shared.NewIntermediateLayer(&c.PodmanCommand)
|
||||||
|
ctr, _, err := shared.CreateContainer(ctx, &results, r.Runtime)
|
||||||
|
return ctr.ID(), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run a libpod container
|
||||||
|
func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode int) (int, error) {
|
||||||
|
results := shared.NewIntermediateLayer(&c.PodmanCommand)
|
||||||
|
|
||||||
|
ctr, createConfig, err := shared.CreateContainer(ctx, &results, r.Runtime)
|
||||||
|
if err != nil {
|
||||||
|
return exitCode, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if logrus.GetLevel() == logrus.DebugLevel {
|
||||||
|
cgroupPath, err := ctr.CGroupPath()
|
||||||
|
if err == nil {
|
||||||
|
logrus.Debugf("container %q has CgroupParent %q", ctr.ID(), cgroupPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle detached start
|
||||||
|
if createConfig.Detach {
|
||||||
|
// if the container was created as part of a pod, also start its dependencies, if any.
|
||||||
|
if err := ctr.Start(ctx, c.IsSet("pod")); err != nil {
|
||||||
|
// This means the command did not exist
|
||||||
|
exitCode = 127
|
||||||
|
if strings.Index(err.Error(), "permission denied") > -1 {
|
||||||
|
exitCode = 126
|
||||||
|
}
|
||||||
|
return exitCode, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%s\n", ctr.ID())
|
||||||
|
exitCode = 0
|
||||||
|
return exitCode, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
outputStream := os.Stdout
|
||||||
|
errorStream := os.Stderr
|
||||||
|
inputStream := os.Stdin
|
||||||
|
|
||||||
|
// If -i is not set, clear stdin
|
||||||
|
if !c.Bool("interactive") {
|
||||||
|
inputStream = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// If attach is set, clear stdin/stdout/stderr and only attach requested
|
||||||
|
if c.IsSet("attach") || c.IsSet("a") {
|
||||||
|
outputStream = nil
|
||||||
|
errorStream = nil
|
||||||
|
if !c.Bool("interactive") {
|
||||||
|
inputStream = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
attachTo := c.StringSlice("attach")
|
||||||
|
for _, stream := range attachTo {
|
||||||
|
switch strings.ToLower(stream) {
|
||||||
|
case "stdout":
|
||||||
|
outputStream = os.Stdout
|
||||||
|
case "stderr":
|
||||||
|
errorStream = os.Stderr
|
||||||
|
case "stdin":
|
||||||
|
inputStream = os.Stdin
|
||||||
|
default:
|
||||||
|
return exitCode, errors.Wrapf(libpod.ErrInvalidArg, "invalid stream %q for --attach - must be one of stdin, stdout, or stderr", stream)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if the container was created as part of a pod, also start its dependencies, if any.
|
||||||
|
if err := StartAttachCtr(ctx, ctr, outputStream, errorStream, inputStream, c.String("detach-keys"), c.Bool("sig-proxy"), true, c.IsSet("pod")); err != nil {
|
||||||
|
// We've manually detached from the container
|
||||||
|
// Do not perform cleanup, or wait for container exit code
|
||||||
|
// Just exit immediately
|
||||||
|
if errors.Cause(err) == libpod.ErrDetach {
|
||||||
|
exitCode = 0
|
||||||
|
return exitCode, nil
|
||||||
|
}
|
||||||
|
// This means the command did not exist
|
||||||
|
exitCode = 127
|
||||||
|
if strings.Index(err.Error(), "permission denied") > -1 {
|
||||||
|
exitCode = 126
|
||||||
|
}
|
||||||
|
if c.IsSet("rm") {
|
||||||
|
if deleteError := r.Runtime.RemoveContainer(ctx, ctr, true, false); deleteError != nil {
|
||||||
|
logrus.Errorf("unable to remove container %s after failing to start and attach to it", ctr.ID())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return exitCode, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if ecode, err := ctr.Wait(); err != nil {
|
||||||
|
if errors.Cause(err) == libpod.ErrNoSuchCtr {
|
||||||
|
// The container may have been removed
|
||||||
|
// Go looking for an exit file
|
||||||
|
config, err := r.Runtime.GetConfig()
|
||||||
|
if err != nil {
|
||||||
|
return exitCode, err
|
||||||
|
}
|
||||||
|
ctrExitCode, err := ReadExitFile(config.TmpDir, ctr.ID())
|
||||||
|
if err != nil {
|
||||||
|
logrus.Errorf("Cannot get exit code: %v", err)
|
||||||
|
exitCode = 127
|
||||||
|
} else {
|
||||||
|
exitCode = ctrExitCode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
exitCode = int(ecode)
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.IsSet("rm") {
|
||||||
|
r.Runtime.RemoveContainer(ctx, ctr, false, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return exitCode, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadExitFile reads a container's exit file
|
||||||
|
func ReadExitFile(runtimeTmp, ctrID string) (int, error) {
|
||||||
|
exitFile := filepath.Join(runtimeTmp, "exits", fmt.Sprintf("%s-old", ctrID))
|
||||||
|
|
||||||
|
logrus.Debugf("Attempting to read container %s exit code from file %s", ctrID, exitFile)
|
||||||
|
|
||||||
|
// Check if it exists
|
||||||
|
if _, err := os.Stat(exitFile); err != nil {
|
||||||
|
return 0, errors.Wrapf(err, "error getting exit file for container %s", ctrID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// File exists, read it in and convert to int
|
||||||
|
statusStr, err := ioutil.ReadFile(exitFile)
|
||||||
|
if err != nil {
|
||||||
|
return 0, errors.Wrapf(err, "error reading exit file for container %s", ctrID)
|
||||||
|
}
|
||||||
|
|
||||||
|
exitCode, err := strconv.Atoi(string(statusStr))
|
||||||
|
if err != nil {
|
||||||
|
return 0, errors.Wrapf(err, "error parsing exit code for container %s", ctrID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return exitCode, nil
|
||||||
|
}
|
||||||
|
@ -262,3 +262,33 @@ func (r *LocalRuntime) Log(c *cliconfig.LogsValues, options *libpod.LogOptions)
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateContainer creates a container from the cli over varlink
|
||||||
|
func (r *LocalRuntime) CreateContainer(ctx context.Context, c *cliconfig.CreateValues) (string, error) {
|
||||||
|
if !c.Bool("detach") {
|
||||||
|
// TODO need to add attach when that function becomes available
|
||||||
|
return "", errors.New("the remote client only supports detached containers")
|
||||||
|
}
|
||||||
|
results := shared.NewIntermediateLayer(&c.PodmanCommand)
|
||||||
|
return iopodman.CreateContainer().Call(r.Conn, results.MakeVarlink())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run creates a container overvarlink and then starts it
|
||||||
|
func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode int) (int, error) {
|
||||||
|
// TODO the exit codes for run need to be figured out for remote connections
|
||||||
|
if !c.Bool("detach") {
|
||||||
|
return 0, errors.New("the remote client only supports detached containers")
|
||||||
|
}
|
||||||
|
results := shared.NewIntermediateLayer(&c.PodmanCommand)
|
||||||
|
cid, err := iopodman.CreateContainer().Call(r.Conn, results.MakeVarlink())
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
fmt.Println(cid)
|
||||||
|
_, err = iopodman.StartContainer().Call(r.Conn, cid)
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadExitFile(runtimeTmp, ctrID string) (int, error) {
|
||||||
|
return 0, libpod.ErrNotImplemented
|
||||||
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package main
|
package adapter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ProxySignals ...
|
||||||
func ProxySignals(ctr *libpod.Container) {
|
func ProxySignals(ctr *libpod.Container) {
|
||||||
sigBuffer := make(chan os.Signal, 128)
|
sigBuffer := make(chan os.Signal, 128)
|
||||||
signal.CatchAll(sigBuffer)
|
signal.CatchAll(sigBuffer)
|
159
pkg/adapter/terminal.go
Normal file
159
pkg/adapter/terminal.go
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
package adapter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
gosignal "os/signal"
|
||||||
|
|
||||||
|
"github.com/containers/libpod/libpod"
|
||||||
|
"github.com/docker/docker/pkg/signal"
|
||||||
|
"github.com/docker/docker/pkg/term"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/crypto/ssh/terminal"
|
||||||
|
"k8s.io/client-go/tools/remotecommand"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RawTtyFormatter ...
|
||||||
|
type RawTtyFormatter struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartAttachCtr starts and (if required) attaches to a container
|
||||||
|
func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr, stdin *os.File, detachKeys string, sigProxy bool, startContainer bool, recursive bool) error {
|
||||||
|
resize := make(chan remotecommand.TerminalSize)
|
||||||
|
|
||||||
|
haveTerminal := terminal.IsTerminal(int(os.Stdin.Fd()))
|
||||||
|
|
||||||
|
// Check if we are attached to a terminal. If we are, generate resize
|
||||||
|
// events, and set the terminal to raw mode
|
||||||
|
if haveTerminal && ctr.Spec().Process.Terminal {
|
||||||
|
logrus.Debugf("Handling terminal attach")
|
||||||
|
|
||||||
|
subCtx, cancel := context.WithCancel(ctx)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
resizeTty(subCtx, resize)
|
||||||
|
|
||||||
|
oldTermState, err := term.SaveState(os.Stdin.Fd())
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "unable to save terminal state")
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.SetFormatter(&RawTtyFormatter{})
|
||||||
|
term.SetRawTerminal(os.Stdin.Fd())
|
||||||
|
|
||||||
|
defer restoreTerminal(oldTermState)
|
||||||
|
}
|
||||||
|
|
||||||
|
streams := new(libpod.AttachStreams)
|
||||||
|
streams.OutputStream = stdout
|
||||||
|
streams.ErrorStream = stderr
|
||||||
|
streams.InputStream = stdin
|
||||||
|
streams.AttachOutput = true
|
||||||
|
streams.AttachError = true
|
||||||
|
streams.AttachInput = true
|
||||||
|
|
||||||
|
if stdout == nil {
|
||||||
|
logrus.Debugf("Not attaching to stdout")
|
||||||
|
streams.AttachOutput = false
|
||||||
|
}
|
||||||
|
if stderr == nil {
|
||||||
|
logrus.Debugf("Not attaching to stderr")
|
||||||
|
streams.AttachError = false
|
||||||
|
}
|
||||||
|
if stdin == nil {
|
||||||
|
logrus.Debugf("Not attaching to stdin")
|
||||||
|
streams.AttachInput = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !startContainer {
|
||||||
|
if sigProxy {
|
||||||
|
ProxySignals(ctr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctr.Attach(streams, detachKeys, resize)
|
||||||
|
}
|
||||||
|
|
||||||
|
attachChan, err := ctr.StartAndAttach(ctx, streams, detachKeys, resize, recursive)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if sigProxy {
|
||||||
|
ProxySignals(ctr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if stdout == nil && stderr == nil {
|
||||||
|
fmt.Printf("%s\n", ctr.ID())
|
||||||
|
}
|
||||||
|
|
||||||
|
err = <-attachChan
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "error attaching to container %s", ctr.ID())
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getResize returns a TerminalSize command matching stdin's current
|
||||||
|
// size on success, and nil on errors.
|
||||||
|
func getResize() *remotecommand.TerminalSize {
|
||||||
|
winsize, err := term.GetWinsize(os.Stdin.Fd())
|
||||||
|
if err != nil {
|
||||||
|
logrus.Warnf("Could not get terminal size %v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &remotecommand.TerminalSize{
|
||||||
|
Width: winsize.Width,
|
||||||
|
Height: winsize.Height,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper for prepareAttach - set up a goroutine to generate terminal resize events
|
||||||
|
func resizeTty(ctx context.Context, resize chan remotecommand.TerminalSize) {
|
||||||
|
sigchan := make(chan os.Signal, 1)
|
||||||
|
gosignal.Notify(sigchan, signal.SIGWINCH)
|
||||||
|
go func() {
|
||||||
|
defer close(resize)
|
||||||
|
// Update the terminal size immediately without waiting
|
||||||
|
// for a SIGWINCH to get the correct initial size.
|
||||||
|
resizeEvent := getResize()
|
||||||
|
for {
|
||||||
|
if resizeEvent == nil {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case <-sigchan:
|
||||||
|
resizeEvent = getResize()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case <-sigchan:
|
||||||
|
resizeEvent = getResize()
|
||||||
|
case resize <- *resizeEvent:
|
||||||
|
resizeEvent = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func restoreTerminal(state *term.State) error {
|
||||||
|
logrus.SetFormatter(&logrus.TextFormatter{})
|
||||||
|
return term.RestoreTerminal(os.Stdin.Fd(), state)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format ...
|
||||||
|
func (f *RawTtyFormatter) Format(entry *logrus.Entry) ([]byte, error) {
|
||||||
|
textFormatter := logrus.TextFormatter{}
|
||||||
|
bytes, err := textFormatter.Format(entry)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
bytes = append(bytes, '\r')
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes, err
|
||||||
|
}
|
@ -1,3 +1,5 @@
|
|||||||
|
// +build varlink
|
||||||
|
|
||||||
package varlinkapi
|
package varlinkapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// +build varlink
|
||||||
|
|
||||||
package varlinkapi
|
package varlinkapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -583,27 +585,6 @@ func (i *LibpodAPI) GetContainerStatsWithHistory(call iopodman.VarlinkCall, prev
|
|||||||
return call.ReplyGetContainerStatsWithHistory(cStats)
|
return call.ReplyGetContainerStatsWithHistory(cStats)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainerStatsToLibpodContainerStats converts the varlink containerstats to a libpod
|
|
||||||
// container stats
|
|
||||||
func ContainerStatsToLibpodContainerStats(stats iopodman.ContainerStats) libpod.ContainerStats {
|
|
||||||
cstats := libpod.ContainerStats{
|
|
||||||
ContainerID: stats.Id,
|
|
||||||
Name: stats.Name,
|
|
||||||
CPU: stats.Cpu,
|
|
||||||
CPUNano: uint64(stats.Cpu_nano),
|
|
||||||
SystemNano: uint64(stats.System_nano),
|
|
||||||
MemUsage: uint64(stats.Mem_usage),
|
|
||||||
MemLimit: uint64(stats.Mem_limit),
|
|
||||||
MemPerc: stats.Mem_perc,
|
|
||||||
NetInput: uint64(stats.Net_input),
|
|
||||||
NetOutput: uint64(stats.Net_output),
|
|
||||||
BlockInput: uint64(stats.Block_input),
|
|
||||||
BlockOutput: uint64(stats.Block_output),
|
|
||||||
PIDs: uint64(stats.Pids),
|
|
||||||
}
|
|
||||||
return cstats
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetContainersLogs is the varlink endpoint to obtain one or more container logs
|
// GetContainersLogs is the varlink endpoint to obtain one or more container logs
|
||||||
func (i *LibpodAPI) GetContainersLogs(call iopodman.VarlinkCall, names []string, follow, latest bool, since string, tail int64, timestamps bool) error {
|
func (i *LibpodAPI) GetContainersLogs(call iopodman.VarlinkCall, names []string, follow, latest bool, since string, tail int64, timestamps bool) error {
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
@ -1,220 +1,18 @@
|
|||||||
|
// +build varlink
|
||||||
|
|
||||||
package varlinkapi
|
package varlinkapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"github.com/containers/libpod/cmd/podman/shared"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/containers/libpod/cmd/podman/varlink"
|
"github.com/containers/libpod/cmd/podman/varlink"
|
||||||
"github.com/containers/libpod/libpod"
|
|
||||||
"github.com/containers/libpod/libpod/image"
|
|
||||||
"github.com/containers/libpod/pkg/inspect"
|
|
||||||
"github.com/containers/libpod/pkg/namespaces"
|
|
||||||
"github.com/containers/libpod/pkg/rootless"
|
|
||||||
cc "github.com/containers/libpod/pkg/spec"
|
|
||||||
"github.com/containers/libpod/pkg/util"
|
|
||||||
"github.com/docker/docker/pkg/signal"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateContainer ...
|
// CreateContainer ...
|
||||||
func (i *LibpodAPI) CreateContainer(call iopodman.VarlinkCall, config iopodman.Create) error {
|
func (i *LibpodAPI) CreateContainer(call iopodman.VarlinkCall, config iopodman.Create) error {
|
||||||
rtc, err := i.Runtime.GetConfig()
|
generic := shared.VarlinkCreateToGeneric(config)
|
||||||
|
ctr, _, err := shared.CreateContainer(getContext(), &generic, i.Runtime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return call.ReplyErrorOccurred(err.Error())
|
return call.ReplyErrorOccurred(err.Error())
|
||||||
}
|
}
|
||||||
ctx := getContext()
|
|
||||||
|
|
||||||
newImage, err := i.Runtime.ImageRuntime().New(ctx, config.Image, rtc.SignaturePolicyPath, "", os.Stderr, nil, image.SigningOptions{}, false, nil)
|
|
||||||
if err != nil {
|
|
||||||
return call.ReplyErrorOccurred(err.Error())
|
|
||||||
}
|
|
||||||
data, err := newImage.Inspect(ctx)
|
|
||||||
|
|
||||||
createConfig, err := varlinkCreateToCreateConfig(ctx, config, i.Runtime, config.Image, data)
|
|
||||||
if err != nil {
|
|
||||||
return call.ReplyErrorOccurred(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
runtimeSpec, err := cc.CreateConfigToOCISpec(createConfig)
|
|
||||||
if err != nil {
|
|
||||||
return call.ReplyErrorOccurred(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO fix when doing remote client and dealing with the ability to create a container
|
|
||||||
// within a non-existing pod (i.e. --pod new:foobar)
|
|
||||||
options, err := createConfig.GetContainerCreateOptions(i.Runtime, nil)
|
|
||||||
if err != nil {
|
|
||||||
return call.ReplyErrorOccurred(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
ctr, err := i.Runtime.NewContainer(ctx, runtimeSpec, options...)
|
|
||||||
if err != nil {
|
|
||||||
return call.ReplyErrorOccurred(err.Error())
|
|
||||||
}
|
|
||||||
createConfigJSON, err := json.Marshal(createConfig)
|
|
||||||
if err != nil {
|
|
||||||
return call.ReplyErrorOccurred(err.Error())
|
|
||||||
}
|
|
||||||
if err := ctr.AddArtifact("create-config", createConfigJSON); err != nil {
|
|
||||||
return call.ReplyErrorOccurred(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
logrus.Debug("new container created ", ctr.ID())
|
|
||||||
|
|
||||||
return call.ReplyCreateContainer(ctr.ID())
|
return call.ReplyCreateContainer(ctr.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
// varlinkCreateToCreateConfig takes the varlink input struct and maps it to a pointer
|
|
||||||
// of a CreateConfig, which eventually can be used to create the OCI spec.
|
|
||||||
func varlinkCreateToCreateConfig(ctx context.Context, create iopodman.Create, runtime *libpod.Runtime, imageName string, data *inspect.ImageData) (*cc.CreateConfig, error) {
|
|
||||||
idmappings, err := util.ParseIDMapping(create.Uidmap, create.Gidmap, create.Subuidname, create.Subgidname)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
inputCommand := create.Command
|
|
||||||
entrypoint := create.Entrypoint
|
|
||||||
|
|
||||||
// ENTRYPOINT
|
|
||||||
// User input entrypoint takes priority over image entrypoint
|
|
||||||
if len(entrypoint) == 0 {
|
|
||||||
entrypoint = data.Config.Entrypoint
|
|
||||||
}
|
|
||||||
// if entrypoint=, we need to clear the entrypoint
|
|
||||||
if len(entrypoint) == 1 && strings.Join(create.Entrypoint, "") == "" {
|
|
||||||
entrypoint = []string{}
|
|
||||||
}
|
|
||||||
// Build the command
|
|
||||||
// If we have an entry point, it goes first
|
|
||||||
command := entrypoint
|
|
||||||
if len(inputCommand) > 0 {
|
|
||||||
// User command overrides data CMD
|
|
||||||
command = append(command, inputCommand...)
|
|
||||||
} else if len(data.Config.Cmd) > 0 && len(command) == 0 {
|
|
||||||
// If not user command, add CMD
|
|
||||||
command = append(command, data.Config.Cmd...)
|
|
||||||
}
|
|
||||||
|
|
||||||
stopSignal := syscall.SIGTERM
|
|
||||||
if create.Stop_signal > 0 {
|
|
||||||
stopSignal, err = signal.ParseSignal(fmt.Sprintf("%d", create.Stop_signal))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
user := create.User
|
|
||||||
if user == "" {
|
|
||||||
user = data.Config.User
|
|
||||||
}
|
|
||||||
|
|
||||||
// EXPOSED PORTS
|
|
||||||
portBindings, err := cc.ExposedPorts(create.Exposed_ports, create.Publish, create.Publish_all, data.Config.ExposedPorts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// NETWORK MODE
|
|
||||||
networkMode := create.Net_mode
|
|
||||||
if networkMode == "" {
|
|
||||||
if rootless.IsRootless() {
|
|
||||||
networkMode = "slirp4netns"
|
|
||||||
} else {
|
|
||||||
networkMode = "bridge"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WORKING DIR
|
|
||||||
workDir := create.Work_dir
|
|
||||||
if workDir == "" {
|
|
||||||
workDir = "/"
|
|
||||||
}
|
|
||||||
|
|
||||||
imageID := data.ID
|
|
||||||
var ImageVolumes map[string]struct{}
|
|
||||||
if data != nil && create.Image_volume_type != "ignore" {
|
|
||||||
ImageVolumes = data.Config.Volumes
|
|
||||||
}
|
|
||||||
|
|
||||||
config := &cc.CreateConfig{
|
|
||||||
Runtime: runtime,
|
|
||||||
BuiltinImgVolumes: ImageVolumes,
|
|
||||||
ConmonPidFile: create.Conmon_pidfile,
|
|
||||||
ImageVolumeType: create.Image_volume_type,
|
|
||||||
CapAdd: create.Cap_add,
|
|
||||||
CapDrop: create.Cap_drop,
|
|
||||||
CgroupParent: create.Cgroup_parent,
|
|
||||||
Command: command,
|
|
||||||
Detach: create.Detach,
|
|
||||||
Devices: create.Devices,
|
|
||||||
DNSOpt: create.Dns_opt,
|
|
||||||
DNSSearch: create.Dns_search,
|
|
||||||
DNSServers: create.Dns_servers,
|
|
||||||
Entrypoint: create.Entrypoint,
|
|
||||||
Env: create.Env,
|
|
||||||
GroupAdd: create.Group_add,
|
|
||||||
Hostname: create.Hostname,
|
|
||||||
HostAdd: create.Host_add,
|
|
||||||
IDMappings: idmappings,
|
|
||||||
Image: imageName,
|
|
||||||
ImageID: imageID,
|
|
||||||
Interactive: create.Interactive,
|
|
||||||
Labels: create.Labels,
|
|
||||||
LogDriver: create.Log_driver,
|
|
||||||
LogDriverOpt: create.Log_driver_opt,
|
|
||||||
Name: create.Name,
|
|
||||||
Network: networkMode,
|
|
||||||
IpcMode: namespaces.IpcMode(create.Ipc_mode),
|
|
||||||
NetMode: namespaces.NetworkMode(networkMode),
|
|
||||||
UtsMode: namespaces.UTSMode(create.Uts_mode),
|
|
||||||
PidMode: namespaces.PidMode(create.Pid_mode),
|
|
||||||
Pod: create.Pod,
|
|
||||||
Privileged: create.Privileged,
|
|
||||||
Publish: create.Publish,
|
|
||||||
PublishAll: create.Publish_all,
|
|
||||||
PortBindings: portBindings,
|
|
||||||
Quiet: create.Quiet,
|
|
||||||
ReadOnlyRootfs: create.Readonly_rootfs,
|
|
||||||
Resources: cc.CreateResourceConfig{
|
|
||||||
BlkioWeight: uint16(create.Resources.Blkio_weight),
|
|
||||||
BlkioWeightDevice: create.Resources.Blkio_weight_device,
|
|
||||||
CPUShares: uint64(create.Resources.Cpu_shares),
|
|
||||||
CPUPeriod: uint64(create.Resources.Cpu_period),
|
|
||||||
CPUsetCPUs: create.Resources.Cpuset_cpus,
|
|
||||||
CPUsetMems: create.Resources.Cpuset_mems,
|
|
||||||
CPUQuota: create.Resources.Cpu_quota,
|
|
||||||
CPURtPeriod: uint64(create.Resources.Cpu_rt_period),
|
|
||||||
CPURtRuntime: create.Resources.Cpu_rt_runtime,
|
|
||||||
CPUs: create.Resources.Cpus,
|
|
||||||
DeviceReadBps: create.Resources.Device_read_bps,
|
|
||||||
DeviceReadIOps: create.Resources.Device_write_bps,
|
|
||||||
DeviceWriteBps: create.Resources.Device_read_iops,
|
|
||||||
DeviceWriteIOps: create.Resources.Device_write_iops,
|
|
||||||
DisableOomKiller: create.Resources.Disable_oomkiller,
|
|
||||||
ShmSize: create.Resources.Shm_size,
|
|
||||||
Memory: create.Resources.Memory,
|
|
||||||
MemoryReservation: create.Resources.Memory_reservation,
|
|
||||||
MemorySwap: create.Resources.Memory_swap,
|
|
||||||
MemorySwappiness: int(create.Resources.Memory_swappiness),
|
|
||||||
KernelMemory: create.Resources.Kernel_memory,
|
|
||||||
OomScoreAdj: int(create.Resources.Oom_score_adj),
|
|
||||||
PidsLimit: create.Resources.Pids_limit,
|
|
||||||
Ulimit: create.Resources.Ulimit,
|
|
||||||
},
|
|
||||||
Rm: create.Rm,
|
|
||||||
StopSignal: stopSignal,
|
|
||||||
StopTimeout: uint(create.Stop_timeout),
|
|
||||||
Sysctl: create.Sys_ctl,
|
|
||||||
Tmpfs: create.Tmpfs,
|
|
||||||
Tty: create.Tty,
|
|
||||||
User: user,
|
|
||||||
UsernsMode: namespaces.UsernsMode(create.Userns_mode),
|
|
||||||
Volumes: create.Volumes,
|
|
||||||
WorkDir: workDir,
|
|
||||||
}
|
|
||||||
|
|
||||||
return config, nil
|
|
||||||
}
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// +build varlink
|
||||||
|
|
||||||
package varlinkapi
|
package varlinkapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// +build varlink
|
||||||
|
|
||||||
package varlinkapi
|
package varlinkapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// +build varlink
|
||||||
|
|
||||||
package varlinkapi
|
package varlinkapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// +build varlink
|
||||||
|
|
||||||
package varlinkapi
|
package varlinkapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
29
pkg/varlinkapi/remote_client.go
Normal file
29
pkg/varlinkapi/remote_client.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// +build varlink remoteclient
|
||||||
|
|
||||||
|
package varlinkapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/containers/libpod/cmd/podman/varlink"
|
||||||
|
"github.com/containers/libpod/libpod"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ContainerStatsToLibpodContainerStats converts the varlink containerstats to a libpod
|
||||||
|
// container stats
|
||||||
|
func ContainerStatsToLibpodContainerStats(stats iopodman.ContainerStats) libpod.ContainerStats {
|
||||||
|
cstats := libpod.ContainerStats{
|
||||||
|
ContainerID: stats.Id,
|
||||||
|
Name: stats.Name,
|
||||||
|
CPU: stats.Cpu,
|
||||||
|
CPUNano: uint64(stats.Cpu_nano),
|
||||||
|
SystemNano: uint64(stats.System_nano),
|
||||||
|
MemUsage: uint64(stats.Mem_usage),
|
||||||
|
MemLimit: uint64(stats.Mem_limit),
|
||||||
|
MemPerc: stats.Mem_perc,
|
||||||
|
NetInput: uint64(stats.Net_input),
|
||||||
|
NetOutput: uint64(stats.Net_output),
|
||||||
|
BlockInput: uint64(stats.Block_input),
|
||||||
|
BlockOutput: uint64(stats.Block_output),
|
||||||
|
PIDs: uint64(stats.Pids),
|
||||||
|
}
|
||||||
|
return cstats
|
||||||
|
}
|
@ -1,3 +1,5 @@
|
|||||||
|
// +build varlink
|
||||||
|
|
||||||
package varlinkapi
|
package varlinkapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// +build varlink
|
||||||
|
|
||||||
package varlinkapi
|
package varlinkapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// +build varlink
|
||||||
|
|
||||||
package varlinkapi
|
package varlinkapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// +build varlink
|
||||||
|
|
||||||
package varlinkapi
|
package varlinkapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
Reference in New Issue
Block a user