diff --git a/cmd/create/createCluster.go b/cmd/create/createCluster.go index 3bf0fdd8..288ac63c 100644 --- a/cmd/create/createCluster.go +++ b/cmd/create/createCluster.go @@ -22,8 +22,6 @@ THE SOFTWARE. package create import ( - "fmt" - "github.com/spf13/cobra" cliutil "github.com/rancher/k3d/cmd/util" @@ -133,11 +131,11 @@ func parseCreateClusterCmd(cmd *cobra.Command, args []string) (runtimes.Runtime, } // volumeFilterMap will map volume mounts to applied node filters - volumeFilterMap := make(map[string]string, 1) + volumeFilterMap := make(map[string][]string, 1) for _, volumeFlag := range volumeFlags { // split node filter from the specified volume - volume, filter, err := cliutil.SplitFilterFromFlag(volumeFlag) + volume, filters, err := cliutil.SplitFiltersFromFlag(volumeFlag) if err != nil { log.Fatalln(err) } @@ -150,9 +148,9 @@ func parseCreateClusterCmd(cmd *cobra.Command, args []string) (runtimes.Runtime, // create new entry or append filter to existing entry if _, exists := volumeFilterMap[volume]; exists { - volumeFilterMap[volume] = fmt.Sprintf("%s;%s", volumeFilterMap[volume], filter) + volumeFilterMap[volume] = append(volumeFilterMap[volume], filters...) } else { - volumeFilterMap[volume] = filter + volumeFilterMap[volume] = filters } } @@ -161,14 +159,20 @@ func parseCreateClusterCmd(cmd *cobra.Command, args []string) (runtimes.Runtime, if err != nil { log.Fatalln(err) } - portFilterMap := make(map[string]string, 1) + portFilterMap := make(map[string][]string, 1) for _, portFlag := range portFlags { // split node filter from the specified volume - portmap, filter, err := cliutil.SplitFilterFromFlag(portFlag) + portmap, filters, err := cliutil.SplitFiltersFromFlag(portFlag) if err != nil { log.Fatalln(err) } + if len(filters) > 1 { + log.Fatalln("Can only apply a Portmap to one node") + } + + // the same portmapping can't be applied to multiple nodes + // validate the specified volume mount and return it in SRC:DEST format portmap, err = cliutil.ValidatePortMap(portmap) if err != nil { @@ -177,9 +181,9 @@ func parseCreateClusterCmd(cmd *cobra.Command, args []string) (runtimes.Runtime, // create new entry or append filter to existing entry if _, exists := portFilterMap[portmap]; exists { - portFilterMap[portmap] = fmt.Sprintf("%s;%s", portFilterMap[portmap], filter) + log.Fatalln("Same Portmapping can not be used for multiple nodes") } else { - portFilterMap[portmap] = filter + portFilterMap[portmap] = filters } } @@ -231,5 +235,16 @@ func parseCreateClusterCmd(cmd *cobra.Command, args []string) (runtimes.Runtime, } } + // append ports + for portmap, filter := range portFilterMap { + nodes, err := cliutil.FilterNodes(cluster.Nodes, filter) + if err != nil { + log.Fatalln(err) + } + for _, node := range nodes { + node.Ports = append(node.Ports, portmap) + } + } + return runtime, cluster } diff --git a/cmd/util/filter.go b/cmd/util/filter.go index 66f90575..a4d77330 100644 --- a/cmd/util/filter.go +++ b/cmd/util/filter.go @@ -36,13 +36,13 @@ import ( // Regexp pattern to match node filters var filterRegexp = regexp.MustCompile(`^(?Pmaster|worker|all)(?P\[(?P(?P(\d+,?)+)|(?P\d*:\d*)|(?P\*))\])?$`) -// SplitFilterFromFlag separates a flag's value from the node filter, if there is one -func SplitFilterFromFlag(flag string) (string, string, error) { +// SplitFiltersFromFlag separates a flag's value from the node filter, if there is one +func SplitFiltersFromFlag(flag string) (string, []string, error) { /* Case 1) no filter specified */ if !strings.Contains(flag, "@") { - return flag, "", nil + return flag, nil, nil } /* Case 2) filter indicated using '@' in flag */ @@ -51,25 +51,22 @@ func SplitFilterFromFlag(flag string) (string, string, error) { // max number of pieces after split = 2 (only one @ allowed in flag) if len(split) > 2 { - return "", "", fmt.Errorf("Invalid flag '%s': only one '@' for node filter allowed", flag) + return "", nil, fmt.Errorf("Invalid flag '%s': only one '@' for node filter allowed", flag) } // trailing or leading '@' if len(split) < 2 { - return "", "", fmt.Errorf("Invalid flag '%s' includes '@' but is missing either an object or a filter", flag) + return "", nil, fmt.Errorf("Invalid flag '%s' includes '@' but is missing either an object or a filter", flag) } - return split[0], split[1], nil + return split[0], strings.Split(split[1], ";"), nil } // FilterNodes takes a string filter to return a filtered list of nodes -func FilterNodes(nodes []*k3d.Node, filterString string) ([]*k3d.Node, error) { +func FilterNodes(nodes []*k3d.Node, filters []string) ([]*k3d.Node, error) { - // filterString is a semicolon-separated list of node filters - filters := strings.Split(filterString, ";") - - if len(filters) == 0 { + if len(filters) == 0 || len(filters[0]) == 0 { log.Warnln("No filter specified") return nodes, nil } @@ -104,7 +101,7 @@ func FilterNodes(nodes []*k3d.Node, filterString string) ([]*k3d.Node, error) { // if one of the filters is 'all', we only return this and drop all others if submatches["group"] == "all" { // TODO: only log if really more than one is specified - log.Warnf("Node filter 'all' set, but more were specified in '%s'", filterString) + log.Warnf("Node filter 'all' set, but more were specified in '%+v'", filters) return nodes, nil } diff --git a/cmd/util/ports.go b/cmd/util/ports.go index 8d111b2d..bc41b19b 100644 --- a/cmd/util/ports.go +++ b/cmd/util/ports.go @@ -70,5 +70,5 @@ func ParseAPIPort(portString string) (k3d.ExposeAPI, error) { // ValidatePortMap validates a port mapping func ValidatePortMap(portmap string) (string, error) { - return "", nil // TODO: + return portmap, nil // TODO: } diff --git a/pkg/runtimes/docker/translate.go b/pkg/runtimes/docker/translate.go index 933b2df7..6675fca1 100644 --- a/pkg/runtimes/docker/translate.go +++ b/pkg/runtimes/docker/translate.go @@ -81,7 +81,7 @@ func TranslateNodeToContainer(node *k3d.Node) (*NodeInDocker, error) { /* Ports */ exposedPorts, portBindings, err := nat.ParsePortSpecs(node.Ports) if err != nil { - log.Errorln("Failed to parse port specs") + log.Errorln("Failed to parse port specs '%v'", node.Ports) return nil, err } containerConfig.ExposedPorts = exposedPorts