mirror of
https://github.com/containers/podman.git
synced 2025-06-28 14:29:04 +08:00
inclusion of podman network
adding podman network and the subcommands inspect, list, and rm. the inspect subcommand displays the raw cni network configuration. the list subcommand displays a summary of the cni networks ala ps. and the rm subcommand removes a cni network. Signed-off-by: baude <bbaude@redhat.com>
This commit is contained in:
@ -258,6 +258,20 @@ type MountValues struct {
|
|||||||
Latest bool
|
Latest bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type NetworkListValues struct {
|
||||||
|
PodmanCommand
|
||||||
|
Filter []string
|
||||||
|
Quiet bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type NetworkRmValues struct {
|
||||||
|
PodmanCommand
|
||||||
|
}
|
||||||
|
|
||||||
|
type NetworkInspectValues struct {
|
||||||
|
PodmanCommand
|
||||||
|
}
|
||||||
|
|
||||||
type PauseValues struct {
|
type PauseValues struct {
|
||||||
PodmanCommand
|
PodmanCommand
|
||||||
All bool
|
All bool
|
||||||
|
31
cmd/podman/network.go
Normal file
31
cmd/podman/network.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
//+build !remoteclient
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var networkcheckDescription = "Manage networks"
|
||||||
|
var networkcheckCommand = cliconfig.PodmanCommand{
|
||||||
|
Command: &cobra.Command{
|
||||||
|
Use: "network",
|
||||||
|
Short: "Manage Networks",
|
||||||
|
Long: networkcheckDescription,
|
||||||
|
RunE: commandRunE(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commands that are universally implemented
|
||||||
|
var networkcheckCommands = []*cobra.Command{
|
||||||
|
_networkinspectCommand,
|
||||||
|
_networklistCommand,
|
||||||
|
_networkrmCommand,
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
networkcheckCommand.AddCommand(networkcheckCommands...)
|
||||||
|
networkcheckCommand.SetUsageTemplate(UsageTemplate())
|
||||||
|
rootCmd.AddCommand(networkcheckCommand.Command)
|
||||||
|
}
|
48
cmd/podman/network_inspect.go
Normal file
48
cmd/podman/network_inspect.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// +build !remoteclient
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||||
|
"github.com/containers/libpod/pkg/adapter"
|
||||||
|
"github.com/containers/libpod/pkg/rootless"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
networkinspectCommand cliconfig.NetworkInspectValues
|
||||||
|
networkinspectDescription = `Inspect network`
|
||||||
|
_networkinspectCommand = &cobra.Command{
|
||||||
|
Use: "inspect NETWORK [NETWORK...] [flags] ",
|
||||||
|
Short: "network inspect",
|
||||||
|
Long: networkinspectDescription,
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
networkinspectCommand.InputArgs = args
|
||||||
|
networkinspectCommand.GlobalFlags = MainGlobalOpts
|
||||||
|
networkinspectCommand.Remote = remoteclient
|
||||||
|
return networkinspectCmd(&networkinspectCommand)
|
||||||
|
},
|
||||||
|
Example: `podman network inspect podman`,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
networkinspectCommand.Command = _networkinspectCommand
|
||||||
|
networkinspectCommand.SetHelpTemplate(HelpTemplate())
|
||||||
|
networkinspectCommand.SetUsageTemplate(UsageTemplate())
|
||||||
|
}
|
||||||
|
|
||||||
|
func networkinspectCmd(c *cliconfig.NetworkInspectValues) error {
|
||||||
|
if rootless.IsRootless() && !remoteclient {
|
||||||
|
return errors.New("network inspect is not supported for rootless mode")
|
||||||
|
}
|
||||||
|
if len(c.InputArgs) < 1 {
|
||||||
|
return errors.Errorf("at least one network name is required")
|
||||||
|
}
|
||||||
|
runtime, err := adapter.GetRuntimeNoStore(getContext(), &c.PodmanCommand)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return runtime.NetworkInspect(c)
|
||||||
|
}
|
53
cmd/podman/network_list.go
Normal file
53
cmd/podman/network_list.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// +build !remoteclient
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||||
|
"github.com/containers/libpod/pkg/adapter"
|
||||||
|
"github.com/containers/libpod/pkg/rootless"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
networklistCommand cliconfig.NetworkListValues
|
||||||
|
networklistDescription = `List networks`
|
||||||
|
_networklistCommand = &cobra.Command{
|
||||||
|
Use: "ls",
|
||||||
|
Args: noSubArgs,
|
||||||
|
Short: "network list",
|
||||||
|
Long: networklistDescription,
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
networklistCommand.InputArgs = args
|
||||||
|
networklistCommand.GlobalFlags = MainGlobalOpts
|
||||||
|
networklistCommand.Remote = remoteclient
|
||||||
|
return networklistCmd(&networklistCommand)
|
||||||
|
},
|
||||||
|
Example: `podman network list`,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
networklistCommand.Command = _networklistCommand
|
||||||
|
networklistCommand.SetHelpTemplate(HelpTemplate())
|
||||||
|
networklistCommand.SetUsageTemplate(UsageTemplate())
|
||||||
|
flags := networklistCommand.Flags()
|
||||||
|
// TODO enable filters based on something
|
||||||
|
//flags.StringSliceVarP(&networklistCommand.Filter, "filter", "f", []string{}, "Pause all running containers")
|
||||||
|
flags.BoolVarP(&networklistCommand.Quiet, "quiet", "q", false, "display only names")
|
||||||
|
}
|
||||||
|
|
||||||
|
func networklistCmd(c *cliconfig.NetworkListValues) error {
|
||||||
|
if rootless.IsRootless() && !remoteclient {
|
||||||
|
return errors.New("network list is not supported for rootless mode")
|
||||||
|
}
|
||||||
|
if len(c.InputArgs) > 0 {
|
||||||
|
return errors.New("network list takes no arguments")
|
||||||
|
}
|
||||||
|
runtime, err := adapter.GetRuntimeNoStore(getContext(), &c.PodmanCommand)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return runtime.NetworkList(c)
|
||||||
|
}
|
48
cmd/podman/network_rm.go
Normal file
48
cmd/podman/network_rm.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// +build !remoteclient
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||||
|
"github.com/containers/libpod/pkg/adapter"
|
||||||
|
"github.com/containers/libpod/pkg/rootless"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
networkrmCommand cliconfig.NetworkRmValues
|
||||||
|
networkrmDescription = `Remove networks`
|
||||||
|
_networkrmCommand = &cobra.Command{
|
||||||
|
Use: "rm [flags] NETWORK [NETWORK...]",
|
||||||
|
Short: "network rm",
|
||||||
|
Long: networkrmDescription,
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
networkrmCommand.InputArgs = args
|
||||||
|
networkrmCommand.GlobalFlags = MainGlobalOpts
|
||||||
|
networkrmCommand.Remote = remoteclient
|
||||||
|
return networkrmCmd(&networkrmCommand)
|
||||||
|
},
|
||||||
|
Example: `podman network rm podman`,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
networkrmCommand.Command = _networkrmCommand
|
||||||
|
networkrmCommand.SetHelpTemplate(HelpTemplate())
|
||||||
|
networkrmCommand.SetUsageTemplate(UsageTemplate())
|
||||||
|
}
|
||||||
|
|
||||||
|
func networkrmCmd(c *cliconfig.NetworkRmValues) error {
|
||||||
|
if rootless.IsRootless() && !remoteclient {
|
||||||
|
return errors.New("network rm is not supported for rootless mode")
|
||||||
|
}
|
||||||
|
if len(c.InputArgs) < 1 {
|
||||||
|
return errors.Errorf("at least one network name is required")
|
||||||
|
}
|
||||||
|
runtime, err := adapter.GetRuntimeNoStore(getContext(), &c.PodmanCommand)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return runtime.NetworkRemove(c)
|
||||||
|
}
|
@ -44,6 +44,10 @@
|
|||||||
| [podman-logout(1)](/docs/podman-logout.1.md) | Logout of a container registry |
|
| [podman-logout(1)](/docs/podman-logout.1.md) | Logout of a container registry |
|
||||||
| [podman-logs(1)](/docs/podman-logs.1.md) | Display the logs of a container |
|
| [podman-logs(1)](/docs/podman-logs.1.md) | Display the logs of a container |
|
||||||
| [podman-mount(1)](/docs/podman-mount.1.md) | Mount a working container's root filesystem |
|
| [podman-mount(1)](/docs/podman-mount.1.md) | Mount a working container's root filesystem |
|
||||||
|
| [podman-network(1)](/docs/podman-network.1.md) | Manage Podman CNI networks |
|
||||||
|
| [podman-network-inspect(1)](/docs/podman-network-inspect.1.md) | Inspect one or more Podman networks |
|
||||||
|
| [podman-network-ls(1)](/docs/podman-network-ls.1.md) | Display a summary of Podman networks |
|
||||||
|
| [podman-network-rm(1)](/docs/podman-network-rm.1.md) | Remove one or more Podman networks |
|
||||||
| [podman-pause(1)](/docs/podman-pause.1.md) | Pause one or more running containers | [](https://podman.io/asciinema/podman/pause_unpause/) | [Here](https://github.com/containers/Demos/blob/master/podman_cli/podman_pause_unpause.sh) |
|
| [podman-pause(1)](/docs/podman-pause.1.md) | Pause one or more running containers | [](https://podman.io/asciinema/podman/pause_unpause/) | [Here](https://github.com/containers/Demos/blob/master/podman_cli/podman_pause_unpause.sh) |
|
||||||
| [podman-play(1)](/docs/podman-play.1.md) | Play pods and containers based on a structured input file |
|
| [podman-play(1)](/docs/podman-play.1.md) | Play pods and containers based on a structured input file |
|
||||||
| [podman-pod(1)](/docs/podman-pod.1.md) | Simple management tool for groups of containers, called pods |
|
| [podman-pod(1)](/docs/podman-pod.1.md) | Simple management tool for groups of containers, called pods |
|
||||||
|
@ -946,6 +946,78 @@ _podman_healthcheck() {
|
|||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_podman_network() {
|
||||||
|
local boolean_options="
|
||||||
|
--help
|
||||||
|
-h
|
||||||
|
"
|
||||||
|
subcommands="
|
||||||
|
inspect
|
||||||
|
ls
|
||||||
|
rm
|
||||||
|
"
|
||||||
|
__podman_subcommands "$subcommands $aliases" && return
|
||||||
|
|
||||||
|
case "$cur" in
|
||||||
|
-*)
|
||||||
|
COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) )
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
_podman_network_inspect() {
|
||||||
|
local options_with_args="
|
||||||
|
"
|
||||||
|
local boolean_options="
|
||||||
|
--help
|
||||||
|
-h
|
||||||
|
"
|
||||||
|
_complete_ "$options_with_args" "$boolean_options"
|
||||||
|
|
||||||
|
case "$cur" in
|
||||||
|
-*)
|
||||||
|
COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
_podman_network_ls() {
|
||||||
|
local options_with_args="
|
||||||
|
"
|
||||||
|
local boolean_options="
|
||||||
|
--help
|
||||||
|
-h
|
||||||
|
--quiet
|
||||||
|
-q
|
||||||
|
"
|
||||||
|
_complete_ "$options_with_args" "$boolean_options"
|
||||||
|
|
||||||
|
case "$cur" in
|
||||||
|
-*)
|
||||||
|
COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
_podman_network_ls() {
|
||||||
|
local options_with_args="
|
||||||
|
"
|
||||||
|
local boolean_options="
|
||||||
|
--help
|
||||||
|
-h
|
||||||
|
"
|
||||||
|
_complete_ "$options_with_args" "$boolean_options"
|
||||||
|
|
||||||
|
case "$cur" in
|
||||||
|
-*)
|
||||||
|
COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
_podman_generate() {
|
_podman_generate() {
|
||||||
local boolean_options="
|
local boolean_options="
|
||||||
--help
|
--help
|
||||||
|
50
docs/podman-network-inspect.1.md
Normal file
50
docs/podman-network-inspect.1.md
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
% podman-network-inspect(1)
|
||||||
|
|
||||||
|
## NAME
|
||||||
|
podman\-network-inspect- Inspect one or more Podman networks
|
||||||
|
|
||||||
|
## SYNOPSIS
|
||||||
|
**podman network inspect** [*network* ...]
|
||||||
|
|
||||||
|
## DESCRIPTION
|
||||||
|
Display the raw (JSON format) network configuration. This command is not available for rootless users.
|
||||||
|
|
||||||
|
## EXAMPLE
|
||||||
|
|
||||||
|
Inspect the default podman network
|
||||||
|
|
||||||
|
```
|
||||||
|
# podman network inspect podman
|
||||||
|
[{
|
||||||
|
"cniVersion": "0.3.0",
|
||||||
|
"name": "podman",
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"type": "bridge",
|
||||||
|
"bridge": "cni0",
|
||||||
|
"isGateway": true,
|
||||||
|
"ipMasq": true,
|
||||||
|
"ipam": {
|
||||||
|
"type": "host-local",
|
||||||
|
"subnet": "10.88.1.0/24",
|
||||||
|
"routes": [
|
||||||
|
{ "dst": "0.0.0.0/0" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "portmap",
|
||||||
|
"capabilities": {
|
||||||
|
"portMappings": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## SEE ALSO
|
||||||
|
podman(1), podman-network(1), podman-network-ls(1)
|
||||||
|
|
||||||
|
## HISTORY
|
||||||
|
August 2019, Originally compiled by Brent Baude <bbaude@redhat.com>
|
43
docs/podman-network-ls.1.md
Normal file
43
docs/podman-network-ls.1.md
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
% podman-network-ls(1)
|
||||||
|
|
||||||
|
## NAME
|
||||||
|
podman\-network-ls- Display a summary of CNI networks
|
||||||
|
|
||||||
|
## SYNOPSIS
|
||||||
|
**podman network ls** [*options*]
|
||||||
|
|
||||||
|
## DESCRIPTION
|
||||||
|
Displays a list of existing podman networks. This command is not available for rootless users.
|
||||||
|
|
||||||
|
## OPTIONS
|
||||||
|
**--quiet**, **-q**
|
||||||
|
|
||||||
|
The `quiet` options will restrict the output to only the network names
|
||||||
|
|
||||||
|
## EXAMPLE
|
||||||
|
|
||||||
|
Display networks
|
||||||
|
|
||||||
|
```
|
||||||
|
# podman network ls
|
||||||
|
NAME VERSION PLUGINS
|
||||||
|
podman 0.3.0 bridge,portmap
|
||||||
|
podman2 0.3.0 bridge,portmap
|
||||||
|
outside 0.3.0 bridge
|
||||||
|
podman9 0.3.0 bridge,portmap
|
||||||
|
```
|
||||||
|
|
||||||
|
Display only network names
|
||||||
|
```
|
||||||
|
# podman network ls -q
|
||||||
|
podman
|
||||||
|
podman2
|
||||||
|
outside
|
||||||
|
podman9
|
||||||
|
```
|
||||||
|
|
||||||
|
## SEE ALSO
|
||||||
|
podman(1), podman-network(1), podman-network-inspect(1)
|
||||||
|
|
||||||
|
## HISTORY
|
||||||
|
August 2019, Originally compiled by Brent Baude <bbaude@redhat.com>
|
25
docs/podman-network-rm.1.md
Normal file
25
docs/podman-network-rm.1.md
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
% podman-network-rm(1)
|
||||||
|
|
||||||
|
## NAME
|
||||||
|
podman\-network-rm- Delete a Podman CNI network
|
||||||
|
|
||||||
|
## SYNOPSIS
|
||||||
|
**podman network rm** [*network...*]
|
||||||
|
|
||||||
|
## DESCRIPTION
|
||||||
|
Delete one or more Podman networks.
|
||||||
|
|
||||||
|
## EXAMPLE
|
||||||
|
|
||||||
|
Delete the `podman9` network
|
||||||
|
|
||||||
|
```
|
||||||
|
# podman network rm podman
|
||||||
|
Deleted: podman9
|
||||||
|
```
|
||||||
|
|
||||||
|
## SEE ALSO
|
||||||
|
podman(1), podman-network(1), podman-network-inspect(1)
|
||||||
|
|
||||||
|
## HISTORY
|
||||||
|
August 2019, Originally compiled by Brent Baude <bbaude@redhat.com>
|
21
docs/podman-network.1.md
Normal file
21
docs/podman-network.1.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
% podman-network(1)
|
||||||
|
|
||||||
|
## NAME
|
||||||
|
podman\-network- Manage podman CNI networks
|
||||||
|
|
||||||
|
## SYNOPSIS
|
||||||
|
**podman network** *subcommand*
|
||||||
|
|
||||||
|
## DESCRIPTION
|
||||||
|
The network command manages CNI networks for Podman. It is not supported for rootless users.
|
||||||
|
|
||||||
|
## COMMANDS
|
||||||
|
|
||||||
|
| Command | Man Page | Description |
|
||||||
|
| ------- | --------------------------------------------------- | ---------------------------------------------------------------------------- |
|
||||||
|
| inspect | [podman-network-inspect(1)](podman-network-inspect.1.md)| Displays the raw CNI network configuration for one or more networks|
|
||||||
|
| ls | [podman-network-ls(1)](podman-network-ls.1.md)| Display a summary of CNI networks |
|
||||||
|
| rm | [podman-network-rm(1)](podman-network-rm.1.md)| Remove one or more CNI networks |
|
||||||
|
|
||||||
|
## SEE ALSO
|
||||||
|
podman(1)
|
@ -161,6 +161,7 @@ the exit codes follow the `chroot` standard, see below:
|
|||||||
| [podman-logout(1)](podman-logout.1.md) | Logout of a container registry. |
|
| [podman-logout(1)](podman-logout.1.md) | Logout of a container registry. |
|
||||||
| [podman-logs(1)](podman-logs.1.md) | Display the logs of a container. |
|
| [podman-logs(1)](podman-logs.1.md) | Display the logs of a container. |
|
||||||
| [podman-mount(1)](podman-mount.1.md) | Mount a working container's root filesystem. |
|
| [podman-mount(1)](podman-mount.1.md) | Mount a working container's root filesystem. |
|
||||||
|
| [podman-network(1)](podman-network.1.md) | Manage Podman CNI networks. |
|
||||||
| [podman-pause(1)](podman-pause.1.md) | Pause one or more containers. |
|
| [podman-pause(1)](podman-pause.1.md) | Pause one or more containers. |
|
||||||
| [podman-play(1)](podman-play.1.md) | Play pods and containers based on a structured input file. |
|
| [podman-play(1)](podman-play.1.md) | Play pods and containers based on a structured input file. |
|
||||||
| [podman-pod(1)](podman-pod.1.md) | Management tool for groups of containers, called pods. |
|
| [podman-pod(1)](podman-pod.1.md) | Management tool for groups of containers, called pods. |
|
||||||
|
147
pkg/adapter/network.go
Normal file
147
pkg/adapter/network.go
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
// +build !remoteclient
|
||||||
|
|
||||||
|
package adapter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"text/tabwriter"
|
||||||
|
|
||||||
|
"github.com/containernetworking/cni/libcni"
|
||||||
|
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||||
|
"github.com/containers/libpod/pkg/network"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getCNIConfDir(r *LocalRuntime) (string, error) {
|
||||||
|
config, err := r.GetConfig()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
configPath := config.CNIConfigDir
|
||||||
|
|
||||||
|
if len(config.CNIConfigDir) < 1 {
|
||||||
|
configPath = network.CNIConfigDir
|
||||||
|
}
|
||||||
|
return configPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkList displays summary information about CNI networks
|
||||||
|
func (r *LocalRuntime) NetworkList(cli *cliconfig.NetworkListValues) error {
|
||||||
|
cniConfigPath, err := getCNIConfDir(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
networks, err := network.LoadCNIConfsFromDir(cniConfigPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// quiet means we only print the network names
|
||||||
|
if cli.Quiet {
|
||||||
|
for _, cniNetwork := range networks {
|
||||||
|
fmt.Println(cniNetwork.Name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||||
|
if _, err := fmt.Fprintln(w, "NAME\tVERSION\tPLUGINS"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, cniNetwork := range networks {
|
||||||
|
if _, err := fmt.Fprintf(w, "%s\t%s\t%s\n", cniNetwork.Name, cniNetwork.CNIVersion, getCNIPlugins(cniNetwork)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return w.Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkInspect displays the raw CNI configuration for one
|
||||||
|
// or more CNI networks
|
||||||
|
func (r *LocalRuntime) NetworkInspect(cli *cliconfig.NetworkInspectValues) error {
|
||||||
|
var (
|
||||||
|
rawCNINetworks []map[string]interface{}
|
||||||
|
)
|
||||||
|
cniConfigPath, err := getCNIConfDir(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, name := range cli.InputArgs {
|
||||||
|
b, err := readRawCNIConfByName(name, cniConfigPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rawList := make(map[string]interface{})
|
||||||
|
if err := json.Unmarshal(b, &rawList); err != nil {
|
||||||
|
return fmt.Errorf("error parsing configuration list: %s", err)
|
||||||
|
}
|
||||||
|
rawCNINetworks = append(rawCNINetworks, rawList)
|
||||||
|
}
|
||||||
|
out, err := json.MarshalIndent(rawCNINetworks, "", "\t")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("%s\n", out)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkRemove deletes one or more CNI networks
|
||||||
|
func (r *LocalRuntime) NetworkRemove(cli *cliconfig.NetworkRmValues) error {
|
||||||
|
cniConfigPath, err := getCNIConfDir(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, name := range cli.InputArgs {
|
||||||
|
cniPath, err := getCNIConfigPathByName(name, cniConfigPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := os.Remove(cniPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("Deleted: %s\n", name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getCNIConfigPathByName finds a CNI network by name and
|
||||||
|
// returns its configuration file path
|
||||||
|
func getCNIConfigPathByName(name, cniConfigPath string) (string, error) {
|
||||||
|
files, err := libcni.ConfFiles(cniConfigPath, []string{".conflist"})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
for _, confFile := range files {
|
||||||
|
conf, err := libcni.ConfListFromFile(confFile)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if conf.Name == name {
|
||||||
|
return confFile, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", errors.Errorf("unable to find network configuration for %s", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// readRawCNIConfByName reads the raw CNI configuration for a CNI
|
||||||
|
// network by name
|
||||||
|
func readRawCNIConfByName(name, cniConfigPath string) ([]byte, error) {
|
||||||
|
confFile, err := getCNIConfigPathByName(name, cniConfigPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
b, err := ioutil.ReadFile(confFile)
|
||||||
|
return b, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// getCNIPlugins returns a list of plugins that a given network
|
||||||
|
// has in the form of a string
|
||||||
|
func getCNIPlugins(list *libcni.NetworkConfigList) string {
|
||||||
|
var plugins []string
|
||||||
|
for _, plug := range list.Plugins {
|
||||||
|
plugins = append(plugins, plug.Network.Type)
|
||||||
|
}
|
||||||
|
return strings.Join(plugins, ",")
|
||||||
|
}
|
4
pkg/network/config.go
Normal file
4
pkg/network/config.go
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
package network
|
||||||
|
|
||||||
|
// CNIConfigDir is the path where CNI config files exist
|
||||||
|
const CNIConfigDir = "/etc/cni/net.d"
|
26
pkg/network/network.go
Normal file
26
pkg/network/network.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package network
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/containernetworking/cni/libcni"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LoadCNIConfsFromDir loads all the CNI configurations from a dir
|
||||||
|
func LoadCNIConfsFromDir(dir string) ([]*libcni.NetworkConfigList, error) {
|
||||||
|
var configs []*libcni.NetworkConfigList
|
||||||
|
files, err := libcni.ConfFiles(dir, []string{".conflist"})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sort.Strings(files)
|
||||||
|
|
||||||
|
for _, confFile := range files {
|
||||||
|
conf, err := libcni.ConfListFromFile(confFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
configs = append(configs, conf)
|
||||||
|
}
|
||||||
|
return configs, nil
|
||||||
|
}
|
158
test/e2e/network_test.go
Normal file
158
test/e2e/network_test.go
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
// +build !remoteclient
|
||||||
|
|
||||||
|
package integration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
. "github.com/containers/libpod/test/utils"
|
||||||
|
"github.com/containers/storage/pkg/stringid"
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
func writeConf(conf []byte, confPath string) {
|
||||||
|
if err := ioutil.WriteFile(confPath, conf, 777); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func removeConf(confPath string) {
|
||||||
|
if err := os.Remove(confPath); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = Describe("Podman network", func() {
|
||||||
|
var (
|
||||||
|
tempdir string
|
||||||
|
err error
|
||||||
|
podmanTest *PodmanTestIntegration
|
||||||
|
)
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
tempdir, err = CreateTempDirInTempDir()
|
||||||
|
if err != nil {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
podmanTest = PodmanTestCreate(tempdir)
|
||||||
|
podmanTest.Setup()
|
||||||
|
})
|
||||||
|
|
||||||
|
AfterEach(func() {
|
||||||
|
podmanTest.Cleanup()
|
||||||
|
f := CurrentGinkgoTestDescription()
|
||||||
|
processTestResult(f)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
var (
|
||||||
|
secondConf = `{
|
||||||
|
"cniVersion": "0.3.0",
|
||||||
|
"name": "podman-integrationtest",
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"type": "bridge",
|
||||||
|
"bridge": "cni1",
|
||||||
|
"isGateway": true,
|
||||||
|
"ipMasq": true,
|
||||||
|
"ipam": {
|
||||||
|
"type": "host-local",
|
||||||
|
"subnet": "10.99.0.0/16",
|
||||||
|
"routes": [
|
||||||
|
{ "dst": "0.0.0.0/0" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "portmap",
|
||||||
|
"capabilities": {
|
||||||
|
"portMappings": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
cniPath = "/etc/cni/net.d"
|
||||||
|
)
|
||||||
|
|
||||||
|
It("podman network list", func() {
|
||||||
|
SkipIfRootless()
|
||||||
|
// Setup, use uuid to prevent conflict with other tests
|
||||||
|
uuid := stringid.GenerateNonCryptoID()
|
||||||
|
secondPath := filepath.Join(cniPath, fmt.Sprintf("%s.conflist", uuid))
|
||||||
|
writeConf([]byte(secondConf), secondPath)
|
||||||
|
defer removeConf(secondPath)
|
||||||
|
|
||||||
|
session := podmanTest.Podman([]string{"network", "ls"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
Expect(session.LineInOutputContains("podman-integrationtest")).To(BeTrue())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("podman network list -q", func() {
|
||||||
|
SkipIfRootless()
|
||||||
|
// Setup, use uuid to prevent conflict with other tests
|
||||||
|
uuid := stringid.GenerateNonCryptoID()
|
||||||
|
secondPath := filepath.Join(cniPath, fmt.Sprintf("%s.conflist", uuid))
|
||||||
|
writeConf([]byte(secondConf), secondPath)
|
||||||
|
defer removeConf(secondPath)
|
||||||
|
|
||||||
|
session := podmanTest.Podman([]string{"network", "ls", "--quiet"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
Expect(session.LineInOutputContains("podman-integrationtest")).To(BeTrue())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("podman network rm no args", func() {
|
||||||
|
SkipIfRootless()
|
||||||
|
session := podmanTest.Podman([]string{"network", "rm"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).ToNot(BeZero())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("podman network rm", func() {
|
||||||
|
SkipIfRootless()
|
||||||
|
// Setup, use uuid to prevent conflict with other tests
|
||||||
|
uuid := stringid.GenerateNonCryptoID()
|
||||||
|
secondPath := filepath.Join(cniPath, fmt.Sprintf("%s.conflist", uuid))
|
||||||
|
writeConf([]byte(secondConf), secondPath)
|
||||||
|
defer removeConf(secondPath)
|
||||||
|
|
||||||
|
session := podmanTest.Podman([]string{"network", "ls", "--quiet"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
Expect(session.LineInOutputContains("podman-integrationtest")).To(BeTrue())
|
||||||
|
|
||||||
|
rm := podmanTest.Podman([]string{"network", "rm", "podman-integrationtest"})
|
||||||
|
rm.WaitWithDefaultTimeout()
|
||||||
|
Expect(rm.ExitCode()).To(BeZero())
|
||||||
|
|
||||||
|
results := podmanTest.Podman([]string{"network", "ls", "--quiet"})
|
||||||
|
results.WaitWithDefaultTimeout()
|
||||||
|
Expect(results.ExitCode()).To(Equal(0))
|
||||||
|
Expect(results.LineInOutputContains("podman-integrationtest")).To(BeFalse())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("podman network inspect no args", func() {
|
||||||
|
SkipIfRootless()
|
||||||
|
session := podmanTest.Podman([]string{"network", "inspect"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).ToNot(BeZero())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("podman network inspect", func() {
|
||||||
|
SkipIfRootless()
|
||||||
|
// Setup, use uuid to prevent conflict with other tests
|
||||||
|
uuid := stringid.GenerateNonCryptoID()
|
||||||
|
secondPath := filepath.Join(cniPath, fmt.Sprintf("%s.conflist", uuid))
|
||||||
|
writeConf([]byte(secondConf), secondPath)
|
||||||
|
defer removeConf(secondPath)
|
||||||
|
|
||||||
|
session := podmanTest.Podman([]string{"network", "inspect", "podman-integrationtest", "podman"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
Expect(session.IsJSONOutputValid()).To(BeTrue())
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
Reference in New Issue
Block a user