diff --git a/pkg/cluster/cluster.go b/pkg/cluster/cluster.go index 4436e78c..f32d8bd1 100644 --- a/pkg/cluster/cluster.go +++ b/pkg/cluster/cluster.go @@ -22,8 +22,10 @@ THE SOFTWARE. package cluster import ( + "bytes" "fmt" "strings" + "time" k3drt "github.com/rancher/k3d/pkg/runtimes" k3d "github.com/rancher/k3d/pkg/types" @@ -125,8 +127,32 @@ func CreateCluster(cluster *k3d.Cluster, runtime k3drt.Runtime) error { return err } masterCount++ + + // wait for the initnode to come up before doing anything else + for { + log.Debugln("Waiting for initializing master node...") + logreader, err := runtime.GetNodeLogs(cluster.InitNode) + defer logreader.Close() + if err != nil { + logreader.Close() + log.Errorln(err) + log.Errorln("Failed to get logs from the initializig master node.. waiting for 3 seconds instead") + time.Sleep(3 * time.Second) + goto initNodeFinished + } + buf := new(bytes.Buffer) + nRead, _ := buf.ReadFrom(logreader) + logreader.Close() + if nRead > 0 && strings.Contains(buf.String(), "Running kubelet") { + log.Debugln("Initializing master node is up... continuing") + break + } + time.Sleep(time.Second) // TODO: timeout + } + } +initNodeFinished: // create all other nodes, but skip the init node for _, node := range cluster.Nodes { if node.Role == k3d.MasterRole { diff --git a/pkg/runtimes/containerd/node.go b/pkg/runtimes/containerd/node.go index 8a886448..c3b3e552 100644 --- a/pkg/runtimes/containerd/node.go +++ b/pkg/runtimes/containerd/node.go @@ -24,6 +24,7 @@ package containerd import ( "context" + "io" "github.com/containerd/containerd" "github.com/containerd/containerd/containers" @@ -119,3 +120,8 @@ func (d Containerd) GetNodesByLabel(labels map[string]string) ([]*k3d.Node, erro func (d Containerd) GetNode(node *k3d.Node) (*k3d.Node, error) { return nil, nil } + +// GetNodeLogs returns the logs from a given node +func (d Containerd) GetNodeLogs(node *k3d.Node) (io.ReadCloser, error) { + return nil, nil +} diff --git a/pkg/runtimes/docker/node.go b/pkg/runtimes/docker/node.go index 3db3eb47..01e4e3fe 100644 --- a/pkg/runtimes/docker/node.go +++ b/pkg/runtimes/docker/node.go @@ -25,6 +25,7 @@ package docker import ( "context" "fmt" + "io" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" @@ -185,3 +186,28 @@ func (d Docker) GetNode(node *k3d.Node) (*k3d.Node, error) { return node, nil } + +// GetNodeLogs returns the logs from a given node +func (d Docker) GetNodeLogs(node *k3d.Node) (io.ReadCloser, error) { + // get the container for the given node + container, err := getNodeContainer(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") + return nil, err + } + + logreader, err := docker.ContainerLogs(ctx, container.ID, types.ContainerLogsOptions{ShowStdout: true, ShowStderr: true}) + if err != nil { + log.Errorf("Failed to get logs from node '%s' (container '%s')", node.Name, container.ID) + return nil, err + } + + return logreader, nil +} diff --git a/pkg/runtimes/runtime.go b/pkg/runtimes/runtime.go index 6ccdf488..05fabe7f 100644 --- a/pkg/runtimes/runtime.go +++ b/pkg/runtimes/runtime.go @@ -49,7 +49,7 @@ type Runtime interface { StopNode(*k3d.Node) error // ExecContainer() error // DeleteContainer() error - // GetContainerLogs() error + GetNodeLogs(*k3d.Node) (io.ReadCloser, error) } // GetRuntime checks, if a given name is represented by an implemented k3d runtime and returns it