summaryrefslogtreecommitdiff
path: root/cmd/podman
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podman')
-rw-r--r--cmd/podman/README.md66
-rw-r--r--cmd/podman/common/create.go28
-rw-r--r--cmd/podman/common/create_opts.go2
-rw-r--r--cmd/podman/common/specgen.go24
-rw-r--r--cmd/podman/containers/create.go38
-rw-r--r--cmd/podman/containers/ps.go4
-rw-r--r--cmd/podman/containers/run.go4
-rw-r--r--cmd/podman/containers/start.go2
-rw-r--r--cmd/podman/images/search.go4
-rw-r--r--cmd/podman/main.go1
-rw-r--r--cmd/podman/networks/create.go81
-rw-r--r--cmd/podman/networks/inspect.go46
-rw-r--r--cmd/podman/networks/list.go133
-rw-r--r--cmd/podman/networks/network.go9
-rw-r--r--cmd/podman/networks/rm.go63
15 files changed, 431 insertions, 74 deletions
diff --git a/cmd/podman/README.md b/cmd/podman/README.md
index c1b8f48a7..da92d0216 100644
--- a/cmd/podman/README.md
+++ b/cmd/podman/README.md
@@ -1,23 +1,16 @@
-# Adding a podman V2 commands
+# Podman CLI
-## Build podman V2
+The following is an example of how to add a new primary command (`manifest`) and a sub-command (`inspect`) to the Podman CLI.
+This is example code, the production code has additional error checking and the business logic provided.
-```shell script
-$ cd $GOPATH/src/github.com/containers/libpod/cmd/podmanV2
-```
-If you wish to include the libpod library in your program,
-```shell script
-$ go build -tags 'ABISupport' .
-```
-The `--remote` flag may be used to connect to the Podman service using the API.
-Otherwise, direct calls will be made to the Libpod library.
-```shell script
-$ go build -tags '!ABISupport' .
-```
-The Libpod library is not linked into the executable.
-All calls are made via the API and `--remote=False` is an error condition.
+See items below for details on building, installing, contributing to Podman:
+ - [Readme](README.md)
+ - [Contributing](CONTRIBUTING.md)
+ - [Podman Usage](transfer.md)
+ - [Trouble Shooting](troubleshooting.md)
+ - [Code Of Conduct](CODE-OF-CONDUCT.md)
-## Adding a new command `podman manifests`
+## Adding a new command `podman manifest`
```shell script
$ mkdir -p $GOPATH/src/github.com/containers/libpod/cmd/podmanV2/manifests
```
@@ -27,6 +20,7 @@ package manifests
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"
)
@@ -36,11 +30,11 @@ var (
manifestCmd = &cobra.Command{
Use: "manifest",
Short: "Manage manifests",
+ Args: cobra.ExactArgs(1),
Long: "Manage manifests",
- Example: "podman manifests IMAGE",
+ Example: "podman manifest IMAGE",
TraverseChildren: true,
- PersistentPreRunE: preRunE,
- RunE: registry.SubCommandExists, // Report error if there is no sub command given
+ RunE: validate.SubCommandExists, // Report error if there is no sub command given
}
)
func init() {
@@ -51,15 +45,6 @@ func init() {
// The definition for this command
Command: manifestCmd,
})
- // Setup cobra templates, sub commands will inherit
- manifestCmd.SetHelpTemplate(registry.HelpTemplate())
- manifestCmd.SetUsageTemplate(registry.UsageTemplate())
-}
-
-// preRunE populates the image engine for sub commands
-func preRunE(cmd *cobra.Command, args []string) error {
- _, err := registry.NewImageEngine(cmd, args)
- return err
}
```
To "wire" in the `manifest` command, edit the file ```$GOPATH/src/github.com/containers/libpod/cmd/podmanV2/main.go``` to add:
@@ -87,7 +72,11 @@ var (
Short: "Display manifest from image",
Long: "Displays the low-level information on a manifest identified by image name or ID",
RunE: inspect,
- Example: "podman manifest DEADBEEF",
+ Annotations: map[string]string{
+ // Add this annotation if this command cannot be run rootless
+ // registry.ParentNSRequired: "",
+ },
+ Example: "podman manifest inspect DEADBEEF",
}
)
@@ -98,6 +87,7 @@ func init() {
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
// The definition for this command
Command: inspectCmd,
+ // The parent command to proceed this command on the CLI
Parent: manifestCmd,
})
@@ -106,8 +96,22 @@ func init() {
// Business logic: cmd is inspectCmd, args is the positional arguments from os.Args
func inspect(cmd *cobra.Command, args []string) error {
- // Business logic using registry.ImageEngine
+ // Business logic using registry.ImageEngine()
// Do not pull from libpod directly use the domain objects and types
return nil
}
```
+
+## Helper functions
+
+The complete set can be found in the `validate` package, here are some examples:
+
+ - `cobra.Command{ Args: validate.NoArgs }` used when the command does not accept errors
+ - `cobra.Command{ Args: validate.IdOrLatestArgs }` used to ensure either a list of ids given or the --latest flag
+ - `cobra.Command{ RunE: validate.SubCommandExists }` used to validate a subcommand given to a command
+ - `validate.ChoiceValue` used to create a `pflag.Value` that validate user input against a provided slice of values. For example:
+ ```go
+ flags := cobraCommand.Flags()
+ created := validate.ChoiceValue(&opts.Sort, "command", "created", "id", "image", "names", "runningfor", "size", "status")
+ flags.Var(created, "sort", "Sort output by: "+created.Choices())
+ ```
diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go
index a0aed984c..0f9476754 100644
--- a/cmd/podman/common/create.go
+++ b/cmd/podman/common/create.go
@@ -49,9 +49,7 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
"cap-drop", []string{},
"Drop capabilities from the container",
)
- cgroupNS := ""
- createFlags.StringVar(
- &cgroupNS,
+ createFlags.String(
"cgroupns", containerConfig.CgroupNS(),
"cgroup namespace to use",
)
@@ -155,9 +153,7 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
"device-write-iops", []string{},
"Limit write rate (IO per second) to a device (e.g. --device-write-iops=/dev/sda:1000)",
)
- createFlags.StringVar(
- &cf.Entrypoint,
- "entrypoint", "",
+ createFlags.String("entrypoint", "",
"Overwrite the default ENTRYPOINT of the image",
)
createFlags.StringArrayVarP(
@@ -248,9 +244,7 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
"interactive", "i", false,
"Keep STDIN open even if not attached",
)
- ipcNS := ""
- createFlags.StringVar(
- &ipcNS,
+ createFlags.String(
"ipc", containerConfig.IPCNS(),
"IPC namespace to use",
)
@@ -331,9 +325,7 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
"use `OS` instead of the running OS for choosing images",
)
// markFlagHidden(createFlags, "override-os")
- pid := ""
- createFlags.StringVar(
- &pid,
+ createFlags.String(
"pid", containerConfig.PidNS(),
"PID namespace to use",
)
@@ -397,9 +389,7 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
"security-opt", containerConfig.SecurityOptions(),
"Security Options",
)
- shmSize := ""
- createFlags.StringVar(
- &shmSize,
+ createFlags.String(
"shm-size", containerConfig.ShmSize(),
"Size of /dev/shm "+sizeWithUnitFormat,
)
@@ -464,15 +454,11 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
"user", "u", "",
"Username or UID (format: <name|uid>[:<group|gid>])",
)
- userNS := ""
- createFlags.StringVar(
- &userNS,
+ createFlags.String(
"userns", containerConfig.Containers.UserNS,
"User namespace to use",
)
- utsNS := ""
- createFlags.StringVar(
- &utsNS,
+ createFlags.String(
"uts", containerConfig.Containers.UTSNS,
"UTS namespace to use",
)
diff --git a/cmd/podman/common/create_opts.go b/cmd/podman/common/create_opts.go
index 2f08bb6a6..c275b1674 100644
--- a/cmd/podman/common/create_opts.go
+++ b/cmd/podman/common/create_opts.go
@@ -31,7 +31,7 @@ type ContainerCLIOpts struct {
DeviceReadIOPs []string
DeviceWriteBPs []string
DeviceWriteIOPs []string
- Entrypoint string
+ Entrypoint *string
env []string
EnvHost bool
EnvFile []string
diff --git a/cmd/podman/common/specgen.go b/cmd/podman/common/specgen.go
index 96cd630a3..33cba30cd 100644
--- a/cmd/podman/common/specgen.go
+++ b/cmd/podman/common/specgen.go
@@ -364,20 +364,20 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
s.WorkDir = workDir
entrypoint := []string{}
userCommand := []string{}
- if ep := c.Entrypoint; len(ep) > 0 {
- // Check if entrypoint specified is json
- if err := json.Unmarshal([]byte(c.Entrypoint), &entrypoint); err != nil {
- entrypoint = append(entrypoint, ep)
+ if c.Entrypoint != nil {
+ if ep := *c.Entrypoint; len(ep) > 0 {
+ // Check if entrypoint specified is json
+ if err := json.Unmarshal([]byte(*c.Entrypoint), &entrypoint); err != nil {
+ entrypoint = append(entrypoint, ep)
+ }
}
+ s.Entrypoint = entrypoint
}
-
var command []string
- s.Entrypoint = entrypoint
-
// Build the command
// If we have an entry point, it goes first
- if len(entrypoint) > 0 {
+ if c.Entrypoint != nil {
command = entrypoint
}
if len(inputCommand) > 0 {
@@ -386,9 +386,12 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
userCommand = append(userCommand, inputCommand...)
}
- if len(inputCommand) > 0 {
+ switch {
+ case len(inputCommand) > 0:
s.Command = userCommand
- } else {
+ case c.Entrypoint != nil:
+ s.Command = []string{}
+ default:
s.Command = command
}
@@ -400,6 +403,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
}
s.ShmSize = &shmSize
}
+ s.CNINetworks = c.Net.CNINetworks
s.HostAdd = c.Net.AddHosts
s.UseImageResolvConf = c.Net.UseImageResolvConf
s.DNSServers = c.Net.DNSServers
diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go
index f3f9d18f3..7927da04d 100644
--- a/cmd/podman/containers/create.go
+++ b/cmd/podman/containers/create.go
@@ -1,8 +1,10 @@
package containers
import (
+ "context"
"fmt"
"os"
+ "strings"
"github.com/containers/common/pkg/config"
"github.com/containers/libpod/cmd/podman/common"
@@ -106,6 +108,10 @@ func create(cmd *cobra.Command, args []string) error {
return err
}
+ if _, err := createPodIfNecessary(s); err != nil {
+ return err
+ }
+
report, err := registry.ContainerEngine().ContainerCreate(registry.GetContext(), s)
if err != nil {
return err
@@ -160,6 +166,10 @@ func createInit(c *cobra.Command) error {
if c.Flag("cgroupns").Changed {
cliVals.CGroupsNS = c.Flag("cgroupns").Value.String()
}
+ if c.Flag("entrypoint").Changed {
+ val := c.Flag("entrypoint").Value.String()
+ cliVals.Entrypoint = &val
+ }
// Docker-compatibility: the "-h" flag for run/create is reserved for
// the hostname (see https://github.com/containers/libpod/issues/1367).
@@ -181,8 +191,10 @@ func pullImage(imageName string) error {
return errors.New("unable to find a name and tag match for busybox in repotags: no such image")
}
_, pullErr := registry.ImageEngine().Pull(registry.GetContext(), imageName, entities.ImagePullOptions{
- Authfile: cliVals.Authfile,
- Quiet: cliVals.Quiet,
+ Authfile: cliVals.Authfile,
+ Quiet: cliVals.Quiet,
+ OverrideArch: cliVals.OverrideArch,
+ OverrideOS: cliVals.OverrideOS,
})
if pullErr != nil {
return pullErr
@@ -204,3 +216,25 @@ func openCidFile(cidfile string) (*os.File, error) {
}
return cidFile, nil
}
+
+// createPodIfNecessary automatically creates a pod when requested. if the pod name
+// has the form new:ID, the pod ID is created and the name in the spec generator is replaced
+// with ID.
+func createPodIfNecessary(s *specgen.SpecGenerator) (*entities.PodCreateReport, error) {
+ if !strings.HasPrefix(s.Pod, "new:") {
+ return nil, nil
+ }
+ podName := strings.Replace(s.Pod, "new:", "", 1)
+ if len(podName) < 1 {
+ return nil, errors.Errorf("new pod name must be at least one character")
+ }
+ createOptions := entities.PodCreateOptions{
+ Name: podName,
+ Infra: true,
+ Net: &entities.NetOptions{
+ PublishPorts: s.PortMappings,
+ },
+ }
+ s.Pod = podName
+ return registry.ContainerEngine().PodCreate(context.Background(), createOptions)
+}
diff --git a/cmd/podman/containers/ps.go b/cmd/podman/containers/ps.go
index c5696a158..e9146bda7 100644
--- a/cmd/podman/containers/ps.go
+++ b/cmd/podman/containers/ps.go
@@ -67,8 +67,8 @@ func listFlagSet(flags *pflag.FlagSet) {
flags.BoolVar(&listOpts.Sync, "sync", false, "Sync container state with OCI runtime")
flags.UintVarP(&listOpts.Watch, "watch", "w", 0, "Watch the ps output on an interval in seconds")
- created := validate.ChoiceValue(&listOpts.Sort, "command", "created", "id", "image", "names", "runningfor", "size", "status")
- flags.Var(created, "sort", "Sort output by: "+created.Choices())
+ sort := validate.ChoiceValue(&listOpts.Sort, "command", "created", "id", "image", "names", "runningfor", "size", "status")
+ flags.Var(sort, "sort", "Sort output by: "+sort.Choices())
if registry.IsRemote() {
_ = flags.MarkHidden("latest")
diff --git a/cmd/podman/containers/run.go b/cmd/podman/containers/run.go
index 1e4d47b42..b13983e37 100644
--- a/cmd/podman/containers/run.go
+++ b/cmd/podman/containers/run.go
@@ -146,6 +146,10 @@ func run(cmd *cobra.Command, args []string) error {
}
runOpts.Spec = s
+ if _, err := createPodIfNecessary(s); err != nil {
+ return err
+ }
+
report, err := registry.ContainerEngine().ContainerRun(registry.GetContext(), runOpts)
// report.ExitCode is set by ContainerRun even it it returns an error
if report != nil {
diff --git a/cmd/podman/containers/start.go b/cmd/podman/containers/start.go
index 381bf8e26..ce78d24ed 100644
--- a/cmd/podman/containers/start.go
+++ b/cmd/podman/containers/start.go
@@ -99,7 +99,7 @@ func start(cmd *cobra.Command, args []string) error {
for _, r := range responses {
if r.Err == nil {
- fmt.Println(r.Id)
+ fmt.Println(r.RawInput)
} else {
errs = append(errs, r.Err)
}
diff --git a/cmd/podman/images/search.go b/cmd/podman/images/search.go
index a8abfb339..a259b2419 100644
--- a/cmd/podman/images/search.go
+++ b/cmd/podman/images/search.go
@@ -105,6 +105,10 @@ func imageSearch(cmd *cobra.Command, args []string) error {
return errors.Errorf("search requires exactly one argument")
}
+ if searchOptions.Limit > 100 {
+ return errors.Errorf("Limit %d is outside the range of [1, 100]", searchOptions.Limit)
+ }
+
// 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
diff --git a/cmd/podman/main.go b/cmd/podman/main.go
index 3a8958b6d..422dee90b 100644
--- a/cmd/podman/main.go
+++ b/cmd/podman/main.go
@@ -9,6 +9,7 @@ import (
_ "github.com/containers/libpod/cmd/podman/healthcheck"
_ "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/pods"
"github.com/containers/libpod/cmd/podman/registry"
_ "github.com/containers/libpod/cmd/podman/system"
diff --git a/cmd/podman/networks/create.go b/cmd/podman/networks/create.go
new file mode 100644
index 000000000..2bb75ea9e
--- /dev/null
+++ b/cmd/podman/networks/create.go
@@ -0,0 +1,81 @@
+package network
+
+import (
+ "fmt"
+ "net"
+
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/libpod/pkg/network"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+ "github.com/spf13/pflag"
+)
+
+var (
+ networkCreateDescription = `create CNI networks for containers and pods`
+ networkCreateCommand = &cobra.Command{
+ Use: "create [flags] [NETWORK]",
+ Short: "network create",
+ Long: networkCreateDescription,
+ RunE: networkCreate,
+ Example: `podman network create podman1`,
+ Annotations: map[string]string{
+ registry.ParentNSRequired: "",
+ },
+ }
+)
+
+var (
+ networkCreateOptions entities.NetworkCreateOptions
+)
+
+func networkCreateFlags(flags *pflag.FlagSet) {
+ flags.StringVarP(&networkCreateOptions.Driver, "driver", "d", "bridge", "driver to manage the network")
+ flags.IPVar(&networkCreateOptions.Gateway, "gateway", nil, "IPv4 or IPv6 gateway for the subnet")
+ flags.BoolVar(&networkCreateOptions.Internal, "internal", false, "restrict external access from this network")
+ flags.IPNetVar(&networkCreateOptions.Range, "ip-range", net.IPNet{}, "allocate container IP from range")
+ flags.StringVar(&networkCreateOptions.MacVLAN, "macvlan", "", "create a Macvlan connection based on this device")
+ // TODO not supported yet
+ //flags.StringVar(&networkCreateOptions.IPamDriver, "ipam-driver", "", "IP Address Management Driver")
+ // TODO enable when IPv6 is working
+ //flags.BoolVar(&networkCreateOptions.IPV6, "IPv6", false, "enable IPv6 networking")
+ flags.IPNetVar(&networkCreateOptions.Subnet, "subnet", net.IPNet{}, "subnet in CIDR format")
+ flags.BoolVar(&networkCreateOptions.DisableDNS, "disable-dns", false, "disable dns plugin")
+}
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Command: networkCreateCommand,
+ Parent: networkCmd,
+ })
+ flags := networkCreateCommand.Flags()
+ networkCreateFlags(flags)
+
+}
+
+func networkCreate(cmd *cobra.Command, args []string) error {
+ var (
+ name string
+ )
+ if err := network.IsSupportedDriver(networkCreateOptions.Driver); err != nil {
+ return err
+ }
+ if len(args) > 1 {
+ return errors.Errorf("only one network can be created at a time")
+ }
+ if len(args) > 0 && !libpod.NameRegex.MatchString(args[0]) {
+ return libpod.RegexError
+ }
+
+ if len(args) > 0 {
+ name = args[0]
+ }
+ response, err := registry.ContainerEngine().NetworkCreate(registry.Context(), name, networkCreateOptions)
+ if err != nil {
+ return err
+ }
+ fmt.Println(response.Filename)
+ return nil
+}
diff --git a/cmd/podman/networks/inspect.go b/cmd/podman/networks/inspect.go
new file mode 100644
index 000000000..0bc73579a
--- /dev/null
+++ b/cmd/podman/networks/inspect.go
@@ -0,0 +1,46 @@
+package network
+
+import (
+ "encoding/json"
+ "fmt"
+
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ networkinspectDescription = `Inspect network`
+ networkinspectCommand = &cobra.Command{
+ Use: "inspect NETWORK [NETWORK...] [flags] ",
+ Short: "network inspect",
+ Long: networkinspectDescription,
+ RunE: networkInspect,
+ Example: `podman network inspect podman`,
+ Args: cobra.MinimumNArgs(1),
+ Annotations: map[string]string{
+ registry.ParentNSRequired: "",
+ },
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Command: networkinspectCommand,
+ Parent: networkCmd,
+ })
+}
+
+func networkInspect(cmd *cobra.Command, args []string) error {
+ responses, err := registry.ContainerEngine().NetworkInspect(registry.Context(), args, entities.NetworkInspectOptions{})
+ if err != nil {
+ return err
+ }
+ b, err := json.MarshalIndent(responses, "", " ")
+ if err != nil {
+ return err
+ }
+ fmt.Println(string(b))
+ return nil
+}
diff --git a/cmd/podman/networks/list.go b/cmd/podman/networks/list.go
new file mode 100644
index 000000000..e27062255
--- /dev/null
+++ b/cmd/podman/networks/list.go
@@ -0,0 +1,133 @@
+package network
+
+import (
+ "encoding/json"
+ "fmt"
+ "html/template"
+ "io"
+ "os"
+ "strings"
+
+ "github.com/containers/libpod/cmd/podman/validate"
+
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/libpod/pkg/network"
+ "github.com/spf13/cobra"
+ "github.com/spf13/pflag"
+)
+
+var (
+ networklistDescription = `List networks`
+ networklistCommand = &cobra.Command{
+ Use: "ls",
+ Args: validate.NoArgs,
+ Short: "network list",
+ Long: networklistDescription,
+ RunE: networkList,
+ Example: `podman network list`,
+ Annotations: map[string]string{
+ registry.ParentNSRequired: "",
+ },
+ }
+)
+
+var (
+ networkListOptions entities.NetworkListOptions
+ headers string = "NAME\tVERSION\tPLUGINS\n"
+ defaultListRow string = "{{.Name}}\t{{.Version}}\t{{.Plugins}}\n"
+)
+
+func networkListFlags(flags *pflag.FlagSet) {
+ // TODO enable filters based on something
+ //flags.StringSliceVarP(&networklistCommand.Filter, "filter", "f", []string{}, "Pause all running containers")
+ flags.StringVarP(&networkListOptions.Format, "format", "f", "", "Pretty-print containers to JSON or using a Go template")
+ flags.BoolVarP(&networkListOptions.Quiet, "quiet", "q", false, "display only names")
+}
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Command: networklistCommand,
+ Parent: networkCmd,
+ })
+ flags := networklistCommand.Flags()
+ networkListFlags(flags)
+}
+
+func networkList(cmd *cobra.Command, args []string) error {
+ var (
+ w io.Writer = os.Stdout
+ nlprs []NetworkListPrintReports
+ )
+
+ responses, err := registry.ContainerEngine().NetworkList(registry.Context(), networkListOptions)
+ if err != nil {
+ return err
+ }
+
+ // quiet means we only print the network names
+ if networkListOptions.Quiet {
+ return quietOut(responses)
+ }
+
+ if networkListOptions.Format == "json" {
+ return jsonOut(responses)
+ }
+
+ for _, r := range responses {
+ nlprs = append(nlprs, NetworkListPrintReports{r})
+ }
+
+ row := networkListOptions.Format
+ if len(row) < 1 {
+ row = defaultListRow
+ }
+ if !strings.HasSuffix(row, "\n") {
+ row += "\n"
+ }
+
+ format := "{{range . }}" + row + "{{end}}"
+ if !cmd.Flag("format").Changed {
+ format = headers + format
+ }
+ tmpl, err := template.New("listNetworks").Parse(format)
+ if err != nil {
+ return err
+ }
+ if err := tmpl.Execute(w, nlprs); err != nil {
+ return err
+ }
+ if flusher, ok := w.(interface{ Flush() error }); ok {
+ return flusher.Flush()
+ }
+ return nil
+}
+
+func quietOut(responses []*entities.NetworkListReport) error {
+ for _, r := range responses {
+ fmt.Println(r.Name)
+ }
+ return nil
+}
+
+func jsonOut(responses []*entities.NetworkListReport) error {
+ b, err := json.MarshalIndent(responses, "", " ")
+ if err != nil {
+ return err
+ }
+ fmt.Println(string(b))
+ return nil
+}
+
+type NetworkListPrintReports struct {
+ *entities.NetworkListReport
+}
+
+func (n NetworkListPrintReports) Version() string {
+ return n.CNIVersion
+}
+
+func (n NetworkListPrintReports) Plugins() string {
+ return network.GetCNIPlugins(n.NetworkConfigList)
+}
diff --git a/cmd/podman/networks/network.go b/cmd/podman/networks/network.go
index e2a928312..56dd390ea 100644
--- a/cmd/podman/networks/network.go
+++ b/cmd/podman/networks/network.go
@@ -1,4 +1,4 @@
-package images
+package network
import (
"github.com/containers/libpod/cmd/podman/registry"
@@ -9,7 +9,7 @@ import (
var (
// Command: podman _network_
- cmd = &cobra.Command{
+ networkCmd = &cobra.Command{
Use: "network",
Short: "Manage networks",
Long: "Manage networks",
@@ -18,12 +18,9 @@ var (
}
)
-// TODO add the following to main.go to get networks back onto the
-// command list.
-// _ "github.com/containers/libpod/cmd/podman/networks"
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode},
- Command: cmd,
+ Command: networkCmd,
})
}
diff --git a/cmd/podman/networks/rm.go b/cmd/podman/networks/rm.go
new file mode 100644
index 000000000..dc1eb9909
--- /dev/null
+++ b/cmd/podman/networks/rm.go
@@ -0,0 +1,63 @@
+package network
+
+import (
+ "fmt"
+
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/cmd/podman/utils"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+ "github.com/spf13/pflag"
+)
+
+var (
+ networkrmDescription = `Remove networks`
+ networkrmCommand = &cobra.Command{
+ Use: "rm [flags] NETWORK [NETWORK...]",
+ Short: "network rm",
+ Long: networkrmDescription,
+ RunE: networkRm,
+ Example: `podman network rm podman`,
+ Args: cobra.MinimumNArgs(1),
+ Annotations: map[string]string{
+ registry.ParentNSRequired: "",
+ },
+ }
+)
+
+var (
+ networkRmOptions entities.NetworkRmOptions
+)
+
+func networkRmFlags(flags *pflag.FlagSet) {
+ flags.BoolVarP(&networkRmOptions.Force, "force", "f", false, "remove any containers using network")
+}
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Command: networkrmCommand,
+ Parent: networkCmd,
+ })
+ flags := networkrmCommand.Flags()
+ networkRmFlags(flags)
+}
+
+func networkRm(cmd *cobra.Command, args []string) error {
+ var (
+ errs utils.OutputErrors
+ )
+
+ responses, err := registry.ContainerEngine().NetworkRm(registry.Context(), args, networkRmOptions)
+ if err != nil {
+ return err
+ }
+ for _, r := range responses {
+ if r.Err == nil {
+ fmt.Println(r.Name)
+ } else {
+ errs = append(errs, r.Err)
+ }
+ }
+ return errs.PrintErrors()
+}