diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/network/create.go | 4 | ||||
-rw-r--r-- | libpod/network/files.go | 30 | ||||
-rw-r--r-- | libpod/network/netconflist.go | 80 | ||||
-rw-r--r-- | libpod/runtime_pod_infra_linux.go | 67 |
4 files changed, 151 insertions, 30 deletions
diff --git a/libpod/network/create.go b/libpod/network/create.go index 7e4fc574a..cac438963 100644 --- a/libpod/network/create.go +++ b/libpod/network/create.go @@ -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 diff --git a/libpod/network/files.go b/libpod/network/files.go index 7f1e3ee18..83cb1c23a 100644 --- a/libpod/network/files.go +++ b/libpod/network/files.go @@ -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" ) // ErrNoSuchNetworkInterface indicates that no network interface exists @@ -89,6 +90,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) { diff --git a/libpod/network/netconflist.go b/libpod/network/netconflist.go index ee9adce14..3db38485b 100644 --- a/libpod/network/netconflist.go +++ b/libpod/network/netconflist.go @@ -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 +} diff --git a/libpod/runtime_pod_infra_linux.go b/libpod/runtime_pod_infra_linux.go index 76419587a..3e4185db1 100644 --- a/libpod/runtime_pod_infra_linux.go +++ b/libpod/runtime_pod_infra_linux.go @@ -34,40 +34,56 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm // Set Pod hostname g.Config.Hostname = p.config.Hostname + var options []CtrCreateOption + + // Command: If user-specified, use that preferentially. + // If not set and the config file is set, fall back to that. + var infraCtrCommand []string + if p.config.InfraContainer.InfraCommand != nil { + logrus.Debugf("User-specified infra container entrypoint %v", p.config.InfraContainer.InfraCommand) + infraCtrCommand = p.config.InfraContainer.InfraCommand + } else if r.config.Engine.InfraCommand != "" { + logrus.Debugf("Config-specified infra container entrypoint %s", r.config.Engine.InfraCommand) + infraCtrCommand = []string{r.config.Engine.InfraCommand} + } + // Only if set by the user or containers.conf, we set entrypoint for the + // infra container. + // This is only used by commit, so it shouldn't matter... But someone + // may eventually want to commit an infra container? + // TODO: Should we actually do this if set by containers.conf? + if infraCtrCommand != nil { + // Need to duplicate the array - we are going to add Cmd later + // so the current array will be changed. + newArr := make([]string, 0, len(infraCtrCommand)) + newArr = append(newArr, infraCtrCommand...) + options = append(options, WithEntrypoint(newArr)) + } + isRootless := rootless.IsRootless() - entrypointSet := len(p.config.InfraContainer.InfraCommand) > 0 - entryPoint := p.config.InfraContainer.InfraCommand - entryCmd := []string{} - var options []CtrCreateOption // I've seen circumstances where config is being passed as nil. // Let's err on the side of safety and make sure it's safe to use. if config != nil { - // default to entrypoint in image if there is one - if !entrypointSet { - if len(config.Entrypoint) > 0 { - entrypointSet = true - entryPoint = config.Entrypoint - entryCmd = config.Entrypoint + if infraCtrCommand == nil { + // If we have no entrypoint and command from the image, + // we can't go on - the infra container has no command. + if len(config.Entrypoint) == 0 && len(config.Cmd) == 0 { + return nil, errors.Errorf("infra container has no command") } - } else { // so use the InfraCommand - entrypointSet = true - entryCmd = entryPoint - } - - if len(config.Cmd) > 0 { - // We can't use the default pause command, since we're - // sourcing from the image. If we didn't already set an - // entrypoint, set one now. - if !entrypointSet { + if len(config.Entrypoint) > 0 { + infraCtrCommand = config.Entrypoint + } else { // Use the Docker default "/bin/sh -c" // entrypoint, as we're overriding command. // If an image doesn't want this, it can // override entrypoint too. - entryCmd = []string{"/bin/sh", "-c"} + infraCtrCommand = []string{"/bin/sh", "-c"} } - entryCmd = append(entryCmd, config.Cmd...) } + if len(config.Cmd) > 0 { + infraCtrCommand = append(infraCtrCommand, config.Cmd...) + } + if len(config.Env) > 0 { for _, nameValPair := range config.Env { nameValSlice := strings.Split(nameValPair, "=") @@ -127,9 +143,9 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm } g.SetRootReadonly(true) - g.SetProcessArgs(entryCmd) + g.SetProcessArgs(infraCtrCommand) - logrus.Debugf("Using %q as infra container entrypoint", entryCmd) + logrus.Debugf("Using %q as infra container command", infraCtrCommand) g.RemoveMount("/dev/shm") if isRootless { @@ -148,9 +164,6 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm options = append(options, WithRootFSFromImage(imgID, imgName, rawImageName)) options = append(options, WithName(containerName)) options = append(options, withIsInfra()) - if entrypointSet { - options = append(options, WithEntrypoint(entryPoint)) - } if len(p.config.InfraContainer.ConmonPidFile) > 0 { options = append(options, WithConmonPidFile(p.config.InfraContainer.ConmonPidFile)) } |