summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/networks/list.go11
-rw-r--r--docs/source/markdown/podman-network-ls.1.md31
-rw-r--r--libpod/network/files.go18
-rw-r--r--libpod/network/netconflist.go10
-rw-r--r--libpod/network/network.go11
-rw-r--r--pkg/api/handlers/compat/networks.go14
-rw-r--r--pkg/api/server/register_networks.go2
-rw-r--r--test/apiv2/35-networks.at16
-rw-r--r--test/e2e/network_test.go34
9 files changed, 124 insertions, 23 deletions
diff --git a/cmd/podman/networks/list.go b/cmd/podman/networks/list.go
index 6e6bbb07d..16ae980dc 100644
--- a/cmd/podman/networks/list.go
+++ b/cmd/podman/networks/list.go
@@ -37,6 +37,7 @@ var (
var (
networkListOptions entities.NetworkListOptions
filters []string
+ noTrunc bool
)
func networkListFlags(flags *pflag.FlagSet) {
@@ -45,6 +46,7 @@ func networkListFlags(flags *pflag.FlagSet) {
_ = networklistCommand.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteJSONFormat)
flags.BoolVarP(&networkListOptions.Quiet, "quiet", "q", false, "display only names")
+ flags.BoolVar(&noTrunc, "no-trunc", false, "Do not truncate the network ID")
filterFlagName := "filter"
flags.StringArrayVarP(&filters, filterFlagName, "f", nil, "Provide filter values (e.g. 'name=podman')")
@@ -96,6 +98,7 @@ func networkList(cmd *cobra.Command, args []string) error {
"Version": "version",
"Plugins": "plugins",
"Labels": "labels",
+ "ID": "network id",
})
renderHeaders := true
row := "{{.Name}}\t{{.Version}}\t{{.Plugins}}\n"
@@ -155,3 +158,11 @@ func (n ListPrintReports) Labels() string {
}
return strings.Join(list, ",")
}
+
+func (n ListPrintReports) ID() string {
+ length := 12
+ if noTrunc {
+ length = 64
+ }
+ return network.GetNetworkID(n.Name)[:length]
+}
diff --git a/docs/source/markdown/podman-network-ls.1.md b/docs/source/markdown/podman-network-ls.1.md
index fcba51190..a964c97e8 100644
--- a/docs/source/markdown/podman-network-ls.1.md
+++ b/docs/source/markdown/podman-network-ls.1.md
@@ -10,14 +10,6 @@ podman\-network\-ls - Display a summary of CNI networks
Displays a list of existing podman networks. This command is not available for rootless users.
## OPTIONS
-#### **--quiet**, **-q**
-
-The `quiet` option will restrict the output to only the network names.
-
-#### **--format**
-
-Pretty-print networks to JSON or using a Go template.
-
#### **--filter**, **-f**
Filter output based on conditions given.
@@ -30,10 +22,33 @@ Valid filters are listed below:
| **Filter** | **Description** |
| ---------- | ------------------------------------------------------------------------------------- |
| name | [Name] Network name (accepts regex) |
+| id | [ID] Full or partial network ID |
| label | [Key] or [Key=Value] Label assigned to a network |
| plugin | [Plugin] CNI plugins included in a network (e.g `bridge`,`portmap`,`firewall`,`tuning`,`dnsname`,`macvlan`) |
| driver | [Driver] Only `bridge` is supported |
+#### **--format**
+
+Change the default output format. This can be of a supported type like 'json'
+or a Go template.
+Valid placeholders for the Go template are listed below:
+
+| **Placeholder** | **Description** |
+| --------------- | --------------------------------|
+| .ID | Network ID |
+| .Name | Network name |
+| .Plugins | Network Plugins |
+| .Labels | Network labels |
+| .Version | CNI Version of the config file |
+
+#### **--no-trunc**
+
+Do not truncate the network ID. The network ID is not displayed by default and must be specified with **--format**.
+
+#### **--quiet**, **-q**
+
+The `quiet` option will restrict the output to only the network names.
+
## EXAMPLE
Display networks
diff --git a/libpod/network/files.go b/libpod/network/files.go
index 83cb1c23a..33cf01064 100644
--- a/libpod/network/files.go
+++ b/libpod/network/files.go
@@ -50,13 +50,15 @@ func LoadCNIConfsFromDir(dir string) ([]*libcni.NetworkConfigList, error) {
return configs, nil
}
-// GetCNIConfigPathByName finds a CNI network by name and
+// GetCNIConfigPathByNameOrID finds a CNI network by name and
// returns its configuration file path
-func GetCNIConfigPathByName(config *config.Config, name string) (string, error) {
+func GetCNIConfigPathByNameOrID(config *config.Config, name string) (string, error) {
files, err := libcni.ConfFiles(GetCNIConfDir(config), []string{".conflist"})
if err != nil {
return "", err
}
+ idMatch := 0
+ file := ""
for _, confFile := range files {
conf, err := libcni.ConfListFromFile(confFile)
if err != nil {
@@ -65,6 +67,16 @@ func GetCNIConfigPathByName(config *config.Config, name string) (string, error)
if conf.Name == name {
return confFile, nil
}
+ if strings.HasPrefix(GetNetworkID(conf.Name), name) {
+ idMatch++
+ file = confFile
+ }
+ }
+ if idMatch == 1 {
+ return file, nil
+ }
+ if idMatch > 1 {
+ return "", errors.Errorf("more than one result for network ID %s", name)
}
return "", errors.Wrap(define.ErrNoSuchNetwork, fmt.Sprintf("unable to find network configuration for %s", name))
}
@@ -72,7 +84,7 @@ func GetCNIConfigPathByName(config *config.Config, name string) (string, error)
// ReadRawCNIConfByName reads the raw CNI configuration for a CNI
// network by name
func ReadRawCNIConfByName(config *config.Config, name string) ([]byte, error) {
- confFile, err := GetCNIConfigPathByName(config, name)
+ confFile, err := GetCNIConfigPathByNameOrID(config, name)
if err != nil {
return nil, err
}
diff --git a/libpod/network/netconflist.go b/libpod/network/netconflist.go
index a5fec5e80..d61b96ecb 100644
--- a/libpod/network/netconflist.go
+++ b/libpod/network/netconflist.go
@@ -230,8 +230,16 @@ func IfPassesFilter(netconf *libcni.NetworkConfigList, filters map[string][]stri
}
}
+ case "id":
+ // matches part of one id
+ for _, filterValue := range filterValues {
+ if strings.Contains(GetNetworkID(netconf.Name), filterValue) {
+ result = true
+ break
+ }
+ }
+
// TODO: add dangling filter
- // TODO TODO: add id filter if we support ids
default:
return false, errors.Errorf("invalid filter %q", key)
diff --git a/libpod/network/network.go b/libpod/network/network.go
index 0febb52f6..89f0b67ac 100644
--- a/libpod/network/network.go
+++ b/libpod/network/network.go
@@ -1,6 +1,8 @@
package network
import (
+ "crypto/sha256"
+ "encoding/hex"
"encoding/json"
"net"
"os"
@@ -175,7 +177,7 @@ func RemoveNetwork(config *config.Config, name string) error {
return err
}
defer l.releaseCNILock()
- cniPath, err := GetCNIConfigPathByName(config, name)
+ cniPath, err := GetCNIConfigPathByNameOrID(config, name)
if err != nil {
return err
}
@@ -229,3 +231,10 @@ func Exists(config *config.Config, name string) (bool, error) {
}
return true, nil
}
+
+// GetNetworkID return the network ID for a given name.
+// It is just the sha256 hash but this should be good enough.
+func GetNetworkID(name string) string {
+ hash := sha256.Sum256([]byte(name))
+ return hex.EncodeToString(hash[:])
+}
diff --git a/pkg/api/handlers/compat/networks.go b/pkg/api/handlers/compat/networks.go
index 762f88a68..b4f3aa2f1 100644
--- a/pkg/api/handlers/compat/networks.go
+++ b/pkg/api/handlers/compat/networks.go
@@ -50,7 +50,7 @@ func InspectNetwork(w http.ResponseWriter, r *http.Request) {
utils.NetworkNotFound(w, name, err)
return
}
- report, err := getNetworkResourceByName(name, runtime, nil)
+ report, err := getNetworkResourceByNameOrID(name, runtime, nil)
if err != nil {
utils.InternalServerError(w, err)
return
@@ -58,7 +58,7 @@ func InspectNetwork(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusOK, report)
}
-func getNetworkResourceByName(name string, runtime *libpod.Runtime, filters map[string][]string) (*types.NetworkResource, error) {
+func getNetworkResourceByNameOrID(nameOrID string, runtime *libpod.Runtime, filters map[string][]string) (*types.NetworkResource, error) {
var (
ipamConfigs []dockerNetwork.IPAMConfig
)
@@ -68,7 +68,7 @@ func getNetworkResourceByName(name string, runtime *libpod.Runtime, filters map[
}
containerEndpoints := map[string]types.EndpointResource{}
// Get the network path so we can get created time
- networkConfigPath, err := network.GetCNIConfigPathByName(config, name)
+ networkConfigPath, err := network.GetCNIConfigPathByNameOrID(config, nameOrID)
if err != nil {
return nil, err
}
@@ -116,7 +116,7 @@ func getNetworkResourceByName(name string, runtime *libpod.Runtime, filters map[
if err != nil {
return nil, err
}
- if netData, ok := data.NetworkSettings.Networks[name]; ok {
+ if netData, ok := data.NetworkSettings.Networks[conf.Name]; ok {
containerEndpoint := types.EndpointResource{
Name: netData.NetworkID,
EndpointID: netData.EndpointID,
@@ -128,8 +128,8 @@ func getNetworkResourceByName(name string, runtime *libpod.Runtime, filters map[
}
}
report := types.NetworkResource{
- Name: name,
- ID: name,
+ Name: conf.Name,
+ ID: network.GetNetworkID(conf.Name),
Created: time.Unix(int64(stat.Ctim.Sec), int64(stat.Ctim.Nsec)), // nolint: unconvert
Scope: "",
Driver: network.DefaultNetworkDriver,
@@ -199,7 +199,7 @@ func ListNetworks(w http.ResponseWriter, r *http.Request) {
var reports []*types.NetworkResource
logrus.Errorf("netNames: %q", strings.Join(netNames, ", "))
for _, name := range netNames {
- report, err := getNetworkResourceByName(name, runtime, query.Filters)
+ report, err := getNetworkResourceByNameOrID(name, runtime, query.Filters)
if err != nil {
utils.InternalServerError(w, err)
return
diff --git a/pkg/api/server/register_networks.go b/pkg/api/server/register_networks.go
index 193b05e6d..e6c85d244 100644
--- a/pkg/api/server/register_networks.go
+++ b/pkg/api/server/register_networks.go
@@ -68,6 +68,7 @@ func (s *APIServer) registerNetworkHandlers(r *mux.Router) error {
// description: |
// JSON encoded value of the filters (a map[string][]string) to process on the network list. Currently available filters:
// - name=[name] Matches network name (accepts regex).
+ // - id=[id] Matches for full or partial ID.
// - driver=[driver] Only bridge is supported.
// - label=[key] or label=[key=value] Matches networks based on the presence of a label alone or a label and a value.
// produces:
@@ -225,6 +226,7 @@ func (s *APIServer) registerNetworkHandlers(r *mux.Router) error {
// description: |
// JSON encoded value of the filters (a map[string][]string) to process on the network list. Available filters:
// - name=[name] Matches network name (accepts regex).
+ // - id=[id] Matches for full or partial ID.
// - driver=[driver] Only bridge is supported.
// - label=[key] or label=[key=value] Matches networks based on the presence of a label alone or a label and a value.
// - plugin=[plugin] Matches CNI plugins included in a network (e.g `bridge`,`portmap`,`firewall`,`tuning`,`dnsname`,`macvlan`)
diff --git a/test/apiv2/35-networks.at b/test/apiv2/35-networks.at
index d9556d59f..0ce56ee3c 100644
--- a/test/apiv2/35-networks.at
+++ b/test/apiv2/35-networks.at
@@ -38,9 +38,19 @@ length=2
# filters={"label":["abc"]}
t GET networks?filters=%7B%22label%22%3A%5B%22abc%22%5D%7D 200 \
length=1
-# invalid filter filters={"id":["abc"]}
-t GET networks?filters=%7B%22id%22%3A%5B%22abc%22%5D%7D 500 \
-.cause='invalid filter "id"'
+# id filter filters={"id":["a7662f44d65029fd4635c91feea3d720a57cef52e2a9fcc7772b69072cc1ccd1"]}
+t GET networks?filters=%7B%22id%22%3A%5B%22a7662f44d65029fd4635c91feea3d720a57cef52e2a9fcc7772b69072cc1ccd1%22%5D%7D 200 \
+length=1 \
+.[0].Name=network1 \
+.[0].Id=a7662f44d65029fd4635c91feea3d720a57cef52e2a9fcc7772b69072cc1ccd1
+# invalid filter filters={"dangling":["1"]}
+t GET networks?filters=%7B%22dangling%22%3A%5B%221%22%5D%7D 500 \
+.cause='invalid filter "dangling"'
+
+# network inspect docker
+t GET networks/a7662f44d65029fd4635c91feea3d720a57cef52e2a9fcc7772b69072cc1ccd1 200 \
+.Name=network1 \
+.Id=a7662f44d65029fd4635c91feea3d720a57cef52e2a9fcc7772b69072cc1ccd1
# clean the network
t DELETE libpod/networks/network1 200 \
diff --git a/test/e2e/network_test.go b/test/e2e/network_test.go
index ad6af61c7..ffc914bc2 100644
--- a/test/e2e/network_test.go
+++ b/test/e2e/network_test.go
@@ -135,6 +135,40 @@ var _ = Describe("Podman network", func() {
Expect(session.LineInOutputContains(name)).To(BeFalse())
})
+ It("podman network ID test", func() {
+ net := "networkIDTest"
+ // the network id should be the sha256 hash of the network name
+ netID := "6073aefe03cdf8f29be5b23ea9795c431868a3a22066a6290b187691614fee84"
+ session := podmanTest.Podman([]string{"network", "create", net})
+ session.WaitWithDefaultTimeout()
+ defer podmanTest.removeCNINetwork(net)
+ Expect(session.ExitCode()).To(BeZero())
+
+ session = podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}} {{.ID}}", "--filter", "id=" + netID})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ Expect(session.OutputToString()).To(ContainSubstring(net + " " + netID[:12]))
+
+ session = podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}} {{.ID}}", "--filter", "id=" + netID[10:50], "--no-trunc"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ Expect(session.OutputToString()).To(ContainSubstring(net + " " + netID))
+
+ session = podmanTest.Podman([]string{"network", "inspect", netID[:40]})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ Expect(session.OutputToString()).To(ContainSubstring(net))
+
+ session = podmanTest.Podman([]string{"network", "inspect", netID[1:]})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).ToNot(BeZero())
+ Expect(session.ErrorToString()).To(ContainSubstring("no such network"))
+
+ session = podmanTest.Podman([]string{"network", "rm", netID})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ })
+
rm_func := func(rm string) {
It(fmt.Sprintf("podman network %s no args", rm), func() {
session := podmanTest.Podman([]string{"network", rm})