|
|
@ -34,6 +34,7 @@ import ( |
|
|
|
"time" |
|
|
|
"time" |
|
|
|
|
|
|
|
|
|
|
|
copystruct "github.com/mitchellh/copystructure" |
|
|
|
copystruct "github.com/mitchellh/copystructure" |
|
|
|
|
|
|
|
"gopkg.in/yaml.v2" |
|
|
|
|
|
|
|
|
|
|
|
"github.com/docker/go-connections/nat" |
|
|
|
"github.com/docker/go-connections/nat" |
|
|
|
dockerunits "github.com/docker/go-units" |
|
|
|
dockerunits "github.com/docker/go-units" |
|
|
@ -691,40 +692,37 @@ func NodeEdit(ctx context.Context, runtime runtimes.Runtime, existingNode, chang |
|
|
|
|
|
|
|
|
|
|
|
// --- Loadbalancer specifics ---
|
|
|
|
// --- Loadbalancer specifics ---
|
|
|
|
if result.Role == k3d.LoadBalancerRole { |
|
|
|
if result.Role == k3d.LoadBalancerRole { |
|
|
|
nodeEditApplyLBSpecifics(ctx, result) |
|
|
|
cluster, err := ClusterGet(ctx, runtime, &k3d.Cluster{Name: existingNode.RuntimeLabels[k3d.LabelClusterName]}) |
|
|
|
} |
|
|
|
if err != nil { |
|
|
|
|
|
|
|
return fmt.Errorf("error updating loadbalancer config: %w", err) |
|
|
|
// replace existing node
|
|
|
|
} |
|
|
|
return NodeReplace(ctx, runtime, existingNode, result) |
|
|
|
cluster.ServerLoadBalancer = result |
|
|
|
|
|
|
|
lbConfig, err := LoadbalancerGenerateConfig(cluster) |
|
|
|
} |
|
|
|
if err != nil { |
|
|
|
|
|
|
|
return fmt.Errorf("error generating loadbalancer config: %v", err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func nodeEditApplyLBSpecifics(ctx context.Context, lbNode *k3d.Node) { |
|
|
|
// prepare to write config to lb container
|
|
|
|
tcp_ports := []string{} |
|
|
|
configyaml, err := yaml.Marshal(lbConfig) |
|
|
|
udp_ports := []string{} |
|
|
|
if err != nil { |
|
|
|
for index, env := range lbNode.Env { |
|
|
|
return err |
|
|
|
if strings.HasPrefix(env, "PORTS=") || strings.HasPrefix(env, "UDP_PORTS=") { |
|
|
|
|
|
|
|
// Remove matching environment variable from slice (does not preserve order)
|
|
|
|
|
|
|
|
lbNode.Env[index] = lbNode.Env[len(lbNode.Env)-1] // copy last element to index of matching env
|
|
|
|
|
|
|
|
lbNode.Env[len(lbNode.Env)-1] = "" // remove last element
|
|
|
|
|
|
|
|
lbNode.Env = lbNode.Env[:len(lbNode.Env)-1] // truncate
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for port := range lbNode.Ports { |
|
|
|
writeLbConfigAction := k3d.NodeHook{ |
|
|
|
switch port.Proto() { |
|
|
|
Stage: k3d.LifecycleStagePreStart, |
|
|
|
case "tcp": |
|
|
|
Action: actions.WriteFileAction{ |
|
|
|
tcp_ports = append(tcp_ports, port.Port()) |
|
|
|
Runtime: runtime, |
|
|
|
break |
|
|
|
Dest: k3d.DefaultLoadbalancerConfigPath, |
|
|
|
case "udp": |
|
|
|
Mode: 0744, |
|
|
|
udp_ports = append(udp_ports, port.Port()) |
|
|
|
Content: configyaml, |
|
|
|
break |
|
|
|
}, |
|
|
|
default: |
|
|
|
|
|
|
|
log.Warnf("Unknown port protocol %s for port %s", port.Proto(), port.Port()) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result.HookActions = append(result.HookActions, writeLbConfigAction) |
|
|
|
} |
|
|
|
} |
|
|
|
lbNode.Env = append(lbNode.Env, fmt.Sprintf("PORTS=%s", strings.Join(tcp_ports, ","))) |
|
|
|
|
|
|
|
lbNode.Env = append(lbNode.Env, fmt.Sprintf("UDP_PORTS=%s", strings.Join(udp_ports, ","))) |
|
|
|
// replace existing node
|
|
|
|
|
|
|
|
return NodeReplace(ctx, runtime, existingNode, result) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func NodeReplace(ctx context.Context, runtime runtimes.Runtime, old, new *k3d.Node) error { |
|
|
|
func NodeReplace(ctx context.Context, runtime runtimes.Runtime, old, new *k3d.Node) error { |
|
|
@ -755,7 +753,7 @@ func NodeReplace(ctx context.Context, runtime runtimes.Runtime, old, new *k3d.No |
|
|
|
|
|
|
|
|
|
|
|
// start new node
|
|
|
|
// start new node
|
|
|
|
log.Infof("Starting new node %s...", new.Name) |
|
|
|
log.Infof("Starting new node %s...", new.Name) |
|
|
|
if err := NodeStart(ctx, runtime, new, k3d.NodeStartOpts{Wait: true}); err != nil { |
|
|
|
if err := NodeStart(ctx, runtime, new, k3d.NodeStartOpts{Wait: true, NodeHooks: new.HookActions}); err != nil { |
|
|
|
if err := NodeDelete(ctx, runtime, new, k3d.NodeDeleteOpts{SkipLBUpdate: true}); err != nil { |
|
|
|
if err := NodeDelete(ctx, runtime, new, k3d.NodeDeleteOpts{SkipLBUpdate: true}); err != nil { |
|
|
|
return fmt.Errorf("Failed to start new node. Also failed to rollback: %+v", err) |
|
|
|
return fmt.Errorf("Failed to start new node. Also failed to rollback: %+v", err) |
|
|
|
} |
|
|
|
} |
|
|
|