mirror of
https://github.com/containers/podman.git
synced 2025-10-25 02:04:43 +08:00
podman network label support
Add label support for podman network create. Use the `args` field in the cni config file to store the podman labels. Use `podman_labels` as key name and store the labels as map[string]string. For reference: https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md#args-in-network-config https://github.com/containernetworking/cni/blob/spec-v0.4.0/SPEC.md#network-configuration Example snippet: ``` ... "args": { "podman_labels": { "key1":"value1", "key2":"value2" } } ... ``` Make podman network list support several filters. Supported filters are name, plugin, driver and label. Filters with different keys work exclusive. Several label filters work exclusive and the other filter keys are working inclusive. Also adjust the compat api to support labels in network create and list. Breaking changes: - podman network ls -f shortform is used for --filter instead --format This matches docker and other podman commands (container ps, volume ps) - libpod network list endpoint filter parameter is removed. Instead the filters paramter should be used as json encoded map[string][]string. Signed-off-by: Paul Holzinger <paul.holzinger@web.de>
This commit is contained in:
@ -169,7 +169,7 @@ func createBridge(name string, options entities.NetworkCreateOptions, runtimeCon
|
||||
}
|
||||
|
||||
// create CNI plugin configuration
|
||||
ncList := NewNcList(name, version.Current())
|
||||
ncList := NewNcList(name, version.Current(), options.Labels)
|
||||
var plugins []CNIPlugins
|
||||
// TODO need to iron out the role of isDefaultGW and IPMasq
|
||||
bridge := NewHostLocalBridge(bridgeDeviceName, isGateway, false, ipMasq, ipamConfig)
|
||||
@ -223,7 +223,7 @@ func createMacVLAN(name string, options entities.NetworkCreateOptions, runtimeCo
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
ncList := NewNcList(name, version.Current())
|
||||
ncList := NewNcList(name, version.Current(), options.Labels)
|
||||
macvlan := NewMacVLANPlugin(options.MacVLAN)
|
||||
plugins = append(plugins, macvlan)
|
||||
ncList["plugins"] = plugins
|
||||
|
||||
@ -12,6 +12,7 @@ import (
|
||||
"github.com/containers/common/pkg/config"
|
||||
"github.com/containers/podman/v2/libpod/define"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// GetCNIConfDir get CNI configuration directory
|
||||
@ -86,6 +87,35 @@ func GetCNIPlugins(list *libcni.NetworkConfigList) string {
|
||||
return strings.Join(plugins, ",")
|
||||
}
|
||||
|
||||
// GetNetworkLabels returns a list of labels as a string
|
||||
func GetNetworkLabels(list *libcni.NetworkConfigList) NcLabels {
|
||||
cniJSON := make(map[string]interface{})
|
||||
err := json.Unmarshal(list.Bytes, &cniJSON)
|
||||
if err != nil {
|
||||
logrus.Errorf("failed to unmarshal network config %v %v", cniJSON["name"], err)
|
||||
return nil
|
||||
}
|
||||
if args, ok := cniJSON["args"]; ok {
|
||||
if key, ok := args.(map[string]interface{}); ok {
|
||||
if labels, ok := key[PodmanLabelKey]; ok {
|
||||
if labels, ok := labels.(map[string]interface{}); ok {
|
||||
result := make(NcLabels, len(labels))
|
||||
for k, v := range labels {
|
||||
if v, ok := v.(string); ok {
|
||||
result[k] = v
|
||||
} else {
|
||||
logrus.Errorf("network config %v invalid label value type %T should be string", cniJSON["name"], labels)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
logrus.Errorf("network config %v invalid label type %T should be map[string]string", cniJSON["name"], labels)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetNetworksFromFilesystem gets all the networks from the cni configuration
|
||||
// files
|
||||
func GetNetworksFromFilesystem(config *config.Config) ([]*allocator.Net, error) {
|
||||
|
||||
@ -4,6 +4,11 @@ import (
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/containernetworking/cni/libcni"
|
||||
"github.com/containers/podman/v2/pkg/util"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -14,12 +19,24 @@ const (
|
||||
// NcList describes a generic map
|
||||
type NcList map[string]interface{}
|
||||
|
||||
// NcArgs describes the cni args field
|
||||
type NcArgs map[string]NcLabels
|
||||
|
||||
// NcLabels describes the label map
|
||||
type NcLabels map[string]string
|
||||
|
||||
// PodmanLabelKey key used to store the podman network label in a cni config
|
||||
const PodmanLabelKey = "podman_labels"
|
||||
|
||||
// NewNcList creates a generic map of values with string
|
||||
// keys and adds in version and network name
|
||||
func NewNcList(name, version string) NcList {
|
||||
func NewNcList(name, version string, labels NcLabels) NcList {
|
||||
n := NcList{}
|
||||
n["cniVersion"] = version
|
||||
n["name"] = name
|
||||
if len(labels) > 0 {
|
||||
n["args"] = NcArgs{PodmanLabelKey: labels}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
@ -159,3 +176,64 @@ func NewMacVLANPlugin(device string) MacVLANConfig {
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// IfPassesFilter filters NetworkListReport and returns true if the filter match the given config
|
||||
func IfPassesFilter(netconf *libcni.NetworkConfigList, filters map[string][]string) (bool, error) {
|
||||
result := true
|
||||
for key, filterValues := range filters {
|
||||
result = false
|
||||
switch strings.ToLower(key) {
|
||||
case "name":
|
||||
// matches one name, regex allowed
|
||||
result = util.StringMatchRegexSlice(netconf.Name, filterValues)
|
||||
|
||||
case "plugin":
|
||||
// match one plugin
|
||||
plugins := GetCNIPlugins(netconf)
|
||||
for _, val := range filterValues {
|
||||
if strings.Contains(plugins, val) {
|
||||
result = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
case "label":
|
||||
// matches all labels
|
||||
labels := GetNetworkLabels(netconf)
|
||||
outer:
|
||||
for _, filterValue := range filterValues {
|
||||
filterArray := strings.SplitN(filterValue, "=", 2)
|
||||
filterKey := filterArray[0]
|
||||
if len(filterArray) > 1 {
|
||||
filterValue = filterArray[1]
|
||||
} else {
|
||||
filterValue = ""
|
||||
}
|
||||
for labelKey, labelValue := range labels {
|
||||
if labelKey == filterKey && ("" == filterValue || labelValue == filterValue) {
|
||||
result = true
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
result = false
|
||||
}
|
||||
|
||||
case "driver":
|
||||
// matches only for the DefaultNetworkDriver
|
||||
for _, filterValue := range filterValues {
|
||||
plugins := GetCNIPlugins(netconf)
|
||||
if filterValue == DefaultNetworkDriver &&
|
||||
strings.Contains(plugins, DefaultNetworkDriver) {
|
||||
result = true
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: add dangling filter
|
||||
// TODO TODO: add id filter if we support ids
|
||||
|
||||
default:
|
||||
return false, errors.Errorf("invalid filter %q", key)
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user