From 6220ef1488d3e135c332c265fdb6a3c7b240b561 Mon Sep 17 00:00:00 2001
From: baude <bbaude@redhat.com>
Date: Wed, 3 Jul 2019 19:21:38 -0500
Subject: 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>
---
 pkg/adapter/network.go | 147 +++++++++++++++++++++++++++++++++++++++++++++++++
 pkg/network/config.go  |   4 ++
 pkg/network/network.go |  26 +++++++++
 3 files changed, 177 insertions(+)
 create mode 100644 pkg/adapter/network.go
 create mode 100644 pkg/network/config.go
 create mode 100644 pkg/network/network.go

(limited to 'pkg')

diff --git a/pkg/adapter/network.go b/pkg/adapter/network.go
new file mode 100644
index 000000000..cf3a1dfdd
--- /dev/null
+++ b/pkg/adapter/network.go
@@ -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, ",")
+}
diff --git a/pkg/network/config.go b/pkg/network/config.go
new file mode 100644
index 000000000..d282f66b6
--- /dev/null
+++ b/pkg/network/config.go
@@ -0,0 +1,4 @@
+package network
+
+// CNIConfigDir is the path where CNI config files exist
+const CNIConfigDir = "/etc/cni/net.d"
diff --git a/pkg/network/network.go b/pkg/network/network.go
new file mode 100644
index 000000000..9d04340a3
--- /dev/null
+++ b/pkg/network/network.go
@@ -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
+}
-- 
cgit v1.2.3-54-g00ecf