createNode: copy as many details as possible from existing
- we now use the full containerJSON details when getting a node - we now use as many details as possible to copy k3d settings from an existing node when adding a new node to a running cluster
This commit is contained in:
parent
da8adf5469
commit
c061104b53
@ -2,4 +2,5 @@ title: Usage
|
||||
arrange:
|
||||
- commands.md
|
||||
- kubeconfig.md
|
||||
- multimaster.md
|
||||
- guides
|
2
go.mod
2
go.mod
@ -21,7 +21,7 @@ require (
|
||||
github.com/gogo/protobuf v1.3.1 // indirect
|
||||
github.com/golang/protobuf v1.4.0 // indirect
|
||||
github.com/heroku/docker-registry-client v0.0.0-20190909225348-afc9e1acc3d5
|
||||
github.com/imdario/mergo v0.3.9 // indirect
|
||||
github.com/imdario/mergo v0.3.9
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect
|
||||
|
@ -25,10 +25,10 @@ package cluster
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/imdario/mergo"
|
||||
"github.com/rancher/k3d/pkg/runtimes"
|
||||
k3d "github.com/rancher/k3d/pkg/types"
|
||||
log "github.com/sirupsen/logrus"
|
||||
@ -70,27 +70,21 @@ func AddNodeToCluster(runtime runtimes.Runtime, node *k3d.Node, cluster *k3d.Clu
|
||||
}
|
||||
}
|
||||
|
||||
// get node details
|
||||
chosenNode, err = GetNode(chosenNode, runtime)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debugf("Copying configuration from existing node %+v", chosenNode)
|
||||
|
||||
// get config from labels
|
||||
for k, v := range chosenNode.Labels {
|
||||
if strings.HasPrefix(k, "k3d") {
|
||||
node.Labels[k] = v
|
||||
}
|
||||
if k == "k3d.cluster.url" {
|
||||
node.Env = append(node.Env, fmt.Sprintf("K3S_URL=%s", v))
|
||||
}
|
||||
if k == "k3d.cluster.secret" {
|
||||
node.Env = append(node.Env, fmt.Sprintf("K3S_TOKEN=%s", v))
|
||||
}
|
||||
// merge node config of new node into existing node config
|
||||
if err := mergo.MergeWithOverwrite(chosenNode, *node); err != nil {
|
||||
log.Errorln("Failed to merge new node config into existing node config")
|
||||
return err
|
||||
}
|
||||
|
||||
// backup: get config from environment variables
|
||||
for _, env := range chosenNode.Env {
|
||||
if strings.HasPrefix(env, "K3S_") {
|
||||
node.Env = append(node.Env, env)
|
||||
}
|
||||
}
|
||||
node = chosenNode
|
||||
|
||||
log.Debugf("Resulting node %+v", node)
|
||||
|
||||
|
@ -38,7 +38,6 @@ import (
|
||||
|
||||
// CreateNode creates a new container
|
||||
func (d Docker) CreateNode(node *k3d.Node) error {
|
||||
log.Debugln("docker.CreateNode...")
|
||||
|
||||
// translate node spec to docker container specs
|
||||
dockerNode, err := TranslateNodeToContainer(node)
|
||||
@ -172,9 +171,30 @@ func getContainersByLabel(labels map[string]string) ([]types.Container, error) {
|
||||
log.Errorln("Failed to list containers")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return containers, nil
|
||||
}
|
||||
|
||||
// getContainer details returns the containerjson with more details
|
||||
func getContainerDetails(containerID string) (types.ContainerJSON, error) {
|
||||
// (0) create docker client
|
||||
ctx := context.Background()
|
||||
docker, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
||||
if err != nil {
|
||||
return types.ContainerJSON{}, fmt.Errorf("Failed to create docker client. %+v", err)
|
||||
}
|
||||
defer docker.Close()
|
||||
|
||||
containerDetails, err := docker.ContainerInspect(ctx, containerID)
|
||||
if err != nil {
|
||||
log.Errorln("Failed to get details for container '%s'", containerID)
|
||||
return types.ContainerJSON{}, err
|
||||
}
|
||||
|
||||
return containerDetails, nil
|
||||
|
||||
}
|
||||
|
||||
// GetNode tries to get a node container by its name
|
||||
func (d Docker) GetNode(node *k3d.Node) (*k3d.Node, error) {
|
||||
container, err := getNodeContainer(node)
|
||||
@ -183,9 +203,14 @@ func (d Docker) GetNode(node *k3d.Node) (*k3d.Node, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
node, err = TranslateContainerToNode(container)
|
||||
containerDetails, err := getContainerDetails(container.ID)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to translate container for node '%s' to node object", node.Name)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
node, err = TranslateContainerDetailsToNode(containerDetails)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to translate container details for node '%s' to node object", node.Name)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@ THE SOFTWARE.
|
||||
package docker
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
@ -117,3 +118,79 @@ func TranslateContainerToNode(cont *types.Container) (*k3d.Node, error) {
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
||||
// TranslateContainerDetailsToNode translates a docker containerJSON object into a k3d node representation
|
||||
func TranslateContainerDetailsToNode(containerDetails types.ContainerJSON) (*k3d.Node, error) {
|
||||
|
||||
// translate portMap to string representation
|
||||
ports := []string{}
|
||||
for containerPort, portBindingList := range containerDetails.HostConfig.PortBindings {
|
||||
for _, hostInfo := range portBindingList {
|
||||
ports = append(ports, fmt.Sprintf("%s:%s:%s", hostInfo.HostIP, hostInfo.HostPort, containerPort))
|
||||
}
|
||||
}
|
||||
|
||||
// restart -> we only set 'unless-stopped' upon cluster creation
|
||||
restart := false
|
||||
if containerDetails.HostConfig.RestartPolicy.IsAlways() || containerDetails.HostConfig.RestartPolicy.IsUnlessStopped() {
|
||||
restart = true
|
||||
}
|
||||
|
||||
// get the clusterNetwork
|
||||
clusterNetwork := ""
|
||||
for networkName := range containerDetails.NetworkSettings.Networks {
|
||||
if strings.HasPrefix(networkName, fmt.Sprintf("%s-%s", k3d.DefaultObjectNamePrefix, containerDetails.Config.Labels["k3d.cluster"])) { // FIXME: catch error if label 'k3d.cluster' does not exist, but this should also never be the case
|
||||
clusterNetwork = networkName
|
||||
}
|
||||
}
|
||||
|
||||
// masterOpts
|
||||
masterOpts := k3d.MasterOpts{IsInit: false}
|
||||
for k, v := range containerDetails.Config.Labels {
|
||||
/*
|
||||
node.Labels["k3d.master.api.hostIP"] = node.MasterOpts.ExposeAPI.HostIP // TODO: maybe get docker machine IP here
|
||||
node.Labels["k3d.master.api.host"] = node.MasterOpts.ExposeAPI.Host
|
||||
node.Labels["k3d.master.api.port"] = node.MasterOpts.ExposeAPI.Port
|
||||
*/
|
||||
if k == "k3d.master.api.hostIP" {
|
||||
masterOpts.ExposeAPI.HostIP = v
|
||||
} else if k == "k3d.master.api.host" {
|
||||
masterOpts.ExposeAPI.Host = v
|
||||
} else if k == "k3d.master.api.port" {
|
||||
masterOpts.ExposeAPI.Port = v
|
||||
}
|
||||
}
|
||||
|
||||
// env vars: only copy K3S_* and K3D_* // FIXME: should we really do this? Might be unexpected, if user has e.g. HTTP_PROXY vars
|
||||
env := []string{}
|
||||
for _, envVar := range containerDetails.Config.Env {
|
||||
if strings.HasPrefix(envVar, "K3D_") || strings.HasPrefix(envVar, "K3S_") {
|
||||
env = append(env, envVar)
|
||||
}
|
||||
}
|
||||
|
||||
// labels: only copy k3d.* labels
|
||||
labels := map[string]string{}
|
||||
for k, v := range containerDetails.Config.Labels {
|
||||
if strings.HasPrefix(k, "k3d") {
|
||||
labels[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
node := &k3d.Node{
|
||||
Name: strings.TrimPrefix(containerDetails.Name, "/"), // container name with leading '/' cut off
|
||||
Role: k3d.NodeRoles[containerDetails.Config.Labels["k3d.role"]],
|
||||
Image: containerDetails.Image,
|
||||
Volumes: containerDetails.HostConfig.Binds,
|
||||
Env: env,
|
||||
Cmd: containerDetails.Config.Cmd,
|
||||
Args: []string{}, // empty, since Cmd already contains flags
|
||||
Ports: ports,
|
||||
Restart: restart,
|
||||
Labels: labels,
|
||||
Network: clusterNetwork,
|
||||
MasterOpts: masterOpts,
|
||||
WorkerOpts: k3d.WorkerOpts{},
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user