Merge pull request #244 from rancher/enhancement/use-context

[Enhancement] v3/overall: use context.Context everywhere (creating possibilities without breaking interfaces later)
pull/258/head
Thorsten Klein 4 years ago committed by GitHub
commit 4491dfcc29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      cmd/create/createCluster.go
  2. 2
      cmd/create/createNode.go
  3. 8
      cmd/delete/deleteCluster.go
  4. 6
      cmd/delete/deleteNode.go
  5. 4
      cmd/get/getCluster.go
  6. 4
      cmd/get/getKubeconfig.go
  7. 4
      cmd/get/getNode.go
  8. 4
      cmd/load/loadImage.go
  9. 6
      cmd/start/startCluster.go
  10. 2
      cmd/start/startNode.go
  11. 6
      cmd/stop/stopCluster.go
  12. 2
      cmd/stop/stopNode.go
  13. 59
      pkg/cluster/cluster.go
  14. 31
      pkg/cluster/kubeconfig.go
  15. 5
      pkg/cluster/loadbalancer.go
  16. 32
      pkg/cluster/node.go
  17. 3
      pkg/runtimes/containerd/kubeconfig.go
  18. 6
      pkg/runtimes/containerd/network.go
  19. 18
      pkg/runtimes/containerd/node.go
  20. 6
      pkg/runtimes/containerd/volume.go
  21. 19
      pkg/runtimes/docker/container.go
  22. 5
      pkg/runtimes/docker/kubeconfig.go
  23. 9
      pkg/runtimes/docker/network.go
  24. 46
      pkg/runtimes/docker/node.go
  25. 3
      pkg/runtimes/docker/translate.go
  26. 6
      pkg/runtimes/docker/volume.go
  27. 28
      pkg/runtimes/runtime.go
  28. 18
      pkg/tools/tools.go

@ -64,7 +64,7 @@ func NewCmdCreateCluster() *cobra.Command {
cluster := parseCreateClusterCmd(cmd, args, createClusterOpts)
// check if a cluster with that name exists already
if _, err := k3dCluster.GetCluster(cluster, runtimes.SelectedRuntime); err == nil {
if _, err := k3dCluster.GetCluster(cmd.Context(), runtimes.SelectedRuntime, cluster); err == nil {
log.Fatalf("Failed to create cluster '%s' because a cluster with that name already exists", cluster.Name)
}
@ -73,11 +73,11 @@ func NewCmdCreateCluster() *cobra.Command {
log.Debugln("'--update-kubeconfig set: enabling wait-for-master")
cluster.CreateClusterOpts.WaitForMaster = true
}
if err := k3dCluster.CreateCluster(cmd.Context(), cluster, runtimes.SelectedRuntime); err != nil {
if err := k3dCluster.CreateCluster(cmd.Context(), runtimes.SelectedRuntime, cluster); err != nil {
// rollback if creation failed
log.Errorln(err)
log.Errorln("Failed to create cluster >>> Rolling Back")
if err := k3dCluster.DeleteCluster(cluster, runtimes.SelectedRuntime); err != nil {
if err := k3dCluster.DeleteCluster(cmd.Context(), runtimes.SelectedRuntime, cluster); err != nil {
log.Errorln(err)
log.Fatalln("Cluster creation FAILED, also FAILED to rollback changes!")
}
@ -87,7 +87,7 @@ func NewCmdCreateCluster() *cobra.Command {
if updateKubeconfig {
log.Debugf("Updating default kubeconfig with a new context for cluster %s", cluster.Name)
if _, err := k3dCluster.GetAndWriteKubeConfig(runtimes.SelectedRuntime, cluster, "", &k3dCluster.WriteKubeConfigOptions{UpdateExisting: true, OverwriteExisting: false, UpdateCurrentContext: false}); err != nil {
if _, err := k3dCluster.GetAndWriteKubeConfig(cmd.Context(), runtimes.SelectedRuntime, cluster, "", &k3dCluster.WriteKubeConfigOptions{UpdateExisting: true, OverwriteExisting: false, UpdateCurrentContext: false}); err != nil {
log.Fatalln(err)
}
}

@ -45,7 +45,7 @@ func NewCmdCreateNode() *cobra.Command {
Run: func(cmd *cobra.Command, args []string) {
nodes, cluster := parseCreateNodeCmd(cmd, args)
for _, node := range nodes {
if err := k3dc.AddNodeToCluster(runtimes.SelectedRuntime, node, cluster); err != nil {
if err := k3dc.AddNodeToCluster(cmd.Context(), runtimes.SelectedRuntime, node, cluster); err != nil {
log.Errorf("Failed to add node '%s' to cluster '%s'", node.Name, cluster.Name)
log.Errorln(err)
}

@ -46,11 +46,11 @@ func NewCmdDeleteCluster() *cobra.Command {
log.Infoln("No clusters found")
} else {
for _, c := range clusters {
if err := cluster.DeleteCluster(c, runtimes.SelectedRuntime); err != nil {
if err := cluster.DeleteCluster(cmd.Context(), runtimes.SelectedRuntime, c); err != nil {
log.Fatalln(err)
}
log.Infoln("Removing cluster details from default kubeconfig")
if err := cluster.RemoveClusterFromDefaultKubeConfig(c); err != nil {
if err := cluster.RemoveClusterFromDefaultKubeConfig(cmd.Context(), c); err != nil {
log.Warnln("Failed to remove cluster details from default kubeconfig")
log.Warnln(err)
}
@ -80,7 +80,7 @@ func parseDeleteClusterCmd(cmd *cobra.Command, args []string) []*k3d.Cluster {
if all, err := cmd.Flags().GetBool("all"); err != nil {
log.Fatalln(err)
} else if all {
clusters, err = cluster.GetClusters(runtimes.SelectedRuntime)
clusters, err = cluster.GetClusters(cmd.Context(), runtimes.SelectedRuntime)
if err != nil {
log.Fatalln(err)
}
@ -92,7 +92,7 @@ func parseDeleteClusterCmd(cmd *cobra.Command, args []string) []*k3d.Cluster {
}
for _, name := range args {
cluster, err := cluster.GetCluster(&k3d.Cluster{Name: name}, runtimes.SelectedRuntime)
cluster, err := cluster.GetCluster(cmd.Context(), runtimes.SelectedRuntime, &k3d.Cluster{Name: name})
if err != nil {
log.Fatalln(err)
}

@ -46,7 +46,7 @@ func NewCmdDeleteNode() *cobra.Command {
log.Infoln("No nodes found")
} else {
for _, node := range nodes {
if err := cluster.DeleteNode(runtimes.SelectedRuntime, node); err != nil {
if err := cluster.DeleteNode(cmd.Context(), runtimes.SelectedRuntime, node); err != nil {
log.Fatalln(err)
}
}
@ -72,7 +72,7 @@ func parseDeleteNodeCmd(cmd *cobra.Command, args []string) []*k3d.Node {
if all, err := cmd.Flags().GetBool("all"); err != nil {
log.Fatalln(err)
} else if all {
nodes, err = cluster.GetNodes(runtimes.SelectedRuntime)
nodes, err = cluster.GetNodes(cmd.Context(), runtimes.SelectedRuntime)
if err != nil {
log.Fatalln(err)
}
@ -84,7 +84,7 @@ func parseDeleteNodeCmd(cmd *cobra.Command, args []string) []*k3d.Node {
}
for _, name := range args {
node, err := cluster.GetNode(&k3d.Node{Name: name}, runtimes.SelectedRuntime)
node, err := cluster.GetNode(cmd.Context(), runtimes.SelectedRuntime, &k3d.Node{Name: name})
if err != nil {
log.Fatalln(err)
}

@ -51,13 +51,13 @@ func NewCmdGetCluster() *cobra.Command {
clusters, headersOff := parseGetClusterCmd(cmd, args)
var existingClusters []*k3d.Cluster
if clusters == nil { // Option a) no cluster name specified -> get all clusters
found, err := cluster.GetClusters(runtimes.SelectedRuntime)
found, err := cluster.GetClusters(cmd.Context(), runtimes.SelectedRuntime)
if err != nil {
log.Fatalln(err)
}
existingClusters = append(existingClusters, found...)
} else { // Option b) cluster name specified -> get specific cluster
found, err := cluster.GetCluster(clusters, runtimes.SelectedRuntime)
found, err := cluster.GetCluster(cmd.Context(), runtimes.SelectedRuntime, clusters)
if err != nil {
log.Fatalln(err)
}

@ -63,7 +63,7 @@ func NewCmdGetKubeconfig() *cobra.Command {
// generate list of clusters
if getKubeconfigFlags.all {
clusters, err = cluster.GetClusters(runtimes.SelectedRuntime)
clusters, err = cluster.GetClusters(cmd.Context(), runtimes.SelectedRuntime)
if err != nil {
log.Fatalln(err)
}
@ -77,7 +77,7 @@ func NewCmdGetKubeconfig() *cobra.Command {
errorGettingKubeconfig := false
for _, c := range clusters {
log.Debugf("Getting kubeconfig for cluster '%s'", c.Name)
if getKubeconfigFlags.output, err = cluster.GetAndWriteKubeConfig(runtimes.SelectedRuntime, c, getKubeconfigFlags.output, &writeKubeConfigOptions); err != nil {
if getKubeconfigFlags.output, err = cluster.GetAndWriteKubeConfig(cmd.Context(), runtimes.SelectedRuntime, c, getKubeconfigFlags.output, &writeKubeConfigOptions); err != nil {
log.Errorln(err)
errorGettingKubeconfig = true
}

@ -49,13 +49,13 @@ func NewCmdGetNode() *cobra.Command {
node, headersOff := parseGetNodeCmd(cmd, args)
var existingNodes []*k3d.Node
if node == nil { // Option a) no name specified -> get all nodes
found, err := cluster.GetNodes(runtimes.SelectedRuntime)
found, err := cluster.GetNodes(cmd.Context(), runtimes.SelectedRuntime)
if err != nil {
log.Fatalln(err)
}
existingNodes = append(existingNodes, found...)
} else { // Option b) cluster name specified -> get specific cluster
found, err := cluster.GetNode(node, runtimes.SelectedRuntime)
found, err := cluster.GetNode(cmd.Context(), runtimes.SelectedRuntime, node)
if err != nil {
log.Fatalln(err)
}

@ -42,10 +42,10 @@ func NewCmdLoadImage() *cobra.Command {
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
images, clusters, keepTarball := parseLoadImageCmd(cmd, args)
log.Debugf("Load images [%+v] from runtime [%s] into clusters [%+v]", runtimes.SelectedRuntime, images, clusters)
log.Debugf("Load images [%+v] from runtime [%s] into clusters [%+v]", images, runtimes.SelectedRuntime, clusters)
for _, cluster := range clusters {
log.Infof("Loading images into '%s'", cluster.Name)
if err := tools.LoadImagesIntoCluster(runtimes.SelectedRuntime, images, &cluster, keepTarball); err != nil {
if err := tools.LoadImagesIntoCluster(cmd.Context(), runtimes.SelectedRuntime, images, &cluster, keepTarball); err != nil {
log.Errorf("Failed to load images into cluster '%s'", cluster.Name)
log.Errorln(err)
}

@ -50,7 +50,7 @@ func NewCmdStartCluster() *cobra.Command {
log.Infoln("No clusters found")
} else {
for _, c := range clusters {
if err := cluster.StartCluster(cmd.Context(), c, runtimes.SelectedRuntime, startClusterOpts); err != nil {
if err := cluster.StartCluster(cmd.Context(), runtimes.SelectedRuntime, c, startClusterOpts); err != nil {
log.Fatalln(err)
}
}
@ -77,7 +77,7 @@ func parseStartClusterCmd(cmd *cobra.Command, args []string) []*k3d.Cluster {
if all, err := cmd.Flags().GetBool("all"); err != nil {
log.Fatalln(err)
} else if all {
clusters, err = cluster.GetClusters(runtimes.SelectedRuntime)
clusters, err = cluster.GetClusters(cmd.Context(), runtimes.SelectedRuntime)
if err != nil {
log.Fatalln(err)
}
@ -89,7 +89,7 @@ func parseStartClusterCmd(cmd *cobra.Command, args []string) []*k3d.Cluster {
}
for _, name := range args {
cluster, err := cluster.GetCluster(&k3d.Cluster{Name: name}, runtimes.SelectedRuntime)
cluster, err := cluster.GetCluster(cmd.Context(), runtimes.SelectedRuntime, &k3d.Cluster{Name: name})
if err != nil {
log.Fatalln(err)
}

@ -39,7 +39,7 @@ func NewCmdStartNode() *cobra.Command {
Long: `Start an existing k3d node.`,
Run: func(cmd *cobra.Command, args []string) {
node := parseStartNodeCmd(cmd, args)
if err := runtimes.SelectedRuntime.StartNode(node); err != nil {
if err := runtimes.SelectedRuntime.StartNode(cmd.Context(), node); err != nil {
log.Fatalln(err)
}
},

@ -45,7 +45,7 @@ func NewCmdStopCluster() *cobra.Command {
log.Infoln("No clusters found")
} else {
for _, c := range clusters {
if err := cluster.StopCluster(c, runtimes.SelectedRuntime); err != nil {
if err := cluster.StopCluster(cmd.Context(), runtimes.SelectedRuntime, c); err != nil {
log.Fatalln(err)
}
}
@ -70,7 +70,7 @@ func parseStopClusterCmd(cmd *cobra.Command, args []string) []*k3d.Cluster {
if all, err := cmd.Flags().GetBool("all"); err != nil {
log.Fatalln(err)
} else if all {
clusters, err = cluster.GetClusters(runtimes.SelectedRuntime)
clusters, err = cluster.GetClusters(cmd.Context(), runtimes.SelectedRuntime)
if err != nil {
log.Fatalln(err)
}
@ -82,7 +82,7 @@ func parseStopClusterCmd(cmd *cobra.Command, args []string) []*k3d.Cluster {
}
for _, name := range args {
cluster, err := cluster.GetCluster(&k3d.Cluster{Name: name}, runtimes.SelectedRuntime)
cluster, err := cluster.GetCluster(cmd.Context(), runtimes.SelectedRuntime, &k3d.Cluster{Name: name})
if err != nil {
log.Fatalln(err)
}

@ -40,7 +40,7 @@ func NewCmdStopNode() *cobra.Command {
Long: `Stop an existing k3d node.`,
Run: func(cmd *cobra.Command, args []string) {
node := parseStopNodeCmd(cmd, args)
if err := runtimes.SelectedRuntime.StopNode(node); err != nil {
if err := runtimes.SelectedRuntime.StopNode(cmd.Context(), node); err != nil {
log.Fatalln(err)
}
},

@ -40,7 +40,7 @@ import (
// CreateCluster creates a new cluster consisting of
// - some containerized k3s nodes
// - a docker network
func CreateCluster(ctx context.Context, cluster *k3d.Cluster, runtime k3drt.Runtime) error {
func CreateCluster(ctx context.Context, runtime k3drt.Runtime, cluster *k3d.Cluster) error {
if cluster.CreateClusterOpts.Timeout > 0*time.Second {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, cluster.CreateClusterOpts.Timeout)
@ -71,7 +71,7 @@ func CreateCluster(ctx context.Context, cluster *k3d.Cluster, runtime k3drt.Runt
}
// create cluster network or use an existing one
networkID, networkExists, err := runtime.CreateNetworkIfNotPresent(cluster.Network.Name)
networkID, networkExists, err := runtime.CreateNetworkIfNotPresent(ctx, cluster.Network.Name)
if err != nil {
log.Errorln("Failed to create cluster network")
return err
@ -99,7 +99,7 @@ func CreateCluster(ctx context.Context, cluster *k3d.Cluster, runtime k3drt.Runt
*/
if !cluster.CreateClusterOpts.DisableImageVolume {
imageVolumeName := fmt.Sprintf("%s-%s-images", k3d.DefaultObjectNamePrefix, cluster.Name)
if err := runtime.CreateVolume(imageVolumeName, map[string]string{"k3d.cluster": cluster.Name}); err != nil {
if err := runtime.CreateVolume(ctx, imageVolumeName, map[string]string{"k3d.cluster": cluster.Name}); err != nil {
log.Errorln("Failed to create image volume '%s' for cluster '%s'", imageVolumeName, cluster.Name)
return err
}
@ -154,7 +154,7 @@ func CreateCluster(ctx context.Context, cluster *k3d.Cluster, runtime k3drt.Runt
// create node
log.Infof("Creating node '%s'", node.Name)
if err := CreateNode(node, runtime); err != nil {
if err := CreateNode(ctx, runtime, node); err != nil {
log.Errorln("Failed to create node")
return err
}
@ -192,7 +192,7 @@ func CreateCluster(ctx context.Context, cluster *k3d.Cluster, runtime k3drt.Runt
default:
}
log.Debugln("Waiting for initializing master node...")
logreader, err := runtime.GetNodeLogs(cluster.InitNode, time.Time{})
logreader, err := runtime.GetNodeLogs(ctx, cluster.InitNode, time.Time{})
if err != nil {
if logreader != nil {
logreader.Close()
@ -259,12 +259,6 @@ func CreateCluster(ctx context.Context, cluster *k3d.Cluster, runtime k3drt.Runt
}
}
if err := waitForMasterWaitgroup.Wait(); err != nil {
log.Errorln("Failed to bring up all master nodes in time. Check the logs:")
log.Errorln(">>> ", err)
return fmt.Errorf("Failed to bring up cluster")
}
/*
* Auxiliary Containers
*/
@ -306,26 +300,41 @@ func CreateCluster(ctx context.Context, cluster *k3d.Cluster, runtime k3drt.Runt
}
cluster.Nodes = append(cluster.Nodes, lbNode) // append lbNode to list of cluster nodes, so it will be considered during rollback
log.Infof("Creating LoadBalancer '%s'", lbNode.Name)
if err := CreateNode(lbNode, runtime); err != nil {
if err := CreateNode(ctx, runtime, lbNode); err != nil {
log.Errorln("Failed to create loadbalancer")
return err
}
if cluster.CreateClusterOpts.WaitForMaster {
waitForMasterWaitgroup.Go(func() error {
// TODO: avoid `level=fatal msg="starting kubernetes: preparing server: post join: a configuration change is already in progress (5)"`
// ... by scanning for this line in logs and restarting the container in case it appears
log.Debugf("Starting to wait for loadbalancer node '%s'", lbNode.Name)
return WaitForNodeLogMessage(ctx, runtime, lbNode, "start worker processes", time.Time{})
})
}
} else {
log.Infoln("Hostnetwork selected -> Skipping creation of Master LoadBalancer")
}
}
if err := waitForMasterWaitgroup.Wait(); err != nil {
log.Errorln("Failed to bring up all master nodes (and loadbalancer) in time. Check the logs:")
log.Errorf(">>> %+v", err)
return fmt.Errorf("Failed to bring up cluster")
}
return nil
}
// DeleteCluster deletes an existing cluster
func DeleteCluster(cluster *k3d.Cluster, runtime k3drt.Runtime) error {
func DeleteCluster(ctx context.Context, runtime k3drt.Runtime, cluster *k3d.Cluster) error {
log.Infof("Deleting cluster '%s'", cluster.Name)
log.Debugf("Cluster Details: %+v", cluster)
failed := 0
for _, node := range cluster.Nodes {
if err := runtime.DeleteNode(node); err != nil {
if err := runtime.DeleteNode(ctx, node); err != nil {
log.Warningf("Failed to delete node '%s': Try to delete it manually", node.Name)
failed++
continue
@ -336,7 +345,7 @@ func DeleteCluster(cluster *k3d.Cluster, runtime k3drt.Runtime) error {
if cluster.Network.Name != "" {
if !cluster.Network.External {
log.Infof("Deleting cluster network '%s'", cluster.Network.Name)
if err := runtime.DeleteNetwork(cluster.Network.Name); err != nil {
if err := runtime.DeleteNetwork(ctx, cluster.Network.Name); err != nil {
if strings.HasSuffix(err.Error(), "active endpoints") {
log.Warningf("Failed to delete cluster network '%s' because it's still in use: is there another cluster using it?", cluster.Network.Name)
} else {
@ -351,7 +360,7 @@ func DeleteCluster(cluster *k3d.Cluster, runtime k3drt.Runtime) error {
// delete image volume
if cluster.ImageVolume != "" {
log.Infof("Deleting image volume '%s'", cluster.ImageVolume)
if err := runtime.DeleteVolume(cluster.ImageVolume); err != nil {
if err := runtime.DeleteVolume(ctx, cluster.ImageVolume); err != nil {
log.Warningf("Failed to delete image volume '%s' of cluster '%s': Try to delete it manually", cluster.ImageVolume, cluster.Name)
}
}
@ -364,8 +373,8 @@ func DeleteCluster(cluster *k3d.Cluster, runtime k3drt.Runtime) error {
}
// GetClusters returns a list of all existing clusters
func GetClusters(runtime k3drt.Runtime) ([]*k3d.Cluster, error) {
nodes, err := runtime.GetNodesByLabel(k3d.DefaultObjectLabels)
func GetClusters(ctx context.Context, runtime k3drt.Runtime) ([]*k3d.Cluster, error) {
nodes, err := runtime.GetNodesByLabel(ctx, k3d.DefaultObjectLabels)
if err != nil {
log.Errorln("Failed to get clusters")
return nil, err
@ -438,9 +447,9 @@ func populateClusterFieldsFromLabels(cluster *k3d.Cluster) error {
}
// GetCluster returns an existing cluster with all fields and node lists populated
func GetCluster(cluster *k3d.Cluster, runtime k3drt.Runtime) (*k3d.Cluster, error) {
func GetCluster(ctx context.Context, runtime k3drt.Runtime, cluster *k3d.Cluster) (*k3d.Cluster, error) {
// get nodes that belong to the selected cluster
nodes, err := runtime.GetNodesByLabel(map[string]string{"k3d.cluster": cluster.Name})
nodes, err := runtime.GetNodesByLabel(ctx, map[string]string{"k3d.cluster": cluster.Name})
if err != nil {
log.Errorf("Failed to get nodes for cluster '%s'", cluster.Name)
}
@ -472,7 +481,7 @@ func generateNodeName(cluster string, role k3d.Role, suffix int) string {
}
// StartCluster starts a whole cluster (i.e. all nodes of the cluster)
func StartCluster(ctx context.Context, cluster *k3d.Cluster, runtime k3drt.Runtime, startClusterOpts types.StartClusterOpts) error {
func StartCluster(ctx context.Context, runtime k3drt.Runtime, cluster *k3d.Cluster, startClusterOpts types.StartClusterOpts) error {
log.Infof("Starting cluster '%s'", cluster.Name)
start := time.Now()
@ -497,7 +506,7 @@ func StartCluster(ctx context.Context, cluster *k3d.Cluster, runtime k3drt.Runti
}
// start node
if err := runtime.StartNode(node); err != nil {
if err := runtime.StartNode(ctx, node); err != nil {
log.Warningf("Failed to start node '%s': Try to start it manually", node.Name)
failed++
continue
@ -518,7 +527,7 @@ func StartCluster(ctx context.Context, cluster *k3d.Cluster, runtime k3drt.Runti
// start masterlb
if masterlb != nil {
log.Debugln("Starting masterlb...")
if err := runtime.StartNode(masterlb); err != nil { // FIXME: we could run into a nullpointer exception here
if err := runtime.StartNode(ctx, masterlb); err != nil { // FIXME: we could run into a nullpointer exception here
log.Warningf("Failed to start masterlb '%s': Try to start it manually", masterlb.Name)
failed++
}
@ -543,12 +552,12 @@ func StartCluster(ctx context.Context, cluster *k3d.Cluster, runtime k3drt.Runti
}
// StopCluster stops a whole cluster (i.e. all nodes of the cluster)
func StopCluster(cluster *k3d.Cluster, runtime k3drt.Runtime) error {
func StopCluster(ctx context.Context, runtime k3drt.Runtime, cluster *k3d.Cluster) error {
log.Infof("Stopping cluster '%s'", cluster.Name)
failed := 0
for _, node := range cluster.Nodes {
if err := runtime.StopNode(node); err != nil {
if err := runtime.StopNode(ctx, node); err != nil {
log.Warningf("Failed to stop node '%s': Try to stop it manually", node.Name)
failed++
continue

@ -23,6 +23,7 @@ package cluster
import (
"bytes"
"context"
"fmt"
"io/ioutil"
"os"
@ -47,10 +48,10 @@ type WriteKubeConfigOptions struct {
// 1. fetches the KubeConfig from the first master node retrieved for a given cluster
// 2. modifies it by updating some fields with cluster-specific information
// 3. writes it to the specified output
func GetAndWriteKubeConfig(runtime runtimes.Runtime, cluster *k3d.Cluster, output string, writeKubeConfigOptions *WriteKubeConfigOptions) (string, error) {
func GetAndWriteKubeConfig(ctx context.Context, runtime runtimes.Runtime, cluster *k3d.Cluster, output string, writeKubeConfigOptions *WriteKubeConfigOptions) (string, error) {
// get kubeconfig from cluster node
kubeconfig, err := GetKubeconfig(runtime, cluster)
kubeconfig, err := GetKubeconfig(ctx, runtime, cluster)
if err != nil {
return output, err
}
@ -65,7 +66,7 @@ func GetAndWriteKubeConfig(runtime runtimes.Runtime, cluster *k3d.Cluster, outpu
// simply write to the output, ignoring existing contents
if writeKubeConfigOptions.OverwriteExisting || output == "-" {
return output, WriteKubeConfigToPath(kubeconfig, output)
return output, WriteKubeConfigToPath(ctx, kubeconfig, output)
}
// load config from existing file or fail if it has non-kubeconfig contents
@ -102,17 +103,17 @@ func GetAndWriteKubeConfig(runtime runtimes.Runtime, cluster *k3d.Cluster, outpu
}
// update existing kubeconfig, but error out if there are conflicting fields but we don't want to update them
return output, UpdateKubeConfig(kubeconfig, existingKubeConfig, output, writeKubeConfigOptions.UpdateExisting, writeKubeConfigOptions.UpdateCurrentContext)
return output, UpdateKubeConfig(ctx, kubeconfig, existingKubeConfig, output, writeKubeConfigOptions.UpdateExisting, writeKubeConfigOptions.UpdateCurrentContext)
}
// GetKubeconfig grabs the kubeconfig file from /output from a master node container,
// modifies it by updating some fields with cluster-specific information
// and returns a Config object for further processing
func GetKubeconfig(runtime runtimes.Runtime, cluster *k3d.Cluster) (*clientcmdapi.Config, error) {
func GetKubeconfig(ctx context.Context, runtime runtimes.Runtime, cluster *k3d.Cluster) (*clientcmdapi.Config, error) {
// get all master nodes for the selected cluster
// TODO: getKubeconfig: we should make sure, that the master node we're trying to fetch from is actually running
masterNodes, err := runtime.GetNodesByLabel(map[string]string{"k3d.cluster": cluster.Name, "k3d.role": string(k3d.MasterRole)})
masterNodes, err := runtime.GetNodesByLabel(ctx, map[string]string{"k3d.cluster": cluster.Name, "k3d.role": string(k3d.MasterRole)})
if err != nil {
log.Errorln("Failed to get master nodes")
return nil, err
@ -142,7 +143,7 @@ func GetKubeconfig(runtime runtimes.Runtime, cluster *k3d.Cluster) (*clientcmdap
chosenMaster = masterNodes[0]
}
// get the kubeconfig from the first master node
reader, err := runtime.GetKubeconfig(chosenMaster)
reader, err := runtime.GetKubeconfig(ctx, chosenMaster)
if err != nil {
log.Errorf("Failed to get kubeconfig from node '%s'", chosenMaster.Name)
return nil, err
@ -199,7 +200,7 @@ func GetKubeconfig(runtime runtimes.Runtime, cluster *k3d.Cluster) (*clientcmdap
}
// WriteKubeConfigToPath takes a kubeconfig and writes it to some path, which can be '-' for os.Stdout
func WriteKubeConfigToPath(kubeconfig *clientcmdapi.Config, path string) error {
func WriteKubeConfigToPath(ctx context.Context, kubeconfig *clientcmdapi.Config, path string) error {
var output *os.File
defer output.Close()
var err error
@ -234,7 +235,7 @@ func WriteKubeConfigToPath(kubeconfig *clientcmdapi.Config, path string) error {
}
// UpdateKubeConfig merges a new kubeconfig into an existing kubeconfig and returns the result
func UpdateKubeConfig(newKubeConfig *clientcmdapi.Config, existingKubeConfig *clientcmdapi.Config, outPath string, overwriteConflicting bool, updateCurrentContext bool) error {
func UpdateKubeConfig(ctx context.Context, newKubeConfig *clientcmdapi.Config, existingKubeConfig *clientcmdapi.Config, outPath string, overwriteConflicting bool, updateCurrentContext bool) error {
log.Debugf("Merging new KubeConfig:\n%+v\n>>> into existing KubeConfig:\n%+v", newKubeConfig, existingKubeConfig)
@ -277,11 +278,11 @@ func UpdateKubeConfig(newKubeConfig *clientcmdapi.Config, existingKubeConfig *cl
log.Debugf("Merged KubeConfig:\n%+v", existingKubeConfig)
return WriteKubeConfig(existingKubeConfig, outPath)
return WriteKubeConfig(ctx, existingKubeConfig, outPath)
}
// WriteKubeConfig writes a kubeconfig to a path atomically
func WriteKubeConfig(kubeconfig *clientcmdapi.Config, path string) error {
func WriteKubeConfig(ctx context.Context, kubeconfig *clientcmdapi.Config, path string) error {
tempPath := fmt.Sprintf("%s.k3d_%s", path, time.Now().Format("20060102_150405.000000"))
if err := clientcmd.WriteToFile(*kubeconfig, tempPath); err != nil {
log.Errorf("Failed to write merged kubeconfig to temporary file '%s'", tempPath)
@ -319,7 +320,7 @@ func GetDefaultKubeConfigPath() (string, error) {
}
// RemoveClusterFromDefaultKubeConfig removes a cluster's details from the default kubeconfig
func RemoveClusterFromDefaultKubeConfig(cluster *k3d.Cluster) error {
func RemoveClusterFromDefaultKubeConfig(ctx context.Context, cluster *k3d.Cluster) error {
defaultKubeConfigPath, err := GetDefaultKubeConfigPath()
if err != nil {
return err
@ -328,12 +329,12 @@ func RemoveClusterFromDefaultKubeConfig(cluster *k3d.Cluster) error {
if err != nil {
return err
}
kubeconfig = RemoveClusterFromKubeConfig(cluster, kubeconfig)
return WriteKubeConfig(kubeconfig, defaultKubeConfigPath)
kubeconfig = RemoveClusterFromKubeConfig(ctx, cluster, kubeconfig)
return WriteKubeConfig(ctx, kubeconfig, defaultKubeConfigPath)
}
// RemoveClusterFromKubeConfig removes a cluster's details from a given kubeconfig
func RemoveClusterFromKubeConfig(cluster *k3d.Cluster, kubeconfig *clientcmdapi.Config) *clientcmdapi.Config {
func RemoveClusterFromKubeConfig(ctx context.Context, cluster *k3d.Cluster, kubeconfig *clientcmdapi.Config) *clientcmdapi.Config {
clusterName := fmt.Sprintf("%s-%s", k3d.DefaultObjectNamePrefix, cluster.Name)
contextName := fmt.Sprintf("%s-%s", k3d.DefaultObjectNamePrefix, cluster.Name)
authInfoName := fmt.Sprintf("admin@%s-%s", k3d.DefaultObjectNamePrefix, cluster.Name)

@ -22,6 +22,7 @@ THE SOFTWARE.
package cluster
import (
"context"
"fmt"
"github.com/rancher/k3d/pkg/runtimes"
@ -30,7 +31,7 @@ import (
)
// AddMasterToLoadBalancer adds a new master node to the loadbalancer configuration
func AddMasterToLoadBalancer(runtime runtimes.Runtime, cluster *k3d.Cluster, newNode *k3d.Node) error {
func AddMasterToLoadBalancer(ctx context.Context, runtime runtimes.Runtime, cluster *k3d.Cluster, newNode *k3d.Node) error {
// find the LoadBalancer for the target cluster
masterNodes := ""
var loadbalancer *k3d.Node
@ -49,7 +50,7 @@ func AddMasterToLoadBalancer(runtime runtimes.Runtime, cluster *k3d.Cluster, new
log.Debugf("Servers as passed to masterlb: '%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 {
if err := runtime.ExecInNode(ctx, loadbalancer, []string{"sh", "-c", command}); err != nil {
log.Errorln("Failed to update loadbalancer configuration")
return err
}

@ -36,8 +36,8 @@ import (
)
// AddNodeToCluster adds a node to an existing cluster
func AddNodeToCluster(runtime runtimes.Runtime, node *k3d.Node, cluster *k3d.Cluster) error {
cluster, err := GetCluster(cluster, runtime)
func AddNodeToCluster(ctx context.Context, runtime runtimes.Runtime, node *k3d.Node, cluster *k3d.Cluster) error {
cluster, err := GetCluster(ctx, runtime, cluster)
if err != nil {
log.Errorf("Failed to find specified cluster '%s'", cluster.Name)
return err
@ -75,7 +75,7 @@ func AddNodeToCluster(runtime runtimes.Runtime, node *k3d.Node, cluster *k3d.Clu
}
// get node details
chosenNode, err = GetNode(chosenNode, runtime)
chosenNode, err = GetNode(ctx, runtime, chosenNode)
if err != nil {
return err
}
@ -107,13 +107,13 @@ func AddNodeToCluster(runtime runtimes.Runtime, node *k3d.Node, cluster *k3d.Clu
}
}
if err := CreateNode(node, runtime); err != nil {
if err := CreateNode(ctx, runtime, node); 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 {
if err := AddMasterToLoadBalancer(ctx, runtime, cluster, node); err != nil {
log.Errorln("Failed to add new master node to cluster loadbalancer")
return err
}
@ -123,16 +123,16 @@ func AddNodeToCluster(runtime runtimes.Runtime, node *k3d.Node, cluster *k3d.Clu
}
// CreateNodes creates a list of nodes
func CreateNodes(nodes []*k3d.Node, runtime runtimes.Runtime) { // TODO: pass `--atomic` flag, so we stop and return an error if any node creation fails?
func CreateNodes(ctx context.Context, runtime runtimes.Runtime, nodes []*k3d.Node) { // TODO: pass `--atomic` flag, so we stop and return an error if any node creation fails?
for _, node := range nodes {
if err := CreateNode(node, runtime); err != nil {
if err := CreateNode(ctx, runtime, node); err != nil {
log.Error(err)
}
}
}
// CreateNode creates a new containerized k3s node
func CreateNode(node *k3d.Node, runtime runtimes.Runtime) error {
func CreateNode(ctx context.Context, runtime runtimes.Runtime, node *k3d.Node) error {
log.Debugf("Creating node from spec\n%+v", node)
/*
@ -170,7 +170,7 @@ func CreateNode(node *k3d.Node, runtime runtimes.Runtime) error {
/*
* CREATION
*/
if err := runtime.CreateNode(node); err != nil {
if err := runtime.CreateNode(ctx, node); err != nil {
return err
}
@ -178,9 +178,9 @@ func CreateNode(node *k3d.Node, runtime runtimes.Runtime) error {
}
// DeleteNode deletes an existing node
func DeleteNode(runtime runtimes.Runtime, node *k3d.Node) error {
func DeleteNode(ctx context.Context, runtime runtimes.Runtime, node *k3d.Node) error {
if err := runtime.DeleteNode(node); err != nil {
if err := runtime.DeleteNode(ctx, node); err != nil {
log.Error(err)
}
return nil
@ -214,8 +214,8 @@ func patchMasterSpec(node *k3d.Node) error {
}
// GetNodes returns a list of all existing clusters
func GetNodes(runtime runtimes.Runtime) ([]*k3d.Node, error) {
nodes, err := runtime.GetNodesByLabel(k3d.DefaultObjectLabels)
func GetNodes(ctx context.Context, runtime runtimes.Runtime) ([]*k3d.Node, error) {
nodes, err := runtime.GetNodesByLabel(ctx, k3d.DefaultObjectLabels)
if err != nil {
log.Errorln("Failed to get nodes")
return nil, err
@ -225,9 +225,9 @@ func GetNodes(runtime runtimes.Runtime) ([]*k3d.Node, error) {
}
// GetNode returns a node matching the specified node fields
func GetNode(node *k3d.Node, runtime runtimes.Runtime) (*k3d.Node, error) {
func GetNode(ctx context.Context, runtime runtimes.Runtime, node *k3d.Node) (*k3d.Node, error) {
// get node
node, err := runtime.GetNode(node)
node, err := runtime.GetNode(ctx, node)
if err != nil {
log.Errorf("Failed to get node '%s'", node.Name)
}
@ -245,7 +245,7 @@ func WaitForNodeLogMessage(ctx context.Context, runtime runtimes.Runtime, node *
}
// read the logs
out, err := runtime.GetNodeLogs(node, since)
out, err := runtime.GetNodeLogs(ctx, node, since)
if err != nil {
if out != nil {
out.Close()

@ -23,12 +23,13 @@ THE SOFTWARE.
package containerd
import (
"context"
"io"
k3d "github.com/rancher/k3d/pkg/types"
)
// GetKubeconfig grabs the kubeconfig from inside a k3d node
func (d Containerd) GetKubeconfig(node *k3d.Node) (io.ReadCloser, error) {
func (d Containerd) GetKubeconfig(ctx context.Context, node *k3d.Node) (io.ReadCloser, error) {
return nil, nil
}

@ -21,12 +21,14 @@ THE SOFTWARE.
*/
package containerd
import "context"
// CreateNetworkIfNotPresent creates a new docker network
func (d Containerd) CreateNetworkIfNotPresent(name string) (string, bool, error) {
func (d Containerd) CreateNetworkIfNotPresent(ctx context.Context, name string) (string, bool, error) {
return "", false, nil
}
// DeleteNetwork deletes a network
func (d Containerd) DeleteNetwork(ID string) error {
func (d Containerd) DeleteNetwork(ctx context.Context, ID string) error {
return nil
}

@ -34,9 +34,8 @@ import (
)
// CreateNode creates a new k3d node
func (d Containerd) CreateNode(node *k3d.Node) error {
func (d Containerd) CreateNode(ctx context.Context, node *k3d.Node) error {
// create containerd client
ctx := context.Background()
clientOpts := []containerd.ClientOpt{
containerd.WithDefaultNamespace("k3d"),
}
@ -76,8 +75,7 @@ func (d Containerd) CreateNode(node *k3d.Node) error {
}
// DeleteNode deletes an existing k3d node
func (d Containerd) DeleteNode(node *k3d.Node) error {
ctx := context.Background()
func (d Containerd) DeleteNode(ctx context.Context, node *k3d.Node) error {
clientOpts := []containerd.ClientOpt{
containerd.WithDefaultNamespace("k3d"),
}
@ -101,30 +99,30 @@ func (d Containerd) DeleteNode(node *k3d.Node) error {
}
// StartNode starts an existing node
func (d Containerd) StartNode(node *k3d.Node) error {
func (d Containerd) StartNode(ctx context.Context, node *k3d.Node) error {
return nil // TODO: fill
}
// StopNode stops an existing node
func (d Containerd) StopNode(node *k3d.Node) error {
func (d Containerd) StopNode(ctx context.Context, node *k3d.Node) error {
return nil // TODO: fill
}
func (d Containerd) GetNodesByLabel(labels map[string]string) ([]*k3d.Node, error) {
func (d Containerd) GetNodesByLabel(ctx context.Context, labels map[string]string) ([]*k3d.Node, error) {
return nil, nil
}
// GetNode tries to get a node container by its name
func (d Containerd) GetNode(node *k3d.Node) (*k3d.Node, error) {
func (d Containerd) GetNode(ctx context.Context, node *k3d.Node) (*k3d.Node, error) {
return nil, nil
}
// GetNodeLogs returns the logs from a given node
func (d Containerd) GetNodeLogs(node *k3d.Node, since time.Time) (io.ReadCloser, error) {
func (d Containerd) GetNodeLogs(ctx context.Context, node *k3d.Node, since time.Time) (io.ReadCloser, error) {
return nil, nil
}
// ExecInNode execs a command inside a node
func (d Containerd) ExecInNode(node *k3d.Node, cmd []string) error {
func (d Containerd) ExecInNode(ctx context.Context, node *k3d.Node, cmd []string) error {
return nil
}

@ -21,13 +21,15 @@ THE SOFTWARE.
*/
package containerd
import "context"
// CreateVolume creates a new named volume
func (d Containerd) CreateVolume(name string, labels map[string]string) error {
func (d Containerd) CreateVolume(ctx context.Context, name string, labels map[string]string) error {
return nil
}
// DeleteVolume creates a new named volume
func (d Containerd) DeleteVolume(name string) error {
func (d Containerd) DeleteVolume(ctx context.Context, name string) error {
return nil
}

@ -38,12 +38,11 @@ import (
)
// createContainer creates a new docker container from translated specs
func createContainer(dockerNode *NodeInDocker, name string) error {
func createContainer(ctx context.Context, dockerNode *NodeInDocker, name string) error {
log.Debugf("Creating docker container with translated config\n%+v\n", dockerNode) // TODO: remove?
// initialize docker client
ctx := context.Background()
docker, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
log.Errorln("Failed to create docker client")
@ -57,13 +56,13 @@ func createContainer(dockerNode *NodeInDocker, name string) error {
resp, err = docker.ContainerCreate(ctx, &dockerNode.ContainerConfig, &dockerNode.HostConfig, &dockerNode.NetworkingConfig, name)
if err != nil {
if client.IsErrNotFound(err) {
if err := pullImage(&ctx, docker, dockerNode.ContainerConfig.Image); err != nil {
log.Errorln("Failed to create container")
if err := pullImage(ctx, docker, dockerNode.ContainerConfig.Image); err != nil {
log.Errorf("Failed to create container '%s'", name)
return err
}
continue
}
log.Errorln("Failed to create container")
log.Errorf("Failed to create container '%s'", name)
return err
}
log.Debugln("Created container", resp.ID)
@ -80,10 +79,9 @@ func createContainer(dockerNode *NodeInDocker, name string) error {
}
// removeContainer deletes a running container (like docker rm -f)
func removeContainer(ID string) error {
func removeContainer(ctx context.Context, ID string) error {
// (0) create docker client
ctx := context.Background()
docker, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
log.Errorln("Failed to create docker client")
@ -109,9 +107,9 @@ func removeContainer(ID string) error {
}
// pullImage pulls a container image and outputs progress if --verbose flag is set
func pullImage(ctx *context.Context, docker *client.Client, image string) error {
func pullImage(ctx context.Context, docker *client.Client, image string) error {
resp, err := docker.ImagePull(*ctx, image, types.ImagePullOptions{})
resp, err := docker.ImagePull(ctx, image, types.ImagePullOptions{})
if err != nil {
log.Errorf("Failed to pull image '%s'", image)
return err
@ -135,9 +133,8 @@ func pullImage(ctx *context.Context, docker *client.Client, image string) error
}
func getNodeContainer(node *k3d.Node) (*types.Container, error) {
func getNodeContainer(ctx context.Context, node *k3d.Node) (*types.Container, error) {
// (0) create docker client
ctx := context.Background()
docker, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
log.Errorln("Failed to create docker client")

@ -32,8 +32,7 @@ import (
)
// GetKubeconfig grabs the kubeconfig from inside a k3d node
func (d Docker) GetKubeconfig(node *k3d.Node) (io.ReadCloser, error) {
ctx := context.Background()
func (d Docker) GetKubeconfig(ctx context.Context, node *k3d.Node) (io.ReadCloser, error) {
docker, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
log.Errorln("Failed to create docker client")
@ -41,7 +40,7 @@ func (d Docker) GetKubeconfig(node *k3d.Node) (io.ReadCloser, error) {
}
defer docker.Close()
container, err := getNodeContainer(node)
container, err := getNodeContainer(ctx, node)
if err != nil {
return nil, err
}

@ -34,10 +34,9 @@ import (
// CreateNetworkIfNotPresent creates a new docker network
// @return: network name, exists, error
func (d Docker) CreateNetworkIfNotPresent(name string) (string, bool, error) {
func (d Docker) CreateNetworkIfNotPresent(ctx context.Context, name string) (string, bool, error) {
// (0) create new docker client
ctx := context.Background()
docker, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
log.Errorln("Failed to create docker client")
@ -82,9 +81,8 @@ func (d Docker) CreateNetworkIfNotPresent(name string) (string, bool, error) {
}
// DeleteNetwork deletes a network
func (d Docker) DeleteNetwork(ID string) error {
func (d Docker) DeleteNetwork(ctx context.Context, ID string) error {
// (0) create new docker client
ctx := context.Background()
docker, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
log.Errorln("Failed to create docker client")
@ -97,8 +95,7 @@ func (d Docker) DeleteNetwork(ID string) error {
}
// GetNetwork gets information about a network by its ID
func GetNetwork(ID string) (types.NetworkResource, error) {
ctx := context.Background()
func GetNetwork(ctx context.Context, ID string) (types.NetworkResource, error) {
docker, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
log.Errorln("Failed to create docker client")

@ -37,7 +37,7 @@ import (
)
// CreateNode creates a new container
func (d Docker) CreateNode(node *k3d.Node) error {
func (d Docker) CreateNode(ctx context.Context, node *k3d.Node) error {
// translate node spec to docker container specs
dockerNode, err := TranslateNodeToContainer(node)
@ -47,8 +47,8 @@ func (d Docker) CreateNode(node *k3d.Node) error {
}
// create node
if err := createContainer(dockerNode, node.Name); err != nil {
log.Errorln("Failed to create k3d node")
if err := createContainer(ctx, dockerNode, node.Name); err != nil {
log.Errorf("Failed to create node '%s'", node.Name)
return err
}
@ -56,15 +56,15 @@ func (d Docker) CreateNode(node *k3d.Node) error {
}
// DeleteNode deletes a node
func (d Docker) DeleteNode(nodeSpec *k3d.Node) error {
return removeContainer(nodeSpec.Name)
func (d Docker) DeleteNode(ctx context.Context, nodeSpec *k3d.Node) error {
return removeContainer(ctx, nodeSpec.Name)
}
// GetNodesByLabel returns a list of existing nodes
func (d Docker) GetNodesByLabel(labels map[string]string) ([]*k3d.Node, error) {
func (d Docker) GetNodesByLabel(ctx context.Context, labels map[string]string) ([]*k3d.Node, error) {
// (0) get containers
containers, err := getContainersByLabel(labels)
containers, err := getContainersByLabel(ctx, labels)
if err != nil {
return nil, err
}
@ -84,9 +84,8 @@ func (d Docker) GetNodesByLabel(labels map[string]string) ([]*k3d.Node, error) {
}
// StartNode starts an existing node
func (d Docker) StartNode(node *k3d.Node) error {
func (d Docker) StartNode(ctx context.Context, node *k3d.Node) error {
// (0) create docker client
ctx := context.Background()
docker, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
return fmt.Errorf("Failed to create docker client. %+v", err)
@ -94,7 +93,7 @@ func (d Docker) StartNode(node *k3d.Node) error {
defer docker.Close()
// get container which represents the node
nodeContainer, err := getNodeContainer(node)
nodeContainer, err := getNodeContainer(ctx, node)
if err != nil {
log.Errorf("Failed to get container for node '%s'", node.Name)
return err
@ -115,9 +114,8 @@ func (d Docker) StartNode(node *k3d.Node) error {
}
// StopNode stops an existing node
func (d Docker) StopNode(node *k3d.Node) error {
func (d Docker) StopNode(ctx context.Context, node *k3d.Node) error {
// (0) create docker client
ctx := context.Background()
docker, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
return fmt.Errorf("Failed to create docker client. %+v", err)
@ -125,7 +123,7 @@ func (d Docker) StopNode(node *k3d.Node) error {
defer docker.Close()
// get container which represents the node
nodeContainer, err := getNodeContainer(node)
nodeContainer, err := getNodeContainer(ctx, node)
if err != nil {
log.Errorf("Failed to get container for node '%s'", node.Name)
return err
@ -144,9 +142,8 @@ func (d Docker) StopNode(node *k3d.Node) error {
return nil
}
func getContainersByLabel(labels map[string]string) ([]types.Container, error) {
func getContainersByLabel(ctx context.Context, labels map[string]string) ([]types.Container, error) {
// (0) create docker client
ctx := context.Background()
docker, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
return nil, fmt.Errorf("Failed to create docker client. %+v", err)
@ -175,9 +172,8 @@ func getContainersByLabel(labels map[string]string) ([]types.Container, error) {
}
// getContainer details returns the containerjson with more details
func getContainerDetails(containerID string) (types.ContainerJSON, error) {
func getContainerDetails(ctx context.Context, 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)
@ -195,14 +191,14 @@ func getContainerDetails(containerID string) (types.ContainerJSON, error) {
}
// GetNode tries to get a node container by its name
func (d Docker) GetNode(node *k3d.Node) (*k3d.Node, error) {
container, err := getNodeContainer(node)
func (d Docker) GetNode(ctx context.Context, node *k3d.Node) (*k3d.Node, error) {
container, err := getNodeContainer(ctx, node)
if err != nil {
log.Errorf("Failed to get container for node '%s'", node.Name)
return node, err
}
containerDetails, err := getContainerDetails(container.ID)
containerDetails, err := getContainerDetails(ctx, container.ID)
if err != nil {
return node, err
}
@ -218,15 +214,14 @@ func (d Docker) GetNode(node *k3d.Node) (*k3d.Node, error) {
}
// GetNodeLogs returns the logs from a given node
func (d Docker) GetNodeLogs(node *k3d.Node, since time.Time) (io.ReadCloser, error) {
func (d Docker) GetNodeLogs(ctx context.Context, node *k3d.Node, since time.Time) (io.ReadCloser, error) {
// get the container for the given node
container, err := getNodeContainer(node)
container, err := getNodeContainer(ctx, node)
if err != nil {
return nil, err
}
// create docker client
ctx := context.Background()
docker, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
log.Errorln("Failed to create docker client")
@ -258,18 +253,17 @@ func (d Docker) GetNodeLogs(node *k3d.Node, since time.Time) (io.ReadCloser, err
}
// ExecInNode execs a command inside a node
func (d Docker) ExecInNode(node *k3d.Node, cmd []string) error {
func (d Docker) ExecInNode(ctx context.Context, node *k3d.Node, cmd []string) error {
log.Debugf("Executing command '%+v' in node '%s'", cmd, node.Name)
// get the container for the given node
container, err := getNodeContainer(node)
container, err := getNodeContainer(ctx, node)
if err != nil {
return err
}
// create docker client
ctx := context.Background()
docker, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
log.Errorln("Failed to create docker client")

@ -23,6 +23,7 @@ THE SOFTWARE.
package docker
import (
"context"
"fmt"
"strings"
@ -94,7 +95,7 @@ func TranslateNodeToContainer(node *k3d.Node) (*NodeInDocker, error) {
networkingConfig.EndpointsConfig = map[string]*network.EndpointSettings{
node.Network: {},
}
netInfo, err := GetNetwork(node.Network)
netInfo, err := GetNetwork(context.Background(), node.Network)
if err != nil {
log.Warnln("Failed to get network information")
log.Warnln(err)

@ -33,9 +33,8 @@ import (
)
// CreateVolume creates a new named volume
func (d Docker) CreateVolume(name string, labels map[string]string) error {
func (d Docker) CreateVolume(ctx context.Context, name string, labels map[string]string) error {
// (0) create new docker client
ctx := context.Background()
docker, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
log.Errorln("Failed to create docker client")
@ -64,9 +63,8 @@ func (d Docker) CreateVolume(name string, labels map[string]string) error {
}
// DeleteVolume creates a new named volume
func (d Docker) DeleteVolume(name string) error {
func (d Docker) DeleteVolume(ctx context.Context, name string) error {
// (0) create new docker client
ctx := context.Background()
docker, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
log.Errorln("Failed to create docker client")

@ -22,6 +22,7 @@ THE SOFTWARE.
package runtimes
import (
"context"
"fmt"
"io"
"time"
@ -42,22 +43,21 @@ var Runtimes = map[string]Runtime{
// Runtime defines an interface that can be implemented for various container runtime environments (docker, containerd, etc.)
type Runtime interface {
CreateNode(*k3d.Node) error
DeleteNode(*k3d.Node) error
GetNodesByLabel(map[string]string) ([]*k3d.Node, error)
GetNode(*k3d.Node) (*k3d.Node, error)
CreateNetworkIfNotPresent(name string) (string, bool, error) // @return NETWORK_NAME, EXISTS, ERROR
GetKubeconfig(*k3d.Node) (io.ReadCloser, error)
DeleteNetwork(ID string) error
StartNode(*k3d.Node) error
StopNode(*k3d.Node) error
CreateVolume(string, map[string]string) error
DeleteVolume(string) error
CreateNode(context.Context, *k3d.Node) error
DeleteNode(context.Context, *k3d.Node) error
GetNodesByLabel(context.Context, map[string]string) ([]*k3d.Node, error)
GetNode(context.Context, *k3d.Node) (*k3d.Node, error)
CreateNetworkIfNotPresent(context.Context, string) (string, bool, error) // @return NETWORK_NAME, EXISTS, ERROR
GetKubeconfig(context.Context, *k3d.Node) (io.ReadCloser, error)
DeleteNetwork(context.Context, string) error
StartNode(context.Context, *k3d.Node) error
StopNode(context.Context, *k3d.Node) error
CreateVolume(context.Context, string, map[string]string) error
DeleteVolume(context.Context, string) error
GetVolume(string) (string, error)
GetRuntimePath() string // returns e.g. '/var/run/docker.sock' for a default docker setup
ExecInNode(*k3d.Node, []string) error
// DeleteContainer() error
GetNodeLogs(*k3d.Node, time.Time) (io.ReadCloser, error)
ExecInNode(context.Context, *k3d.Node, []string) error
GetNodeLogs(context.Context, *k3d.Node, time.Time) (io.ReadCloser, error)
}
// GetRuntime checks, if a given name is represented by an implemented k3d runtime and returns it

@ -22,6 +22,7 @@ THE SOFTWARE.
package tools
import (
"context"
"fmt"
"sync"
"time"
@ -34,8 +35,8 @@ import (
// LoadImagesIntoCluster starts up a k3d tools container for the selected cluster and uses it to export
// images from the runtime to import them into the nodes of the selected cluster
func LoadImagesIntoCluster(runtime runtimes.Runtime, images []string, cluster *k3d.Cluster, keepTarball bool) error {
cluster, err := k3dc.GetCluster(cluster, runtime)
func LoadImagesIntoCluster(ctx context.Context, runtime runtimes.Runtime, images []string, cluster *k3d.Cluster, keepTarball bool) error {
cluster, err := k3dc.GetCluster(ctx, runtime, cluster)
if err != nil {
log.Errorf("Failed to find the specified cluster")
return err
@ -63,6 +64,7 @@ func LoadImagesIntoCluster(runtime runtimes.Runtime, images []string, cluster *k
// create tools node to export images
log.Infoln("Starting k3d-tools node...")
toolsNode, err := startToolsNode( // TODO: re-use existing container
ctx,
runtime,
cluster,
cluster.Network.Name,
@ -77,7 +79,7 @@ func LoadImagesIntoCluster(runtime runtimes.Runtime, images []string, cluster *k
// save image to tarfile in shared volume
log.Infoln("Saving images...")
tarName := fmt.Sprintf("%s/k3d-%s-images-%s.tar", k3d.DefaultImageVolumeMountPath, cluster.Name, time.Now().Format("20060102150405")) // FIXME: change
if err := runtime.ExecInNode(toolsNode, append([]string{"./k3d-tools", "save-image", "-d", tarName}, images...)); err != nil {
if err := runtime.ExecInNode(ctx, toolsNode, append([]string{"./k3d-tools", "save-image", "-d", tarName}, images...)); err != nil {
log.Errorf("Failed to save images in tools container for cluster '%s'", cluster.Name)
return err
}
@ -91,7 +93,7 @@ func LoadImagesIntoCluster(runtime runtimes.Runtime, images []string, cluster *k
importWaitgroup.Add(1)
go func(node *k3d.Node, wg *sync.WaitGroup) {
log.Infof("Importing images into node '%s'...", node.Name)
if err := runtime.ExecInNode(node, []string{"ctr", "image", "import", tarName}); err != nil {
if err := runtime.ExecInNode(ctx, node, []string{"ctr", "image", "import", tarName}); err != nil {
log.Errorf("Failed to import images in node '%s'", node.Name)
log.Errorln(err)
}
@ -104,7 +106,7 @@ func LoadImagesIntoCluster(runtime runtimes.Runtime, images []string, cluster *k
// remove tarball
if !keepTarball {
log.Infoln("Removing the tarball...")
if err := runtime.ExecInNode(cluster.Nodes[0], []string{"rm", "-f", tarName}); err != nil { // TODO: do this in tools node (requires rm)
if err := runtime.ExecInNode(ctx, cluster.Nodes[0], []string{"rm", "-f", tarName}); err != nil { // TODO: do this in tools node (requires rm)
log.Errorf("Failed to delete tarball '%s'", tarName)
log.Errorln(err)
}
@ -112,7 +114,7 @@ func LoadImagesIntoCluster(runtime runtimes.Runtime, images []string, cluster *k
// delete tools container
log.Infoln("Removing k3d-tools node...")
if err := runtime.DeleteNode(toolsNode); err != nil {
if err := runtime.DeleteNode(ctx, toolsNode); err != nil {
log.Errorln("Failed to delete tools node '%s': Try to delete it manually", toolsNode.Name)
}
@ -123,7 +125,7 @@ func LoadImagesIntoCluster(runtime runtimes.Runtime, images []string, cluster *k
}
// startToolsNode will start a new k3d tools container and connect it to the network of the chosen cluster
func startToolsNode(runtime runtimes.Runtime, cluster *k3d.Cluster, network string, volumes []string) (*k3d.Node, error) {
func startToolsNode(ctx context.Context, runtime runtimes.Runtime, cluster *k3d.Cluster, network string, volumes []string) (*k3d.Node, error) {
node := &k3d.Node{
Name: fmt.Sprintf("%s-%s-tools", k3d.DefaultObjectNamePrefix, cluster.Name),
Image: k3d.DefaultToolsContainerImage,
@ -133,7 +135,7 @@ func startToolsNode(runtime runtimes.Runtime, cluster *k3d.Cluster, network stri
Cmd: []string{},
Args: []string{"noop"},
}
if err := runtime.CreateNode(node); err != nil {
if err := runtime.CreateNode(ctx, node); err != nil {
log.Errorf("Failed to create tools container for cluster '%s'", cluster.Name)
return node, err
}

Loading…
Cancel
Save