Skip to content

Commit

Permalink
Merge pull request #57 from srl-labs/feat/tail-nos-container-logs
Browse files Browse the repository at this point in the history
feat: tee node logs to pod logs
  • Loading branch information
carlmontanari authored Oct 20, 2023
2 parents 5baa382 + 9da97f6 commit e82aad1
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 13 deletions.
74 changes: 67 additions & 7 deletions launcher/clabernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (

const (
maxDockerLaunchAttempts = 10
containerCheckInterval = 5 * time.Second
)

// StartClabernetes is a function that starts the clabernetes launcher.
Expand All @@ -38,15 +39,28 @@ func StartClabernetes() {
),
)

ctx, _ := clabernetesutil.SignalHandledContext(clabernetesLogger.Criticalf)
containerlabLogger := logManager.MustRegisterAndGetLogger(
"containerlab",
clabernetesconstants.Info,
)

nodeLogger := logManager.MustRegisterAndGetLogger(
"node",
clabernetesconstants.Info,
)

ctx, cancel := clabernetesutil.SignalHandledContext(clabernetesLogger.Criticalf)

clabernetesInstance = &clabernetes{
ctx: ctx,
ctx: ctx,
cancel: cancel,
appName: clabernetesutil.GetEnvStrOrDefault(
clabernetesconstants.AppNameEnvVar,
clabernetesconstants.AppNameDefault,
),
logger: clabernetesLogger,
logger: clabernetesLogger,
containerlabLogger: containerlabLogger,
nodeLogger: nodeLogger,
}

clabernetesInstance.startup()
Expand All @@ -55,11 +69,16 @@ func StartClabernetes() {
var clabernetesInstance *clabernetes //nolint:gochecknoglobals

type clabernetes struct {
ctx context.Context
ctx context.Context
cancel context.CancelFunc

appName string

logger claberneteslogging.Instance
logger claberneteslogging.Instance
containerlabLogger claberneteslogging.Instance
nodeLogger claberneteslogging.Instance

containerIDs []string
}

func (c *clabernetes) startup() {
Expand All @@ -70,9 +89,13 @@ func (c *clabernetes) startup() {
c.setup()
c.launch()

go c.watch()

c.logger.Info("running for forever or until sigint...")

<-c.ctx.Done()

claberneteslogging.GetManager().Flush()
}

func (c *clabernetes) setup() {
Expand Down Expand Up @@ -115,13 +138,26 @@ func (c *clabernetes) setup() {
func (c *clabernetes) launch() {
c.logger.Debug("launching containerlab...")

err := c.runClab()
err := c.runContainerlab()
if err != nil {
c.logger.Criticalf("failed launching containerlab, err: %s", err)

clabernetesutil.Panic(err.Error())
}

c.containerIDs = c.getContainerIDs()

if len(c.containerIDs) > 0 {
c.logger.Debugf("found container ids %q", c.containerIDs)

c.tailContainerLogs()
} else {
c.logger.Warn(
"failed determining container ids, will continue but may not be in a working " +
"state and no container logs will be captured",
)
}

c.logger.Info("containerlab started, setting up any required tunnels...")

tunnelBytes, err := os.ReadFile("tunnels.yaml")
Expand All @@ -141,7 +177,7 @@ func (c *clabernetes) launch() {
}

for _, tunnel := range tunnelObj {
err = c.runClabVxlanTools(
err = c.runContainerlabVxlanTools(
tunnel.LocalNodeName,
tunnel.LocalLinkName,
tunnel.RemoteName,
Expand All @@ -159,3 +195,27 @@ func (c *clabernetes) launch() {
}
}
}

func (c *clabernetes) watch() {
if len(c.containerIDs) == 0 {
return
}

ticker := time.NewTicker(containerCheckInterval)

for range ticker.C {
currentContainerIDs := c.getContainerIDs()

if len(currentContainerIDs) != len(c.containerIDs) {
c.logger.Criticalf(
"expected %d running containers, but got %d, sending done signal",
len(c.containerIDs),
len(currentContainerIDs),
)

c.cancel()

return
}
}
}
12 changes: 6 additions & 6 deletions launcher/containerlab.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import (
claberneteserrors "github.com/srl-labs/clabernetes/errors"
)

func (c *clabernetes) runClab() error {
clabLogFile, err := os.Create("clab.log")
func (c *clabernetes) runContainerlab() error {
containerlabLogFile, err := os.Create("containerlab.log")
if err != nil {
return err
}

clabOutWriter := io.MultiWriter(c.logger, clabLogFile)
containerlabOutWriter := io.MultiWriter(c.containerlabLogger, containerlabLogFile)

args := []string{
"deploy",
Expand All @@ -31,8 +31,8 @@ func (c *clabernetes) runClab() error {

cmd := exec.Command("containerlab", args...)

cmd.Stdout = clabOutWriter
cmd.Stderr = clabOutWriter
cmd.Stdout = containerlabOutWriter
cmd.Stderr = containerlabOutWriter

err = cmd.Run()
if err != nil {
Expand All @@ -42,7 +42,7 @@ func (c *clabernetes) runClab() error {
return nil
}

func (c *clabernetes) runClabVxlanTools(
func (c *clabernetes) runContainerlabVxlanTools(
localNodeName, cntLink, vxlanRemote string,
vxlanID int,
) error {
Expand Down
64 changes: 64 additions & 0 deletions launcher/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package launcher
import (
"bytes"
"fmt"
"io"
"os"
"os/exec"
"strings"
Expand Down Expand Up @@ -103,3 +104,66 @@ func (c *clabernetes) startDocker() error {
attempts++
}
}

func (c *clabernetes) getContainerIDs() []string {
// return all the container ids running in the pod
psCmd := exec.Command("docker", "ps", "--quiet")

output, err := psCmd.Output()
if err != nil {
c.logger.Warnf(
"failed determining container ids will continue but will not log container output,"+
" err: %s",
err,
)

return nil
}

containerIDLines := strings.Split(string(output), "\n")

var containerIDs []string

for _, line := range containerIDLines {
trimmedLine := strings.TrimSpace(line)

if trimmedLine != "" {
containerIDs = append(containerIDs, trimmedLine)
}
}

return containerIDs
}

func (c *clabernetes) tailContainerLogs() {
nodeLogFile, err := os.Create("node.log")
if err != nil {
c.logger.Warnf("failed creating node log file, err: %s", err)

return
}

nodeOutWriter := io.MultiWriter(c.nodeLogger, nodeLogFile)

for _, containerID := range c.containerIDs {
go func(containerID string, nodeOutWriter io.Writer) {
args := []string{
"logs",
"-f",
containerID,
}

cmd := exec.Command("docker", args...) //nolint:gosec

cmd.Stdout = nodeOutWriter
cmd.Stderr = nodeOutWriter

err = cmd.Run()
if err != nil {
c.logger.Warnf(
"tailing node logs for container id %q failed, err: %s", containerID, err,
)
}
}(containerID, nodeOutWriter)
}
}

0 comments on commit e82aad1

Please sign in to comment.