summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/common/specgen.go4
-rw-r--r--cmd/podman/containers/cp.go26
-rw-r--r--cmd/podman/containers/init.go33
-rw-r--r--cmd/podman/containers/mount.go3
-rw-r--r--cmd/podman/images/search.go3
-rw-r--r--cmd/podman/system/unshare.go50
-rw-r--r--cmd/podman/system/version.go70
-rw-r--r--libpod/container_inspect.go34
-rw-r--r--libpod/define/container_inspect.go7
-rw-r--r--libpod/define/version.go2
-rw-r--r--libpod/options.go16
-rw-r--r--libpod/pod.go15
-rw-r--r--libpod/pod_api.go20
-rw-r--r--pkg/api/handlers/compat/version.go3
-rw-r--r--pkg/api/handlers/types.go4
-rw-r--r--pkg/api/server/register_version.go21
-rw-r--r--pkg/api/server/swagger.go9
-rw-r--r--pkg/bindings/system/system.go38
-rw-r--r--pkg/domain/entities/engine_container.go2
-rw-r--r--pkg/domain/entities/system.go14
-rw-r--r--pkg/domain/infra/abi/system.go26
-rw-r--r--pkg/domain/infra/tunnel/system.go8
-rw-r--r--pkg/specgen/generate/oci.go18
23 files changed, 334 insertions, 92 deletions
diff --git a/cmd/podman/common/specgen.go b/cmd/podman/common/specgen.go
index ff7c39de2..664e66df8 100644
--- a/cmd/podman/common/specgen.go
+++ b/cmd/podman/common/specgen.go
@@ -519,6 +519,10 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
}
s.Sysctl = sysmap
+ if c.CIDFile != "" {
+ s.Annotations[define.InspectAnnotationCIDFile] = c.CIDFile
+ }
+
for _, opt := range c.SecurityOpt {
if opt == "no-new-privileges" {
s.ContainerSecurityConfig.NoNewPrivileges = true
diff --git a/cmd/podman/containers/cp.go b/cmd/podman/containers/cp.go
index f0f9a158d..ac7037621 100644
--- a/cmd/podman/containers/cp.go
+++ b/cmd/podman/containers/cp.go
@@ -7,6 +7,7 @@ import (
"github.com/containers/libpod/pkg/rootless"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
+ "github.com/spf13/pflag"
)
var (
@@ -22,20 +23,41 @@ var (
RunE: cp,
Example: "podman cp [CONTAINER:]SRC_PATH [CONTAINER:]DEST_PATH",
}
+
+ containerCpCommand = &cobra.Command{
+ Use: cpCommand.Use,
+ Short: cpCommand.Short,
+ Long: cpCommand.Long,
+ Args: cpCommand.Args,
+ RunE: cpCommand.RunE,
+ Example: "podman container cp [CONTAINER:]SRC_PATH [CONTAINER:]DEST_PATH",
+ }
)
var (
cpOpts entities.ContainerCpOptions
)
+func cpFlags(flags *pflag.FlagSet) {
+ flags.BoolVar(&cpOpts.Extract, "extract", false, "Extract the tar file into the destination directory.")
+ flags.BoolVar(&cpOpts.Pause, "pause", copyPause(), "Pause the container while copying")
+}
+
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode},
Command: cpCommand,
})
flags := cpCommand.Flags()
- flags.BoolVar(&cpOpts.Extract, "extract", false, "Extract the tar file into the destination directory.")
- flags.BoolVar(&cpOpts.Pause, "pause", copyPause(), "Pause the container while copying")
+ cpFlags(flags)
+
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Command: containerCpCommand,
+ Parent: containerCmd,
+ })
+ containerCpFlags := containerCpCommand.Flags()
+ cpFlags(containerCpFlags)
}
func cp(cmd *cobra.Command, args []string) error {
diff --git a/cmd/podman/containers/init.go b/cmd/podman/containers/init.go
index bb02f22fd..417f170c3 100644
--- a/cmd/podman/containers/init.go
+++ b/cmd/podman/containers/init.go
@@ -8,6 +8,7 @@ import (
"github.com/containers/libpod/cmd/podman/utils"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/spf13/cobra"
+ "github.com/spf13/pflag"
)
var (
@@ -25,21 +26,47 @@ var (
podman init 3c45ef19d893
podman init test1`,
}
+
+ containerInitCommand = &cobra.Command{
+ Use: initCommand.Use,
+ Short: initCommand.Short,
+ Long: initCommand.Long,
+ RunE: initCommand.RunE,
+ Args: initCommand.Args,
+ Example: `podman container init --latest
+ podman container init 3c45ef19d893
+ podman container init test1`,
+ }
)
var (
initOptions entities.ContainerInitOptions
)
+func initFlags(flags *pflag.FlagSet) {
+ flags.BoolVarP(&initOptions.All, "all", "a", false, "Initialize all containers")
+ flags.BoolVarP(&initOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
+ if registry.IsRemote() {
+ _ = flags.MarkHidden("latest")
+ }
+}
+
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: initCommand,
})
flags := initCommand.Flags()
- flags.BoolVarP(&initOptions.All, "all", "a", false, "Initialize all containers")
- flags.BoolVarP(&initOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
- _ = flags.MarkHidden("latest")
+ initFlags(flags)
+
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Parent: containerCmd,
+ Command: containerInitCommand,
+ })
+
+ containerInitFlags := containerInitCommand.Flags()
+ initFlags(containerInitFlags)
}
func initContainer(cmd *cobra.Command, args []string) error {
diff --git a/cmd/podman/containers/mount.go b/cmd/podman/containers/mount.go
index 0bdac72cb..af4d52caa 100644
--- a/cmd/podman/containers/mount.go
+++ b/cmd/podman/containers/mount.go
@@ -30,9 +30,6 @@ var (
Args: func(cmd *cobra.Command, args []string) error {
return parse.CheckAllLatestAndCIDFile(cmd, args, true, false)
},
- Annotations: map[string]string{
- registry.ParentNSRequired: "",
- },
}
containerMountCommmand = &cobra.Command{
diff --git a/cmd/podman/images/search.go b/cmd/podman/images/search.go
index 640d497c3..ccac7e3fe 100644
--- a/cmd/podman/images/search.go
+++ b/cmd/podman/images/search.go
@@ -38,9 +38,6 @@ var (
Long: searchDescription,
RunE: imageSearch,
Args: cobra.ExactArgs(1),
- Annotations: map[string]string{
- registry.ParentNSRequired: "",
- },
Example: `podman search --filter=is-official --limit 3 alpine
podman search registry.fedoraproject.org/ # only works with v2 registries
podman search --format "table {{.Index}} {{.Name}}" registry.fedoraproject.org/fedora`,
diff --git a/cmd/podman/system/unshare.go b/cmd/podman/system/unshare.go
new file mode 100644
index 000000000..7db5d36d2
--- /dev/null
+++ b/cmd/podman/system/unshare.go
@@ -0,0 +1,50 @@
+package system
+
+import (
+ "os"
+
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/libpod/pkg/rootless"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ unshareDescription = "Runs a command in a modified user namespace."
+ unshareCommand = &cobra.Command{
+ Use: "unshare [flags] [COMMAND [ARG]]",
+ Short: "Run a command in a modified user namespace",
+ Long: unshareDescription,
+ RunE: unshare,
+ Example: `podman unshare id
+ podman unshare cat /proc/self/uid_map,
+ podman unshare podman-script.sh`,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Command: unshareCommand,
+ })
+ flags := unshareCommand.Flags()
+ flags.SetInterspersed(false)
+}
+
+func unshare(cmd *cobra.Command, args []string) error {
+ if isRootless := rootless.IsRootless(); !isRootless {
+ return errors.Errorf("please use unshare with rootless")
+ }
+ // exec the specified command, if there is one
+ if len(args) < 1 {
+ // try to exec the shell, if one's set
+ shell, shellSet := os.LookupEnv("SHELL")
+ if !shellSet {
+ return errors.Errorf("no command specified and no $SHELL specified")
+ }
+ args = []string{shell}
+ }
+
+ return registry.ContainerEngine().Unshare(registry.Context(), args)
+}
diff --git a/cmd/podman/system/version.go b/cmd/podman/system/version.go
index 065eef309..50bd81368 100644
--- a/cmd/podman/system/version.go
+++ b/cmd/podman/system/version.go
@@ -8,12 +8,10 @@ import (
"text/tabwriter"
"time"
- "github.com/containers/buildah/pkg/formats"
"github.com/containers/libpod/cmd/podman/registry"
"github.com/containers/libpod/cmd/podman/validate"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/domain/entities"
- "github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -23,18 +21,10 @@ var (
Args: validate.NoArgs,
Short: "Display the Podman Version Information",
RunE: version,
- Annotations: map[string]string{
- registry.ParentNSRequired: "",
- },
}
versionFormat string
)
-type versionStruct struct {
- Client define.Version
- Server define.Version
-}
-
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
@@ -45,68 +35,44 @@ func init() {
}
func version(cmd *cobra.Command, args []string) error {
- var (
- v versionStruct
- err error
- )
- v.Client, err = define.GetVersion()
+ versions, err := registry.ContainerEngine().Version(registry.Context())
if err != nil {
- return errors.Wrapf(err, "unable to determine version")
+ return err
}
- // TODO we need to discuss how to implement
- // this more. current endpoints dont have a
- // version endpoint. maybe we use info?
- // if remote {
- // v.Server, err = getRemoteVersion(c)
- // if err != nil {
- // return err
- // }
- // } else {
- v.Server = v.Client
- // }
- versionOutputFormat := versionFormat
- if versionOutputFormat != "" {
- if strings.Join(strings.Fields(versionOutputFormat), "") == "{{json.}}" {
- versionOutputFormat = formats.JSONString
+ switch {
+ case versionFormat == "json", versionFormat == "{{ json .}}":
+ s, err := json.MarshalToString(versions)
+ if err != nil {
+ return err
}
- var out formats.Writer
- switch versionOutputFormat {
- case formats.JSONString:
- out = formats.JSONStruct{Output: v}
- return out.Out()
- default:
- out = formats.StdoutTemplate{Output: v, Template: versionOutputFormat}
- err := out.Out()
- if err != nil {
- // On Failure, assume user is using older version of podman version --format and check client
- out = formats.StdoutTemplate{Output: v.Client, Template: versionOutputFormat}
- if err1 := out.Out(); err1 != nil {
- return err
- }
- }
+ _, err = io.WriteString(os.Stdout, s)
+ return err
+ case cmd.Flag("format").Changed:
+ if !strings.HasSuffix(versionFormat, "\n") {
+ versionFormat += "\n"
}
- return nil
}
+
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
defer w.Flush()
- if registry.IsRemote() {
+ if versions.Server != nil {
if _, err := fmt.Fprintf(w, "Client:\n"); err != nil {
return err
}
- formatVersion(w, v.Client)
+ formatVersion(w, versions.Client)
if _, err := fmt.Fprintf(w, "\nServer:\n"); err != nil {
return err
}
- formatVersion(w, v.Server)
+ formatVersion(w, versions.Server)
} else {
- formatVersion(w, v.Client)
+ formatVersion(w, versions.Client)
}
return nil
}
-func formatVersion(writer io.Writer, version define.Version) {
+func formatVersion(writer io.Writer, version *define.Version) {
fmt.Fprintf(writer, "Version:\t%s\n", version.Version)
fmt.Fprintf(writer, "RemoteAPI Version:\t%d\n", version.RemoteAPIVersion)
fmt.Fprintf(writer, "Go Version:\t%s\n", version.GoVersion)
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go
index ae28dde94..b26dcddf6 100644
--- a/libpod/container_inspect.go
+++ b/libpod/container_inspect.go
@@ -580,7 +580,10 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named
networkMode := ""
switch {
case c.config.CreateNetNS:
- networkMode = "default"
+ // We actually store the network
+ // mode for Slirp and Bridge, so
+ // we can just use that
+ networkMode = string(c.config.NetMode)
case c.config.NetNsCtr != "":
networkMode = fmt.Sprintf("container:%s", c.config.NetNsCtr)
default:
@@ -594,7 +597,10 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named
if ns.Path != "" {
networkMode = fmt.Sprintf("ns:%s", ns.Path)
} else {
- networkMode = "private"
+ // We're making a network ns, but not
+ // configuring with Slirp or CNI. That
+ // means it's --net=none
+ networkMode = "none"
}
break
}
@@ -698,6 +704,30 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named
}
hostConfig.IpcMode = ipcMode
+ // Cgroup namespace mode
+ cgroupMode := ""
+ if c.config.CgroupNsCtr != "" {
+ cgroupMode = fmt.Sprintf("container:%s", c.config.CgroupNsCtr)
+ } else if ctrSpec.Linux != nil {
+ // Locate the spec's cgroup namespace
+ // If there is none, it's cgroup=host.
+ // If there is one and it has a path, it's "ns:".
+ // If there is no path, it's private.
+ for _, ns := range ctrSpec.Linux.Namespaces {
+ if ns.Type == spec.CgroupNamespace {
+ if ns.Path != "" {
+ cgroupMode = fmt.Sprintf("ns:%s", ns.Path)
+ } else {
+ cgroupMode = "private"
+ }
+ }
+ }
+ if cgroupMode == "" {
+ cgroupMode = "host"
+ }
+ }
+ hostConfig.CgroupMode = cgroupMode
+
// CGroup parent
// Need to check if it's the default, and not print if so.
defaultCgroupParent := ""
diff --git a/libpod/define/container_inspect.go b/libpod/define/container_inspect.go
index e6a19e5b4..27ada8706 100644
--- a/libpod/define/container_inspect.go
+++ b/libpod/define/container_inspect.go
@@ -228,6 +228,13 @@ type InspectContainerHostConfig struct {
// include a Mounts field in inspect.
// Format: <src>:<destination>[:<comma-separated options>]
Binds []string `json:"Binds"`
+ // CgroupMode is the configuration of the container's cgroup namespace.
+ // Populated as follows:
+ // private - a cgroup namespace has been created
+ // host - No cgroup namespace created
+ // container:<id> - Using another container's cgroup namespace
+ // ns:<path> - A path to a cgroup namespace has been specified
+ CgroupMode string `json:"CgroupMode"`
// ContainerIDFile is a file created during container creation to hold
// the ID of the created container.
// This is not handled within libpod and is stored in an annotation.
diff --git a/libpod/define/version.go b/libpod/define/version.go
index 0f9f49050..954cd00f1 100644
--- a/libpod/define/version.go
+++ b/libpod/define/version.go
@@ -17,7 +17,7 @@ var (
buildInfo string
)
-//Version is an output struct for varlink
+// Version is an output struct for varlink
type Version struct {
RemoteAPIVersion int64
Version string
diff --git a/libpod/options.go b/libpod/options.go
index 33b423bce..05241baf3 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -1692,6 +1692,22 @@ func WithPodUTS() PodCreateOption {
}
}
+// WithPodCgroup tells containers in this pod to use the cgroup namespace
+// created for this pod.
+// Containers in a pod will inherit the kernel namespaces from the first
+// container added.
+func WithPodCgroup() PodCreateOption {
+ return func(pod *Pod) error {
+ if pod.valid {
+ return define.ErrPodFinalized
+ }
+
+ pod.config.UsePodCgroupNS = true
+
+ return nil
+ }
+}
+
// WithInfraContainer tells the pod to create a pause container
func WithInfraContainer() PodCreateOption {
return func(pod *Pod) error {
diff --git a/libpod/pod.go b/libpod/pod.go
index 8eb06ae2f..34ceef5ef 100644
--- a/libpod/pod.go
+++ b/libpod/pod.go
@@ -51,12 +51,13 @@ type PodConfig struct {
// The following UsePod{kernelNamespace} indicate whether the containers
// in the pod will inherit the namespace from the first container in the pod.
- UsePodPID bool `json:"sharesPid,omitempty"`
- UsePodIPC bool `json:"sharesIpc,omitempty"`
- UsePodNet bool `json:"sharesNet,omitempty"`
- UsePodMount bool `json:"sharesMnt,omitempty"`
- UsePodUser bool `json:"sharesUser,omitempty"`
- UsePodUTS bool `json:"sharesUts,omitempty"`
+ UsePodPID bool `json:"sharesPid,omitempty"`
+ UsePodIPC bool `json:"sharesIpc,omitempty"`
+ UsePodNet bool `json:"sharesNet,omitempty"`
+ UsePodMount bool `json:"sharesMnt,omitempty"`
+ UsePodUser bool `json:"sharesUser,omitempty"`
+ UsePodUTS bool `json:"sharesUts,omitempty"`
+ UsePodCgroupNS bool `json:"sharesCgroupNS,omitempty"`
InfraContainer *InfraContainerConfig `json:"infraConfig"`
@@ -167,7 +168,7 @@ func (p *Pod) SharesUTS() bool {
// SharesCgroup returns whether containers in the pod will default to this pod's
// cgroup instead of the default libpod parent
func (p *Pod) SharesCgroup() bool {
- return p.config.UsePodCgroup
+ return p.config.UsePodCgroupNS
}
// CgroupPath returns the path to the pod's CGroup
diff --git a/libpod/pod_api.go b/libpod/pod_api.go
index 45aa5cb8d..0be9f2573 100644
--- a/libpod/pod_api.go
+++ b/libpod/pod_api.go
@@ -466,6 +466,24 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) {
if err != nil {
return nil, err
}
+
+ namespaces := map[string]bool{
+ "pid": p.config.UsePodPID,
+ "ipc": p.config.UsePodIPC,
+ "net": p.config.UsePodNet,
+ "mount": p.config.UsePodMount,
+ "user": p.config.UsePodUser,
+ "uts": p.config.UsePodUTS,
+ "cgroup": p.config.UsePodCgroupNS,
+ }
+
+ sharesNS := []string{}
+ for nsStr, include := range namespaces {
+ if include {
+ sharesNS = append(sharesNS, nsStr)
+ }
+ }
+
inspectData := define.InspectPodData{
ID: p.ID(),
Name: p.Name(),
@@ -480,7 +498,7 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) {
CreateInfra: false,
InfraContainerID: p.state.InfraContainerID,
InfraConfig: nil,
- SharedNamespaces: nil,
+ SharedNamespaces: sharesNS,
NumContainers: uint(len(containers)),
Containers: ctrs,
}
diff --git a/pkg/api/handlers/compat/version.go b/pkg/api/handlers/compat/version.go
index 35a95b562..8786f1d5b 100644
--- a/pkg/api/handlers/compat/version.go
+++ b/pkg/api/handlers/compat/version.go
@@ -10,6 +10,7 @@ import (
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/api/handlers"
"github.com/containers/libpod/pkg/api/handlers/utils"
+ "github.com/containers/libpod/pkg/domain/entities"
docker "github.com/docker/docker/api/types"
"github.com/pkg/errors"
)
@@ -46,7 +47,7 @@ func VersionHandler(w http.ResponseWriter, r *http.Request) {
},
}}
- utils.WriteResponse(w, http.StatusOK, handlers.Version{Version: docker.Version{
+ utils.WriteResponse(w, http.StatusOK, entities.ComponentVersion{Version: docker.Version{
Platform: struct {
Name string
}{
diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go
index a7abf59c0..2075d29df 100644
--- a/pkg/api/handlers/types.go
+++ b/pkg/api/handlers/types.go
@@ -71,10 +71,6 @@ type Container struct {
docker.ContainerCreateConfig
}
-type Version struct {
- docker.Version
-}
-
type DiskUsage struct {
docker.DiskUsage
}
diff --git a/pkg/api/server/register_version.go b/pkg/api/server/register_version.go
index 25cacbc61..30289ffe3 100644
--- a/pkg/api/server/register_version.go
+++ b/pkg/api/server/register_version.go
@@ -8,7 +8,28 @@ import (
)
func (s *APIServer) registerVersionHandlers(r *mux.Router) error {
+ // swagger:operation GET /version compat CompatSystemVersion
+ // ---
+ // summary: Component Version information
+ // tags:
+ // - system (compat)
+ // produces:
+ // - application/json
+ // responses:
+ // 200:
+ // $ref: "#/responses/Version"
r.Handle("/version", s.APIHandler(compat.VersionHandler)).Methods(http.MethodGet)
r.Handle(VersionedPath("/version"), s.APIHandler(compat.VersionHandler)).Methods(http.MethodGet)
+ // swagger:operation GET /libpod/version libpod SystemVersion
+ // ---
+ // summary: Component Version information
+ // tags:
+ // - system
+ // produces:
+ // - application/json
+ // responses:
+ // 200:
+ // $ref: "#/responses/Version"
+ r.Handle(VersionedPath("/libpod/version"), s.APIHandler(compat.VersionHandler)).Methods(http.MethodGet)
return nil
}
diff --git a/pkg/api/server/swagger.go b/pkg/api/server/swagger.go
index 75dcc71a6..e47f2cc2f 100644
--- a/pkg/api/server/swagger.go
+++ b/pkg/api/server/swagger.go
@@ -181,3 +181,12 @@ type swagHealthCheckRunResponse struct {
define.HealthCheckResults
}
}
+
+// Version
+// swagger:response Version
+type swagVersion struct {
+ // in:body
+ Body struct {
+ entities.SystemVersionReport
+ }
+}
diff --git a/pkg/bindings/system/system.go b/pkg/bindings/system/system.go
index df6b529de..caef6af6f 100644
--- a/pkg/bindings/system/system.go
+++ b/pkg/bindings/system/system.go
@@ -3,11 +3,14 @@ package system
import (
"context"
"encoding/json"
+ "fmt"
"io"
"net/http"
"net/url"
"strconv"
+ "time"
+ "github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/bindings"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/pkg/errors"
@@ -83,3 +86,38 @@ func Prune(ctx context.Context, all, volumes *bool) (*entities.SystemPruneReport
}
return &report, response.Process(&report)
}
+
+func Version(ctx context.Context) (*entities.SystemVersionReport, error) {
+ var report entities.SystemVersionReport
+ var component entities.ComponentVersion
+
+ version, err := define.GetVersion()
+ if err != nil {
+ return nil, err
+ }
+ report.Client = &version
+
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return nil, err
+ }
+ response, err := conn.DoRequest(nil, http.MethodGet, "/version", nil)
+ if err != nil {
+ return nil, err
+ }
+
+ if err = response.Process(&component); err != nil {
+ return nil, err
+ }
+ f, _ := strconv.ParseFloat(component.APIVersion, 64)
+ b, _ := time.Parse(time.RFC3339, component.BuildTime)
+ report.Server = &define.Version{
+ RemoteAPIVersion: int64(f),
+ Version: component.Version.Version,
+ GoVersion: component.GoVersion,
+ GitCommit: component.GitCommit,
+ Built: b.Unix(),
+ OsArch: fmt.Sprintf("%s/%s", component.Os, component.Arch),
+ }
+ return &report, err
+}
diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go
index 7c93e6802..719ac3f9e 100644
--- a/pkg/domain/entities/engine_container.go
+++ b/pkg/domain/entities/engine_container.go
@@ -71,7 +71,9 @@ type ContainerEngine interface {
SetupRootless(ctx context.Context, cmd *cobra.Command) error
Shutdown(ctx context.Context)
SystemDf(ctx context.Context, options SystemDfOptions) (*SystemDfReport, error)
+ Unshare(ctx context.Context, args []string) error
VarlinkService(ctx context.Context, opts ServiceOptions) error
+ Version(ctx context.Context) (*SystemVersionReport, error)
VolumeCreate(ctx context.Context, opts VolumeCreateOptions) (*IdOrNameResponse, error)
VolumeInspect(ctx context.Context, namesOrIds []string, opts VolumeInspectOptions) ([]*VolumeInspectReport, error)
VolumeList(ctx context.Context, opts VolumeListOptions) ([]*VolumeListReport, error)
diff --git a/pkg/domain/entities/system.go b/pkg/domain/entities/system.go
index c62f40025..5e4760d12 100644
--- a/pkg/domain/entities/system.go
+++ b/pkg/domain/entities/system.go
@@ -3,6 +3,8 @@ package entities
import (
"time"
+ "github.com/containers/libpod/libpod/define"
+ "github.com/docker/docker/api/types"
"github.com/spf13/cobra"
)
@@ -83,3 +85,15 @@ type SystemDfVolumeReport struct {
type SystemResetOptions struct {
Force bool
}
+
+// SystemVersionReport describes version information about the running Podman service
+type SystemVersionReport struct {
+ // Always populated
+ Client *define.Version `json:",omitempty"`
+ // May be populated, when in tunnel mode
+ Server *define.Version `json:",omitempty"`
+}
+
+type ComponentVersion struct {
+ types.Version
+}
diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go
index 24c62465f..d701d65de 100644
--- a/pkg/domain/infra/abi/system.go
+++ b/pkg/domain/infra/abi/system.go
@@ -5,6 +5,7 @@ import (
"fmt"
"io/ioutil"
"os"
+ "os/exec"
"path/filepath"
"strconv"
"syscall"
@@ -391,3 +392,28 @@ func (s SystemEngine) Shutdown(ctx context.Context) {
logrus.Error(err)
}
}
+
+func unshareEnv(graphroot, runroot string) []string {
+ return append(os.Environ(), "_CONTAINERS_USERNS_CONFIGURED=done",
+ fmt.Sprintf("CONTAINERS_GRAPHROOT=%s", graphroot),
+ fmt.Sprintf("CONTAINERS_RUNROOT=%s", runroot))
+}
+
+func (ic *ContainerEngine) Unshare(ctx context.Context, args []string) error {
+ cmd := exec.Command(args[0], args[1:]...)
+ cmd.Env = unshareEnv(ic.Libpod.StorageConfig().GraphRoot, ic.Libpod.StorageConfig().RunRoot)
+ cmd.Stdin = os.Stdin
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ return cmd.Run()
+}
+
+func (ic ContainerEngine) Version(ctx context.Context) (*entities.SystemVersionReport, error) {
+ var report entities.SystemVersionReport
+ v, err := define.GetVersion()
+ if err != nil {
+ return nil, err
+ }
+ report.Client = &v
+ return &report, err
+}
diff --git a/pkg/domain/infra/tunnel/system.go b/pkg/domain/infra/tunnel/system.go
index 448fbed1f..dafada805 100644
--- a/pkg/domain/infra/tunnel/system.go
+++ b/pkg/domain/infra/tunnel/system.go
@@ -30,3 +30,11 @@ func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.Sys
func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.SystemDfOptions) (*entities.SystemDfReport, error) {
panic(errors.New("system df is not supported on remote clients"))
}
+
+func (ic *ContainerEngine) Unshare(ctx context.Context, args []string) error {
+ return errors.New("unshare is not supported on remote clients")
+}
+
+func (ic ContainerEngine) Version(ctx context.Context) (*entities.SystemVersionReport, error) {
+ return system.Version(ic.ClientCxt)
+}
diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go
index a2bb66a44..11b18e2d0 100644
--- a/pkg/specgen/generate/oci.go
+++ b/pkg/specgen/generate/oci.go
@@ -321,12 +321,6 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt
configSpec.Annotations = make(map[string]string)
}
- // TODO cidfile is not in specgen; when wiring up cli, we will need to move this out of here
- // leaving as a reminder
- //if config.CidFile != "" {
- // configSpec.Annotations[libpod.InspectAnnotationCIDFile] = config.CidFile
- //}
-
if s.Remove {
configSpec.Annotations[define.InspectAnnotationAutoremove] = define.InspectResponseTrue
} else {
@@ -343,13 +337,11 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt
configSpec.Annotations[define.InspectAnnotationPrivileged] = define.InspectResponseFalse
}
- // TODO Init might not make it into the specgen and therefore is not available here. We should deal
- // with this when we wire up the CLI; leaving as a reminder
- //if s.Init {
- // configSpec.Annotations[libpod.InspectAnnotationInit] = libpod.InspectResponseTrue
- //} else {
- // configSpec.Annotations[libpod.InspectAnnotationInit] = libpod.InspectResponseFalse
- //}
+ if s.Init {
+ configSpec.Annotations[define.InspectAnnotationInit] = define.InspectResponseTrue
+ } else {
+ configSpec.Annotations[define.InspectAnnotationInit] = define.InspectResponseFalse
+ }
return configSpec, nil
}