diff --git a/cmd/cluster/cluster.go b/cmd/cluster/cluster.go index f9221f416..c6f931147 100644 --- a/cmd/cluster/cluster.go +++ b/cmd/cluster/cluster.go @@ -48,8 +48,7 @@ func NewCmdCluster() *cobra.Command { NewCmdClusterStop(), NewCmdClusterDelete(), NewCmdClusterList(), - NewCmdClusterEdit(), - ) + NewCmdClusterEdit()) // add flags diff --git a/cmd/debug/debug.go b/cmd/debug/debug.go index 32bc6126e..aa584674d 100644 --- a/cmd/debug/debug.go +++ b/cmd/debug/debug.go @@ -23,8 +23,6 @@ package debug import ( "fmt" - "os" - "path/filepath" "github.com/spf13/cobra" "sigs.k8s.io/yaml" @@ -36,10 +34,6 @@ import ( "github.com/k3d-io/k3d/v5/pkg/types" ) -var nodeName string -var exportPath string -var components []string - // NewCmdDebug returns a new cobra command func NewCmdDebug() *cobra.Command { cmd := &cobra.Command{ @@ -56,42 +50,6 @@ func NewCmdDebug() *cobra.Command { } cmd.AddCommand(NewCmdDebugLoadbalancer()) - cmd.AddCommand(NewCmdExportLogs()) - return cmd -} - -func NewCmdExportLogs() *cobra.Command { - cmd := &cobra.Command{ - Use: "export-logs CLUSTER", - Short: "Export logs of a k3d cluster", - Long: "Export logs of a k3d cluster for all nodes or selective nodes using filters", - ValidArgsFunction: util.ValidArgsAvailableClusters, - Run: func(cmd *cobra.Command, args []string) { - if len(args) == 0 || len(args[0]) == 0 { - l.Log().Fatalln("Cluster name is required") - } - cluster, err := client.ClusterGet(cmd.Context(), runtimes.SelectedRuntime, &types.Cluster{Name: args[0]}) - if err != nil { - l.Log().Fatalln(err) - } - exportPath = filepath.Join(exportPath, fmt.Sprintf("debug-logs-%s", cluster.Name)) - for _, node := range cluster.Nodes { - if nodeName == "" || nodeName == node.Name { - if err := runtimes.SelectedRuntime.ExportLogsFromNode(cmd.Context(), node, exportPath, components); err != nil { - l.Log().Fatalln(err) - } - } - } - }, - } - - cwd, err := os.Getwd() - if err != nil { - l.Log().Fatalln(err) - } - - cmd.Flags().StringVarP(&nodeName, "node", "n", "", "Node name to export logs from") - cmd.Flags().StringVarP(&exportPath, "path", "p", cwd, "Path to export the logs to") return cmd } diff --git a/cmd/node/node.go b/cmd/node/node.go index 1781298d6..132f8f979 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -47,8 +47,7 @@ func NewCmdNode() *cobra.Command { NewCmdNodeStop(), NewCmdNodeDelete(), NewCmdNodeList(), - NewCmdNodeEdit(), - ) + NewCmdNodeEdit()) // add flags diff --git a/pkg/config/v1alpha5/schema.json b/pkg/config/v1alpha5/schema.json index 7d53a1f5f..e700751ff 100644 --- a/pkg/config/v1alpha5/schema.json +++ b/pkg/config/v1alpha5/schema.json @@ -385,9 +385,9 @@ "config": { "type": "string", "description": "Reference a K3s registry configuration file or at it's contents here." - }, - "additionalProperties": false - } + } + }, + "additionalProperties": false }, "hostAliases": { "type": "array", diff --git a/pkg/runtimes/docker/docker.go b/pkg/runtimes/docker/docker.go index 01534f330..5e2d28b8a 100644 --- a/pkg/runtimes/docker/docker.go +++ b/pkg/runtimes/docker/docker.go @@ -29,7 +29,6 @@ import ( "os" l "github.com/k3d-io/k3d/v5/pkg/logger" - k3d "github.com/k3d-io/k3d/v5/pkg/types" ) type Docker struct{} @@ -43,32 +42,6 @@ func (d Docker) ID() string { return "docker" } -type commandInfo struct { - Command []string - FileName string -} - -var roleBasedExportPath = map[k3d.Role][]string{ - k3d.ServerRole: {"/var/log", "/var/lib/rancher/k3s/agent/containerd/containerd.log"}, - k3d.AgentRole: {"/var/log", "/var/lib/rancher/k3s/agent/containerd/containerd.log"}, -} - -var roleBasedCommandsToExecute = map[k3d.Role][]commandInfo{ - k3d.ServerRole: { - {Command: []string{"crictl", "images"}, FileName: "crictl-images.log"}, - {Command: []string{"crictl", "ps", "-a"}, FileName: "crictl-ps.log"}, - {Command: []string{"kubectl", "cluster-info"}, FileName: "cluster-info.log"}, - {Command: []string{"kubectl", "version"}, FileName: "kubectl-version.log"}, - {Command: []string{"kubectl", "get", "node", "-o", "yaml"}, FileName: "kubectl-get-node.yaml"}, - {Command: []string{"ps", "-aef"}, FileName: "ps-aef.log"}, - }, - k3d.AgentRole: { - {Command: []string{"crictl", "images"}, FileName: "crictl-images.log"}, - {Command: []string{"crictl", "ps", "-a"}, FileName: "crictl-ps.log"}, - {Command: []string{"ps", "-aef"}, FileName: "ps-aef.log"}, - }, -} - // GetHost returns the docker daemon host func (d Docker) GetHost() string { // a) docker-machine diff --git a/pkg/runtimes/docker/node.go b/pkg/runtimes/docker/node.go index 457d32647..5de0e45bd 100644 --- a/pkg/runtimes/docker/node.go +++ b/pkg/runtimes/docker/node.go @@ -29,8 +29,6 @@ import ( "errors" "fmt" "io" - "os" - "path/filepath" "time" "github.com/docker/docker/api/types" @@ -495,48 +493,3 @@ func (d Docker) RenameNode(ctx context.Context, node *k3d.Node, newName string) return docker.ContainerRename(ctx, container.ID, newName) } - -func (d Docker) ExportLogsFromNode(ctx context.Context, node *k3d.Node, dstPath string, components []string) error { - destinationPath := filepath.Join(dstPath, node.Name) - - err := os.MkdirAll(destinationPath, os.FileMode(os.ModePerm)) - if err != nil { - return fmt.Errorf("failed to create destination directory '%s': %w", destinationPath, err) - } - c, err := getNodeContainer(ctx, node) - if err != nil { - return fmt.Errorf("failed to get container for node '%s': %w", node.Name, err) - } - - // create docker client - docker, err := GetDockerClient() - if err != nil { - return fmt.Errorf("failed to get docker client: %w", err) - } - defer docker.Close() - - reader, err := docker.ContainerLogs(ctx, c.ID, container.LogsOptions{Details: true, ShowStdout: true, ShowStderr: true}) - if err != nil { - return fmt.Errorf("failed to get logs from container '%s': %w", c.ID, err) - } - defer reader.Close() - - err = readerToFile(reader, filepath.Join(dstPath, fmt.Sprintf("%s.log", node.Name))) - if err != nil { - return fmt.Errorf("failed to write logs to file: %w", err) - } - - for _, srcPath := range roleBasedExportPath[node.Role] { - contentReader, _, err := docker.CopyFromContainer(ctx, c.ID, srcPath) - if err != nil { - return fmt.Errorf("failed to copy files from container '%s': %w", c.ID, err) - } - if err := untarReader(ctx, docker, c.ID, contentReader, destinationPath); err != nil { - return fmt.Errorf("failed to untar files from container '%s': %w", c.ID, err) - } - } - for _, command := range roleBasedCommandsToExecute[node.Role] { - d.executeCommandInContainer(ctx, docker, c.ID, command.Command, filepath.Join(destinationPath, command.FileName)) - } - return nil -} diff --git a/pkg/runtimes/docker/util.go b/pkg/runtimes/docker/util.go index 9b7bf7b0d..5ece57823 100644 --- a/pkg/runtimes/docker/util.go +++ b/pkg/runtimes/docker/util.go @@ -23,13 +23,11 @@ package docker import ( "archive/tar" - "bufio" "bytes" "context" "fmt" "io" "os" - "path/filepath" "regexp" "strings" @@ -38,7 +36,6 @@ import ( "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/flags" "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/strslice" "github.com/docker/docker/client" "github.com/docker/docker/pkg/archive" l "github.com/k3d-io/k3d/v5/pkg/logger" @@ -183,51 +180,6 @@ func (d Docker) ReadFromNode(ctx context.Context, path string, node *k3d.Node) ( return reader, err } -func (d Docker) executeCommandInContainer(ctx context.Context, cli client.APIClient, containerID string, command []string, outputFilePath string) error { - execConfig := container.ExecOptions{ - Cmd: strslice.StrSlice(command), - AttachStdout: true, - AttachStderr: true, - Tty: false, - } - - execIDResp, err := cli.ContainerExecCreate(ctx, containerID, execConfig) - if err != nil { - return fmt.Errorf("error creating exec instance: %v", err) - } - - resp, err := cli.ContainerExecAttach(ctx, execIDResp.ID, container.ExecStartOptions{Tty: false}) - if err != nil { - return fmt.Errorf("error attaching to exec instance: %v", err) - } - defer resp.Close() - - outputFile, err := os.Create(outputFilePath) - if err != nil { - return fmt.Errorf("error creating output file: %v", err) - } - defer outputFile.Close() - - writer := bufio.NewWriter(outputFile) - - var stdoutBuf bytes.Buffer - - _, err = io.Copy(&stdoutBuf, resp.Reader) - if err != nil { - return fmt.Errorf("Error copying stdout: %v", err) - } - - if _, err := writer.WriteString(stdoutBuf.String()); err != nil { - return fmt.Errorf("Error writing stdout to file: %v", err) - } - - if err := writer.Flush(); err != nil { - return fmt.Errorf("Error flushing writer: %v", err) - } - - return nil -} - // GetDockerClient returns a docker client func GetDockerClient() (client.APIClient, error) { dockerCli, err := command.NewDockerCli(command.WithStandardStreams()) @@ -259,94 +211,3 @@ func isAttachedToNetwork(node *k3d.Node, network string) bool { } return false } - -func readerToFile(reader io.Reader, target string) error { - file, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600)) - if err != nil { - return err - } - defer file.Close() - if _, err := io.Copy(file, reader); err != nil { - return err - } - - return nil -} - -func copyFile(tarReader *tar.Reader, target string, mode os.FileMode) error { - file, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, mode) - if err != nil { - return err - } - defer file.Close() - - if _, err := io.Copy(file, tarReader); err != nil { - return err - } - - return nil -} - -func copyOriginalContent(cli client.APIClient, ctx context.Context, containerID, linkTarget, target string) error { - reader, _, err := cli.CopyFromContainer(ctx, containerID, linkTarget) - if err != nil { - return err - } - defer reader.Close() - - tarReader := tar.NewReader(reader) - header, err := tarReader.Next() - if err != nil { - return err - } - - if header.Typeflag == tar.TypeReg { - if err := copyFile(tarReader, target, os.FileMode(header.Mode)); err != nil { - return err - } - } else if header.Typeflag == tar.TypeDir { - if err := untarReader(ctx, cli, containerID, reader, target); err != nil { - return err - } - } else { - return fmt.Errorf("unsupported symlink target file type: %v", header.Typeflag) - } - - return nil -} - -func untarReader(ctx context.Context, cli client.APIClient, containerID string, reader io.Reader, dstPath string) error { - tarReader := tar.NewReader(reader) - - for { - header, err := tarReader.Next() - if err == io.EOF { - break - } - if err != nil { - return err - } - - target := filepath.Join(dstPath, header.Name) - - switch header.Typeflag { - case tar.TypeDir: - if err := os.MkdirAll(target, os.FileMode(header.Mode)); err != nil { - return err - } - case tar.TypeReg: - if err := copyFile(tarReader, target, os.FileMode(header.Mode)); err != nil { - return err - } - case tar.TypeSymlink: - linkTarget := header.Linkname - if err := copyOriginalContent(cli, ctx, containerID, linkTarget, target); err != nil { - return err - } - default: - return fmt.Errorf("unsupported file type: %v", header.Typeflag) - } - } - - return nil -} diff --git a/pkg/runtimes/runtime.go b/pkg/runtimes/runtime.go index 91c6fb2f1..52f2fce06 100644 --- a/pkg/runtimes/runtime.go +++ b/pkg/runtimes/runtime.go @@ -81,7 +81,6 @@ type Runtime interface { DisconnectNodeFromNetwork(context.Context, *k3d.Node, string) error // @param context, node, network name Info() (*runtimeTypes.RuntimeInfo, error) GetNetwork(context.Context, *k3d.ClusterNetwork) (*k3d.ClusterNetwork, error) // @param context, network (so we can filter by name or by id) - ExportLogsFromNode(context.Context, *k3d.Node, string, []string) error // @param context, node, source, destination, components (This is meant for future use once we identify what/how to filter) } // GetRuntime checks, if a given name is represented by an implemented k3d runtime and returns it