diff --git a/pkg/cluster/cluster.go b/pkg/cluster/cluster.go index 3fb550fd..fb7102f8 100644 --- a/pkg/cluster/cluster.go +++ b/pkg/cluster/cluster.go @@ -427,7 +427,7 @@ func populateClusterFieldsFromLabels(cluster *k3d.Cluster) error { return nil } -// GetCluster returns an existing cluster +// GetCluster returns an existing cluster with all fields and node lists populated func GetCluster(cluster *k3d.Cluster, runtime k3drt.Runtime) (*k3d.Cluster, error) { // get nodes that belong to the selected cluster nodes, err := runtime.GetNodesByLabel(map[string]string{"k3d.cluster": cluster.Name}) diff --git a/pkg/cluster/loadbalancer.go b/pkg/cluster/loadbalancer.go new file mode 100644 index 00000000..ec4b0755 --- /dev/null +++ b/pkg/cluster/loadbalancer.go @@ -0,0 +1,59 @@ +/* +Copyright © 2020 The k3d Author(s) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +package cluster + +import ( + "fmt" + + "github.com/rancher/k3d/pkg/runtimes" + k3d "github.com/rancher/k3d/pkg/types" + log "github.com/sirupsen/logrus" +) + +// AddMasterToLoadBalancer adds a new master node to the loadbalancer configuration +func AddMasterToLoadBalancer(runtime runtimes.Runtime, cluster *k3d.Cluster, newNode *k3d.Node) error { + // find the LoadBalancer for the target cluster + masterNodes := "" + var loadbalancer *k3d.Node + for _, node := range cluster.Nodes { + if node.Role == k3d.LoadBalancerRole { // get the loadbalancer we want to update + loadbalancer = node + } else if node.Role == k3d.MasterRole { // create a list of master nodes + masterNodes += node.Name + "," + } + } + if loadbalancer == nil { + return fmt.Errorf("Failed to find loadbalancer for cluster '%s'", cluster.Name) + } + masterNodes += newNode.Name // append the new master node to the end of the list + + log.Debugf("SERVERS=%s", masterNodes) + + command := fmt.Sprintf("SERVERS=%s %s", masterNodes, "confd -onetime -backend env && nginx -s reload") + if err := runtime.ExecInNode(loadbalancer, []string{"sh", "-c", command}); err != nil { + log.Errorln("Failed to update loadbalancer configuration") + return err + } + + return nil + +} diff --git a/pkg/cluster/node.go b/pkg/cluster/node.go index 75b605d7..0fe10def 100644 --- a/pkg/cluster/node.go +++ b/pkg/cluster/node.go @@ -94,7 +94,19 @@ func AddNodeToCluster(runtime runtimes.Runtime, node *k3d.Node, cluster *k3d.Clu log.Debugf("Resulting node %+v", node) - return CreateNode(node, runtime) + if err := CreateNode(node, runtime); err != nil { + return err + } + + // if it's a master node, then update the loadbalancer configuration to include it + if node.Role == k3d.MasterRole { + if err := AddMasterToLoadBalancer(runtime, cluster, node); err != nil { + log.Errorln("Failed to add new master node to cluster loadbalancer") + return err + } + } + + return nil } // CreateNodes creates a list of nodes @@ -196,7 +208,7 @@ func GetNodes(runtime runtimes.Runtime) ([]*k3d.Node, error) { return nodes, nil } -// GetNode returns an existing cluster +// GetNode returns a node matching the specified node fields func GetNode(node *k3d.Node, runtime runtimes.Runtime) (*k3d.Node, error) { // get node node, err := runtime.GetNode(node) diff --git a/pkg/runtimes/docker/translate.go b/pkg/runtimes/docker/translate.go index 46e70e0e..d1b6a019 100644 --- a/pkg/runtimes/docker/translate.go +++ b/pkg/runtimes/docker/translate.go @@ -23,6 +23,8 @@ THE SOFTWARE. package docker import ( + "strings" + "github.com/docker/docker/api/types" docker "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/network" @@ -107,10 +109,10 @@ func TranslateNodeToContainer(node *k3d.Node) (*NodeInDocker, error) { // TranslateContainerToNode translates a docker container object into a k3d node representation func TranslateContainerToNode(cont *types.Container) (*k3d.Node, error) { node := &k3d.Node{ - Name: cont.Names[0], + Name: strings.TrimPrefix(cont.Names[0], "/"), // container name with leading '/' cut off Image: cont.Image, Labels: cont.Labels, - Role: k3d.NodeRoles[cont.Labels["k3d.role"]], // TODO: what if this is not present? + Role: k3d.NodeRoles[cont.Labels["k3d.role"]], // TODO: all the rest } return node, nil