summaryrefslogtreecommitdiff
path: root/cmd/podman
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podman')
-rw-r--r--cmd/podman/common/specgen.go3
-rw-r--r--cmd/podman/common/types.go3
-rw-r--r--cmd/podman/containers/port.go38
-rw-r--r--cmd/podman/generate/generate.go2
-rw-r--r--cmd/podman/generate/kube.go68
-rw-r--r--cmd/podman/generate/systemd.go2
-rw-r--r--cmd/podman/images/trust.go27
-rw-r--r--cmd/podman/images/trust_set.go56
-rw-r--r--cmd/podman/images/trust_show.go77
-rw-r--r--cmd/podman/main.go1
-rw-r--r--cmd/podman/parse/common.go15
-rw-r--r--cmd/podman/play/kube.go101
-rw-r--r--cmd/podman/play/play.go26
-rw-r--r--cmd/podman/pods/create.go3
14 files changed, 407 insertions, 15 deletions
diff --git a/cmd/podman/common/specgen.go b/cmd/podman/common/specgen.go
index 3681804ea..3e9772576 100644
--- a/cmd/podman/common/specgen.go
+++ b/cmd/podman/common/specgen.go
@@ -534,10 +534,13 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
case "label":
// TODO selinux opts and label opts are the same thing
s.ContainerSecurityConfig.SelinuxOpts = append(s.ContainerSecurityConfig.SelinuxOpts, con[1])
+ s.Annotations[define.InspectAnnotationLabel] = con[1]
case "apparmor":
s.ContainerSecurityConfig.ApparmorProfile = con[1]
+ s.Annotations[define.InspectAnnotationApparmor] = con[1]
case "seccomp":
s.SeccompProfilePath = con[1]
+ s.Annotations[define.InspectAnnotationSeccomp] = con[1]
default:
return fmt.Errorf("invalid --security-opt 2: %q", opt)
}
diff --git a/cmd/podman/common/types.go b/cmd/podman/common/types.go
deleted file mode 100644
index 2427ae975..000000000
--- a/cmd/podman/common/types.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package common
-
-var DefaultKernelNamespaces = "cgroup,ipc,net,uts"
diff --git a/cmd/podman/containers/port.go b/cmd/podman/containers/port.go
index 2e3386aa9..ec0ddf838 100644
--- a/cmd/podman/containers/port.go
+++ b/cmd/podman/containers/port.go
@@ -11,6 +11,7 @@ import (
"github.com/cri-o/ocicni/pkg/ocicni"
"github.com/pkg/errors"
"github.com/spf13/cobra"
+ "github.com/spf13/pflag"
)
var (
@@ -28,23 +29,50 @@ var (
podman port ctrID 80/tcp
podman port --latest 80`,
}
+
+ containerPortCommand = &cobra.Command{
+ Use: "port [flags] CONTAINER [PORT]",
+ Short: portCommand.Short,
+ Long: portDescription,
+ RunE: portCommand.RunE,
+ Args: func(cmd *cobra.Command, args []string) error {
+ return parse.CheckAllLatestAndCIDFile(cmd, args, true, false)
+ },
+ Example: `podman container port --all
+ podman container port --latest 80`,
+ }
)
var (
portOpts entities.ContainerPortOptions
)
+func portFlags(flags *pflag.FlagSet) {
+ flags.BoolVarP(&portOpts.All, "all", "a", false, "Display port information for all containers")
+ flags.BoolVarP(&portOpts.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},
Command: portCommand,
})
+
flags := portCommand.Flags()
- flags.BoolVarP(&portOpts.All, "all", "a", false, "Display port information for all containers")
- flags.BoolVarP(&portOpts.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
- if registry.IsRemote() {
- _ = flags.MarkHidden("latest")
- }
+ portFlags(flags)
+
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Command: containerPortCommand,
+ Parent: containerCmd,
+ })
+
+ containerPortflags := containerPortCommand.Flags()
+ portFlags(containerPortflags)
+
}
func port(cmd *cobra.Command, args []string) error {
diff --git a/cmd/podman/generate/generate.go b/cmd/podman/generate/generate.go
index b112e666a..7803c0c78 100644
--- a/cmd/podman/generate/generate.go
+++ b/cmd/podman/generate/generate.go
@@ -22,7 +22,7 @@ var (
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
- Mode: []entities.EngineMode{entities.ABIMode},
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: generateCmd,
})
}
diff --git a/cmd/podman/generate/kube.go b/cmd/podman/generate/kube.go
new file mode 100644
index 000000000..86a9cc686
--- /dev/null
+++ b/cmd/podman/generate/kube.go
@@ -0,0 +1,68 @@
+package pods
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/cmd/podman/utils"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ kubeOptions = entities.GenerateKubeOptions{}
+ kubeFile = ""
+ kubeDescription = `Command generates Kubernetes pod and service YAML (v1 specification) from a Podman container or pod.
+
+Whether the input is for a container or pod, Podman will always generate the specification as a pod.`
+
+ kubeCmd = &cobra.Command{
+ Use: "kube [flags] CONTAINER | POD",
+ Short: "Generate Kubernetes YAML from a container or pod.",
+ Long: kubeDescription,
+ RunE: kube,
+ Args: cobra.ExactArgs(1),
+ Example: `podman generate kube ctrID
+ podman generate kube podID
+ podman generate kube --service podID`,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: kubeCmd,
+ Parent: generateCmd,
+ })
+ flags := kubeCmd.Flags()
+ flags.BoolVarP(&kubeOptions.Service, "service", "s", false, "Generate YAML for a Kubernetes service object")
+ flags.StringVarP(&kubeFile, "filename", "f", "", "Write output to the specified path")
+ flags.SetNormalizeFunc(utils.AliasFlags)
+}
+
+func kube(cmd *cobra.Command, args []string) error {
+ report, err := registry.ContainerEngine().GenerateKube(registry.GetContext(), args[0], kubeOptions)
+ if err != nil {
+ return err
+ }
+
+ content, err := ioutil.ReadAll(report.Reader)
+ if err != nil {
+ return err
+ }
+ if cmd.Flags().Changed("filename") {
+ if _, err := os.Stat(kubeFile); err == nil {
+ return errors.Errorf("cannot write to %q", kubeFile)
+ }
+ if err := ioutil.WriteFile(kubeFile, content, 0644); err != nil {
+ return errors.Wrapf(err, "cannot write to %q", kubeFile)
+ }
+ return nil
+ }
+
+ fmt.Println(string(content))
+ return nil
+}
diff --git a/cmd/podman/generate/systemd.go b/cmd/podman/generate/systemd.go
index 55d770249..20d9748d4 100644
--- a/cmd/podman/generate/systemd.go
+++ b/cmd/podman/generate/systemd.go
@@ -29,7 +29,7 @@ var (
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
- Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Mode: []entities.EngineMode{entities.ABIMode},
Command: systemdCmd,
Parent: generateCmd,
})
diff --git a/cmd/podman/images/trust.go b/cmd/podman/images/trust.go
new file mode 100644
index 000000000..88a567871
--- /dev/null
+++ b/cmd/podman/images/trust.go
@@ -0,0 +1,27 @@
+package images
+
+import (
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/cmd/podman/validate"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ trustDescription = `Manages which registries you trust as a source of container images based on their location.
+ The location is determined by the transport and the registry host of the image. Using this container image docker://quay.io/podman/stable as an example, docker is the transport and quay.io is the registry host.`
+ trustCmd = &cobra.Command{
+ Use: "trust",
+ Short: "Manage container image trust policy",
+ Long: trustDescription,
+ RunE: validate.SubCommandExists,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Command: trustCmd,
+ Parent: imageCmd,
+ })
+}
diff --git a/cmd/podman/images/trust_set.go b/cmd/podman/images/trust_set.go
new file mode 100644
index 000000000..5868f5546
--- /dev/null
+++ b/cmd/podman/images/trust_set.go
@@ -0,0 +1,56 @@
+package images
+
+import (
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/libpod/image"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/libpod/pkg/util"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ setTrustDescription = "Set default trust policy or add a new trust policy for a registry"
+ setTrustCommand = &cobra.Command{
+ Use: "set [flags] REGISTRY",
+ Short: "Set default trust policy or a new trust policy for a registry",
+ Long: setTrustDescription,
+ Example: "",
+ RunE: setTrust,
+ Args: cobra.ExactArgs(1),
+ }
+)
+
+var (
+ setOptions entities.SetTrustOptions
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Command: setTrustCommand,
+ Parent: trustCmd,
+ })
+ setFlags := setTrustCommand.Flags()
+ setFlags.StringVar(&setOptions.PolicyPath, "policypath", "", "")
+ _ = setFlags.MarkHidden("policypath")
+ setFlags.StringSliceVarP(&setOptions.PubKeysFile, "pubkeysfile", "f", []string{}, `Path of installed public key(s) to trust for TARGET.
+Absolute path to keys is added to policy.json. May
+used multiple times to define multiple public keys.
+File(s) must exist before using this command`)
+ setFlags.StringVarP(&setOptions.Type, "type", "t", "signedBy", "Trust type, accept values: signedBy(default), accept, reject")
+}
+
+func setTrust(cmd *cobra.Command, args []string) error {
+ validTrustTypes := []string{"accept", "insecureAcceptAnything", "reject", "signedBy"}
+
+ valid, err := image.IsValidImageURI(args[0])
+ if err != nil || !valid {
+ return errors.Wrapf(err, "invalid image uri %s", args[0])
+ }
+
+ if !util.StringInSlice(setOptions.Type, validTrustTypes) {
+ return errors.Errorf("invalid choice: %s (choose from 'accept', 'reject', 'signedBy')", setOptions.Type)
+ }
+ return registry.ImageEngine().SetTrust(registry.Context(), args, setOptions)
+}
diff --git a/cmd/podman/images/trust_show.go b/cmd/podman/images/trust_show.go
new file mode 100644
index 000000000..23ee6c709
--- /dev/null
+++ b/cmd/podman/images/trust_show.go
@@ -0,0 +1,77 @@
+package images
+
+import (
+ "fmt"
+ "os"
+ "text/tabwriter"
+ "text/template"
+
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ showTrustDescription = "Display trust policy for the system"
+ showTrustCommand = &cobra.Command{
+ Use: "show [flags] [REGISTRY]",
+ Short: "Display trust policy for the system",
+ Long: showTrustDescription,
+ RunE: showTrust,
+ Example: "",
+ }
+)
+
+var (
+ showTrustOptions entities.ShowTrustOptions
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Command: showTrustCommand,
+ Parent: trustCmd,
+ })
+ showFlags := showTrustCommand.Flags()
+ showFlags.BoolVarP(&showTrustOptions.JSON, "json", "j", false, "Output as json")
+ showFlags.StringVar(&showTrustOptions.PolicyPath, "policypath", "", "")
+ showFlags.BoolVar(&showTrustOptions.Raw, "raw", false, "Output raw policy file")
+ _ = showFlags.MarkHidden("policypath")
+ showFlags.StringVar(&showTrustOptions.RegistryPath, "registrypath", "", "")
+ _ = showFlags.MarkHidden("registrypath")
+
+}
+
+func showTrust(cmd *cobra.Command, args []string) error {
+ report, err := registry.ImageEngine().ShowTrust(registry.Context(), args, showTrustOptions)
+ if err != nil {
+ return err
+ }
+ if showTrustOptions.Raw {
+ fmt.Println(report.Raw)
+ return nil
+ }
+ if showTrustOptions.JSON {
+ b, err := json.MarshalIndent(report.Policies, "", " ")
+ if err != nil {
+ return err
+ }
+ fmt.Println(string(b))
+ return nil
+ }
+
+ row := "{{.RepoName}}\t{{.Type}}\t{{.GPGId}}\t{{.SignatureStore}}\n"
+ format := "{{range . }}" + row + "{{end}}"
+ tmpl, err := template.New("listContainers").Parse(format)
+ if err != nil {
+ return err
+ }
+ w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
+ if err := tmpl.Execute(w, report.Policies); err != nil {
+ return err
+ }
+ if err := w.Flush(); err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/cmd/podman/main.go b/cmd/podman/main.go
index 422dee90b..76ec7bc8e 100644
--- a/cmd/podman/main.go
+++ b/cmd/podman/main.go
@@ -10,6 +10,7 @@ import (
_ "github.com/containers/libpod/cmd/podman/images"
_ "github.com/containers/libpod/cmd/podman/manifest"
_ "github.com/containers/libpod/cmd/podman/networks"
+ _ "github.com/containers/libpod/cmd/podman/play"
_ "github.com/containers/libpod/cmd/podman/pods"
"github.com/containers/libpod/cmd/podman/registry"
_ "github.com/containers/libpod/cmd/podman/system"
diff --git a/cmd/podman/parse/common.go b/cmd/podman/parse/common.go
index a5e9b4fc2..13f425b6d 100644
--- a/cmd/podman/parse/common.go
+++ b/cmd/podman/parse/common.go
@@ -30,13 +30,20 @@ func CheckAllLatestAndCIDFile(c *cobra.Command, args []string, ignoreArgLen bool
return errors.Errorf("--all and --latest cannot be used together")
}
+ if (argLen > 0) && specifiedAll {
+ return errors.Errorf("no arguments are needed with --all")
+ }
+
if ignoreArgLen {
return nil
}
- if (argLen > 0) && (specifiedAll || specifiedLatest) {
- return errors.Errorf("no arguments are needed with --all or --latest")
- } else if cidfile && (argLen > 0) && (specifiedAll || specifiedLatest || specifiedCIDFile) {
- return errors.Errorf("no arguments are needed with --all, --latest or --cidfile")
+
+ if argLen > 0 {
+ if specifiedLatest {
+ return errors.Errorf("no arguments are needed with --latest")
+ } else if cidfile && (specifiedLatest || specifiedCIDFile) {
+ return errors.Errorf("no arguments are needed with --latest or --cidfile")
+ }
}
if specifiedCIDFile {
diff --git a/cmd/podman/play/kube.go b/cmd/podman/play/kube.go
new file mode 100644
index 000000000..2499b54b9
--- /dev/null
+++ b/cmd/podman/play/kube.go
@@ -0,0 +1,101 @@
+package pods
+
+import (
+ "fmt"
+ "os"
+
+ "github.com/containers/common/pkg/auth"
+ "github.com/containers/image/v5/types"
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/cmd/podman/utils"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+// playKubeOptionsWrapper allows for separating CLI-only fields from API-only
+// fields.
+type playKubeOptionsWrapper struct {
+ entities.PlayKubeOptions
+
+ TLSVerifyCLI bool
+}
+
+var (
+ // https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/
+ defaultSeccompRoot = "/var/lib/kubelet/seccomp"
+ kubeOptions = playKubeOptionsWrapper{}
+ kubeDescription = `Command reads in a structured file of Kubernetes YAML.
+
+ It creates the pod and containers described in the YAML. The containers within the pod are then started and the ID of the new Pod is output.`
+
+ kubeCmd = &cobra.Command{
+ Use: "kube [flags] KUBEFILE",
+ Short: "Play a pod based on Kubernetes YAML.",
+ Long: kubeDescription,
+ RunE: kube,
+ Args: cobra.ExactArgs(1),
+ Example: `podman play kube nginx.yml
+ podman play kube --creds user:password --seccomp-profile-root /custom/path apache.yml`,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: kubeCmd,
+ Parent: playCmd,
+ })
+
+ flags := kubeCmd.Flags()
+ flags.SetNormalizeFunc(utils.AliasFlags)
+ flags.StringVar(&kubeOptions.Credentials, "creds", "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry")
+ flags.StringVar(&kubeOptions.Network, "network", "", "Connect pod to CNI network(s)")
+ flags.BoolVarP(&kubeOptions.Quiet, "quiet", "q", false, "Suppress output information when pulling images")
+ if !registry.IsRemote() {
+ flags.StringVar(&kubeOptions.Authfile, "authfile", auth.GetDefaultAuthFile(), "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override")
+ flags.StringVar(&kubeOptions.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys")
+ flags.BoolVar(&kubeOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries")
+ flags.StringVar(&kubeOptions.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)")
+ flags.StringVar(&kubeOptions.SeccompProfileRoot, "seccomp-profile-root", defaultSeccompRoot, "Directory path for seccomp profiles")
+ }
+}
+
+func kube(cmd *cobra.Command, args []string) error {
+ // TLS verification in c/image is controlled via a `types.OptionalBool`
+ // which allows for distinguishing among set-true, set-false, unspecified
+ // which is important to implement a sane way of dealing with defaults of
+ // boolean CLI flags.
+ if cmd.Flags().Changed("tls-verify") {
+ kubeOptions.SkipTLSVerify = types.NewOptionalBool(!kubeOptions.TLSVerifyCLI)
+ }
+ if kubeOptions.Authfile != "" {
+ if _, err := os.Stat(kubeOptions.Authfile); err != nil {
+ return errors.Wrapf(err, "error getting authfile %s", kubeOptions.Authfile)
+ }
+ }
+
+ report, err := registry.ContainerEngine().PlayKube(registry.GetContext(), args[0], kubeOptions.PlayKubeOptions)
+ if err != nil {
+ return err
+ }
+
+ for _, l := range report.Logs {
+ fmt.Fprintf(os.Stderr, l)
+ }
+
+ fmt.Printf("Pod:\n%s\n", report.Pod)
+ switch len(report.Containers) {
+ case 0:
+ return nil
+ case 1:
+ fmt.Printf("Container:\n")
+ default:
+ fmt.Printf("Containers:\n")
+ }
+ for _, ctr := range report.Containers {
+ fmt.Println(ctr)
+ }
+
+ return nil
+}
diff --git a/cmd/podman/play/play.go b/cmd/podman/play/play.go
new file mode 100644
index 000000000..b151e5f5d
--- /dev/null
+++ b/cmd/podman/play/play.go
@@ -0,0 +1,26 @@
+package pods
+
+import (
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/cmd/podman/validate"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ // Command: podman _play_
+ playCmd = &cobra.Command{
+ Use: "play",
+ Short: "Play a pod and its containers from a structured file.",
+ Long: "Play structured data (e.g., Kubernetes pod or service yaml) based on containers and pods.",
+ TraverseChildren: true,
+ RunE: validate.SubCommandExists,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: playCmd,
+ })
+}
diff --git a/cmd/podman/pods/create.go b/cmd/podman/pods/create.go
index 85b96d37b..0a2016496 100644
--- a/cmd/podman/pods/create.go
+++ b/cmd/podman/pods/create.go
@@ -12,6 +12,7 @@ import (
"github.com/containers/libpod/cmd/podman/validate"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/errorhandling"
+ createconfig "github.com/containers/libpod/pkg/spec"
"github.com/containers/libpod/pkg/specgen"
"github.com/containers/libpod/pkg/util"
"github.com/pkg/errors"
@@ -57,7 +58,7 @@ func init() {
flags.StringVarP(&createOptions.Name, "name", "n", "", "Assign a name to the pod")
flags.StringVarP(&createOptions.Hostname, "hostname", "", "", "Set a hostname to the pod")
flags.StringVar(&podIDFile, "pod-id-file", "", "Write the pod ID to the file")
- flags.StringVar(&share, "share", common.DefaultKernelNamespaces, "A comma delimited list of kernel namespaces the pod will share")
+ flags.StringVar(&share, "share", createconfig.DefaultKernelNamespaces, "A comma delimited list of kernel namespaces the pod will share")
}
func create(cmd *cobra.Command, args []string) error {