From b63fefe74dbd9cfc11358d95c52e8dcbf0d49ac8 Mon Sep 17 00:00:00 2001 From: Thorsten Klein Date: Thu, 25 Nov 2021 14:23:04 +0100 Subject: [PATCH] [Enhancement] extend usability of nodefilters with suffices internally... (#871) ... and throw error if suffix is used in unsupported cases (e.g. volumes) Note: as of now, only the port config supports nodefilter suffices (proxy, direct) and all the others don't. --- pkg/client/ports.go | 6 +++++- pkg/config/transform.go | 4 ---- pkg/util/filter.go | 24 ++++++++++++++++++------ 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/pkg/client/ports.go b/pkg/client/ports.go index 79067d27..b7e320d8 100644 --- a/pkg/client/ports.go +++ b/pkg/client/ports.go @@ -61,12 +61,16 @@ func TransformPorts(ctx context.Context, runtime runtimes.Runtime, cluster *k3d. } } - filteredNodes, err := util.FilterNodesWithSuffix(nodeList, portWithNodeFilters.NodeFilters) + filteredNodes, err := util.FilterNodesWithSuffix(nodeList, portWithNodeFilters.NodeFilters, "proxy", "direct") // TODO: move "proxy" and "direct" allowed suffices to constants if err != nil { return err } for suffix, nodes := range filteredNodes { + // skip, if no nodes in filtered set, so we don't add portmappings with no targets in the backend + if len(nodes) == 0 { + continue + } portmappings, err := nat.ParsePortSpec(portWithNodeFilters.Port) if err != nil { return fmt.Errorf("error parsing port spec '%s': %+v", portWithNodeFilters.Port, err) diff --git a/pkg/config/transform.go b/pkg/config/transform.go index 92a5211b..07a53839 100644 --- a/pkg/config/transform.go +++ b/pkg/config/transform.go @@ -44,10 +44,6 @@ import ( l "github.com/rancher/k3d/v5/pkg/logger" ) -var ( - DefaultTargetsNodefiltersPortMappings = []string{"servers:*:proxy", "agents:*:proxy"} -) - // TransformSimpleToClusterConfig transforms a simple configuration to a full-fledged cluster configuration func TransformSimpleToClusterConfig(ctx context.Context, runtime runtimes.Runtime, simpleConfig conf.SimpleConfig) (*conf.ClusterConfig, error) { diff --git a/pkg/util/filter.go b/pkg/util/filter.go index 2998ffa4..1aaf668f 100644 --- a/pkg/util/filter.go +++ b/pkg/util/filter.go @@ -50,13 +50,17 @@ var ( var NodeFilterRegexp = regexp.MustCompile(`^(?Pserver|servers|agent|agents|loadbalancer|all)(?P:(?P(?P(\d+,?)+)|(?P\d*-\d*)|(?P\*)))?(?P:(?P[[:alpha:]]+))?$`) // FilterNodesBySuffix properly interprets NodeFilters with suffix -func FilterNodesWithSuffix(nodes []*k3d.Node, nodefilters []string) (map[string][]*k3d.Node, error) { +func FilterNodesWithSuffix(nodes []*k3d.Node, nodefilters []string, allowedSuffices ...string) (map[string][]*k3d.Node, error) { if len(nodefilters) == 0 || len(nodefilters[0]) == 0 { return nil, fmt.Errorf("No nodefilters specified") } result := map[string][]*k3d.Node{ - NodeFilterMapKeyAll: nodes, + NodeFilterMapKeyAll: nodes, + NodeFilterSuffixNone: make([]*k3d.Node, 0), + } + for _, s := range allowedSuffices { + result[s] = make([]*k3d.Node, 0) // init map for this suffix, if not exists } for _, nf := range nodefilters { @@ -66,24 +70,27 @@ func FilterNodesWithSuffix(nodes []*k3d.Node, nodefilters []string) (map[string] match := NodeFilterRegexp.FindStringSubmatch(nf) if len(match) == 0 { - return nil, fmt.Errorf("Failed to parse node filters: invalid format or empty subset in '%s'", nf) + return nil, fmt.Errorf("Failed to parse node filters (with suffix): invalid format or empty subset in '%s'", nf) } // map capturing group names to submatches submatches := MapSubexpNames(NodeFilterRegexp.SubexpNames(), match) // get suffix + cleanedNf := nf if sf, ok := submatches["suffix"]; ok && sf != "" { suffix = sf + cleanedNf = strings.TrimSuffix(nf, submatches["suffixSpec"]) } + // suffix not in result map, meaning, that it's also not allowed if _, ok := result[suffix]; !ok { - result[suffix] = make([]*k3d.Node, 0) // init map for this suffix, if not exists + return nil, fmt.Errorf("error filtering nodes: unallowed suffix '%s' in nodefilter '%s'", suffix, nf) } - filteredNodes, err := FilterNodes(nodes, []string{nf}) + filteredNodes, err := FilterNodes(nodes, []string{cleanedNf}) if err != nil { - return nil, fmt.Errorf("failed to filder nodes by filter '%s': %w", nf, err) + return nil, fmt.Errorf("failed to filter nodes by filter '%s': %w", nf, err) } l.Log().Tracef("Filtered %d nodes for suffix '%s' (filter: %s)", len(filteredNodes), suffix, nf) @@ -134,6 +141,11 @@ func FilterNodes(nodes []*k3d.Node, filters []string) ([]*k3d.Node, error) { // map capturing group names to submatches submatches := MapSubexpNames(NodeFilterRegexp.SubexpNames(), match) + // error out if filter is specified (should only work in FilterNodesWithSuffix) + if sf, ok := submatches["suffix"]; ok && sf != "" { + return nil, fmt.Errorf("error filtering with '%s': no suffix allowed in simple filter", filter) + } + // if one of the filters is 'all', we only return this and drop all others if submatches["group"] == "all" { if len(filters) > 1 {