getNodeLogs: accept time.Time parameter

- fixes startCluster's --wait/--timeout functionality
--> now doesn't check all the logs (e.g. from previous run)
----> no more false positives when checking for a specifc log message
only in the current run
pull/252/head
iwilltry42 4 years ago
parent b6e3babb4a
commit 99f5a6884a
No known key found for this signature in database
GPG Key ID: 7BA57AD1CFF16110
  1. 26
      pkg/cluster/cluster.go
  2. 4
      pkg/cluster/node.go
  3. 3
      pkg/runtimes/containerd/node.go
  4. 8
      pkg/runtimes/docker/node.go
  5. 3
      pkg/runtimes/runtime.go
  6. 5
      tests/test_full_lifecycle.sh

@ -192,7 +192,7 @@ func CreateCluster(ctx context.Context, cluster *k3d.Cluster, runtime k3drt.Runt
default: default:
} }
log.Debugln("Waiting for initializing master node...") log.Debugln("Waiting for initializing master node...")
logreader, err := runtime.GetNodeLogs(cluster.InitNode) logreader, err := runtime.GetNodeLogs(cluster.InitNode, time.Time{})
if err != nil { if err != nil {
if logreader != nil { if logreader != nil {
logreader.Close() logreader.Close()
@ -254,7 +254,7 @@ func CreateCluster(ctx context.Context, cluster *k3d.Cluster, runtime k3drt.Runt
// TODO: avoid `level=fatal msg="starting kubernetes: preparing server: post join: a configuration change is already in progress (5)"` // 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 // ... by scanning for this line in logs and restarting the container in case it appears
log.Debugf("Starting to wait for master node '%s'", masterNode.Name) log.Debugf("Starting to wait for master node '%s'", masterNode.Name)
return WaitForNodeLogMessage(ctx, runtime, masterNode, "Wrote kubeconfig") return WaitForNodeLogMessage(ctx, runtime, masterNode, "Wrote kubeconfig", time.Time{})
}) })
} }
} }
@ -475,6 +475,8 @@ func generateNodeName(cluster string, role k3d.Role, suffix int) string {
func StartCluster(ctx context.Context, cluster *k3d.Cluster, runtime k3drt.Runtime, startClusterOpts types.StartClusterOpts) error { func StartCluster(ctx context.Context, cluster *k3d.Cluster, runtime k3drt.Runtime, startClusterOpts types.StartClusterOpts) error {
log.Infof("Starting cluster '%s'", cluster.Name) log.Infof("Starting cluster '%s'", cluster.Name)
start := time.Now()
if startClusterOpts.Timeout > 0*time.Second { if startClusterOpts.Timeout > 0*time.Second {
var cancel context.CancelFunc var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, startClusterOpts.Timeout) ctx, cancel = context.WithTimeout(ctx, startClusterOpts.Timeout)
@ -508,17 +510,11 @@ func StartCluster(ctx context.Context, cluster *k3d.Cluster, runtime k3drt.Runti
// TODO: avoid `level=fatal msg="starting kubernetes: preparing server: post join: a configuration change is already in progress (5)"` // 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 // ... by scanning for this line in logs and restarting the container in case it appears
log.Debugf("Starting to wait for master node '%s'", masterNode.Name) log.Debugf("Starting to wait for master node '%s'", masterNode.Name)
return WaitForNodeLogMessage(ctx, runtime, masterNode, "Wrote kubeconfig") return WaitForNodeLogMessage(ctx, runtime, masterNode, "Wrote kubeconfig", start)
}) })
} }
} }
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")
}
// start masterlb // start masterlb
if masterlb != nil { if masterlb != nil {
log.Debugln("Starting masterlb...") log.Debugln("Starting masterlb...")
@ -526,6 +522,18 @@ func StartCluster(ctx context.Context, cluster *k3d.Cluster, runtime k3drt.Runti
log.Warningf("Failed to start masterlb '%s': Try to start it manually", masterlb.Name) log.Warningf("Failed to start masterlb '%s': Try to start it manually", masterlb.Name)
failed++ failed++
} }
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'", masterlb.Name)
return WaitForNodeLogMessage(ctx, runtime, masterlb, "start worker processes", start)
})
}
if err := waitForMasterWaitgroup.Wait(); err != nil {
log.Errorln("Failed to bring up all nodes in time. Check the logs:")
log.Errorln(">>> ", err)
return fmt.Errorf("Failed to bring up cluster")
} }
if failed > 0 { if failed > 0 {

@ -233,7 +233,7 @@ func GetNode(node *k3d.Node, runtime runtimes.Runtime) (*k3d.Node, error) {
} }
// WaitForNodeLogMessage follows the logs of a node container and returns if it finds a specific line in there (or timeout is reached) // WaitForNodeLogMessage follows the logs of a node container and returns if it finds a specific line in there (or timeout is reached)
func WaitForNodeLogMessage(ctx context.Context, runtime runtimes.Runtime, node *k3d.Node, message string) error { func WaitForNodeLogMessage(ctx context.Context, runtime runtimes.Runtime, node *k3d.Node, message string, since time.Time) error {
for { for {
select { select {
case <-ctx.Done(): case <-ctx.Done():
@ -242,7 +242,7 @@ func WaitForNodeLogMessage(ctx context.Context, runtime runtimes.Runtime, node *
} }
// read the logs // read the logs
out, err := runtime.GetNodeLogs(node) out, err := runtime.GetNodeLogs(node, since)
if err != nil { if err != nil {
if out != nil { if out != nil {
out.Close() out.Close()

@ -25,6 +25,7 @@ package containerd
import ( import (
"context" "context"
"io" "io"
"time"
"github.com/containerd/containerd" "github.com/containerd/containerd"
"github.com/containerd/containerd/containers" "github.com/containerd/containerd/containers"
@ -119,7 +120,7 @@ func (d Containerd) GetNode(node *k3d.Node) (*k3d.Node, error) {
} }
// GetNodeLogs returns the logs from a given node // GetNodeLogs returns the logs from a given node
func (d Containerd) GetNodeLogs(node *k3d.Node) (io.ReadCloser, error) { func (d Containerd) GetNodeLogs(node *k3d.Node, since time.Time) (io.ReadCloser, error) {
return nil, nil return nil, nil
} }

@ -218,7 +218,7 @@ func (d Docker) GetNode(node *k3d.Node) (*k3d.Node, error) {
} }
// GetNodeLogs returns the logs from a given node // GetNodeLogs returns the logs from a given node
func (d Docker) GetNodeLogs(node *k3d.Node) (io.ReadCloser, error) { func (d Docker) GetNodeLogs(node *k3d.Node, since time.Time) (io.ReadCloser, error) {
// get the container for the given node // get the container for the given node
container, err := getNodeContainer(node) container, err := getNodeContainer(node)
if err != nil { if err != nil {
@ -244,7 +244,11 @@ func (d Docker) GetNodeLogs(node *k3d.Node) (io.ReadCloser, error) {
return nil, fmt.Errorf("Node '%s' (container '%s') not running", node.Name, containerInspectResponse.ID) return nil, fmt.Errorf("Node '%s' (container '%s') not running", node.Name, containerInspectResponse.ID)
} }
logreader, err := docker.ContainerLogs(ctx, container.ID, types.ContainerLogsOptions{ShowStdout: true, ShowStderr: true}) sinceStr := ""
if !since.IsZero() {
sinceStr = since.Format("2006-01-02T15:04:05")
}
logreader, err := docker.ContainerLogs(ctx, container.ID, types.ContainerLogsOptions{ShowStdout: true, ShowStderr: true, Since: sinceStr})
if err != nil { if err != nil {
log.Errorf("Failed to get logs from node '%s' (container '%s')", node.Name, container.ID) log.Errorf("Failed to get logs from node '%s' (container '%s')", node.Name, container.ID)
return nil, err return nil, err

@ -24,6 +24,7 @@ package runtimes
import ( import (
"fmt" "fmt"
"io" "io"
"time"
"github.com/rancher/k3d/pkg/runtimes/containerd" "github.com/rancher/k3d/pkg/runtimes/containerd"
"github.com/rancher/k3d/pkg/runtimes/docker" "github.com/rancher/k3d/pkg/runtimes/docker"
@ -56,7 +57,7 @@ type Runtime interface {
GetRuntimePath() string // returns e.g. '/var/run/docker.sock' for a default docker setup GetRuntimePath() string // returns e.g. '/var/run/docker.sock' for a default docker setup
ExecInNode(*k3d.Node, []string) error ExecInNode(*k3d.Node, []string) error
// DeleteContainer() error // DeleteContainer() error
GetNodeLogs(*k3d.Node) (io.ReadCloser, error) GetNodeLogs(*k3d.Node, time.Time) (io.ReadCloser, error)
} }
// GetRuntime checks, if a given name is represented by an implemented k3d runtime and returns it // GetRuntime checks, if a given name is represented by an implemented k3d runtime and returns it

@ -30,10 +30,7 @@ check_clusters "$clustername" && failed "cluster was not stopped, since we still
# 3. start the cluster # 3. start the cluster
info "Starting cluster..." info "Starting cluster..."
$EXE start cluster "$clustername" $EXE start cluster "$clustername" --wait --timeout 360s || failed "cluster didn't come back in time"
info "Sleeping for 5 seconds to give the cluster enough time to get ready..."
sleep 5
info "Checking that we have access to the cluster..." info "Checking that we have access to the cluster..."
check_clusters "$clustername" || failed "error checking cluster" check_clusters "$clustername" || failed "error checking cluster"

Loading…
Cancel
Save