diff --git a/pkg/hhfab/vlabhelpers.go b/pkg/hhfab/vlabhelpers.go index d984a219..2adddf02 100644 --- a/pkg/hhfab/vlabhelpers.go +++ b/pkg/hhfab/vlabhelpers.go @@ -7,7 +7,6 @@ import ( "context" _ "embed" "fmt" - // "io" "log/slog" "net/netip" "os" @@ -113,7 +112,7 @@ func (c *Config) VLABAccess(ctx context.Context, vlab *VLAB, t VLABAccessType, n "core@127.0.0.1", ) } else if entry.IsSwitch { - slog.Info("SSH through control node", "name", name, "type", "switch") + slog.Debug("SSH through control node", "name", name, "type", "switch") kubeconfig := filepath.Join(c.WorkDir, VLABDir, VLABKubeConfig) kube, err := kubeutil.NewClientWithCache(ctx, kubeconfig, wiringapi.SchemeBuilder) @@ -308,7 +307,6 @@ func (c *Config) VLABShowTech(ctx context.Context, vlab *VLAB) error { wg.Add(1) go func(name string, entry VLABAccessInfo) { defer wg.Done() - slog.Debug("Collecting Show Tech bundle for", "entry", name) // Pass entry, scriptConfig, and outputDir to collectShowTech if err := c.collectShowTech(ctx, name, entry, scriptConfig, outputDir); err != nil { @@ -343,16 +341,9 @@ func (c *Config) collectShowTech(ctx context.Context, entryName string, entry VL return nil // Skip entries with no defined script } - // Create VM-specific output directory - vmOutputDir := filepath.Join(outputDir, entryName) - if err := os.MkdirAll(vmOutputDir, 0755); err != nil { - return fmt.Errorf("creating output directory for %s: %w", entryName, err) - } - // Remote paths remoteScriptPath := "/tmp/show-tech.sh" remoteOutputPath := "/tmp/show-tech.log" - localOutputPath := filepath.Join(vmOutputDir, "show-tech.log") // Execute remote commands and file transfers using easyssh-proxy //nolint:goerr113 ssh, err := c.createSSHConfig(ctx, entryName, entry) @@ -395,18 +386,64 @@ func (c *Config) collectShowTech(ctx context.Context, entryName string, entry VL } if stderr != "" { - slog.Debug("show-tech execution produced stderr", - "entry", entryName, - "stderr", stderr) + slog.Debug("show-tech execution produced stderr", "entry", entryName, "stderr", stderr) + } + + localFilePath := filepath.Join(outputDir, entryName+"-show-tech.log") + localFile, err := os.Create(localFilePath) + if err != nil { + fmt.Printf("Failed to create local file for %s: %v\n", entryName, err) + + return fmt.Errorf("failed to create local file for %s: %w", entryName, err) } + defer localFile.Close() - // Download the output file - err = ssh.Scp(remoteOutputPath, localOutputPath) + // Run cat command to fetch remote file contents + stdoutChan, stderrChan, doneChan, errChan, err := ssh.Stream(fmt.Sprintf("cat %s", remoteOutputPath), 60*time.Second) if err != nil { - return fmt.Errorf("downloading show-tech output for %s: %w", entryName, err) + fmt.Printf("Failed to connect to %s: %v\n", entryName, err) + + return fmt.Errorf("failed to connect to %s: %w", entryName, err) + } + + // Read remote file contents and write to local file + isTimeout := true +loop: + for { + select { + case isTimeout = <-doneChan: + + break loop + case line := <-stdoutChan: + _, writeErr := localFile.WriteString(line + "\n") + if writeErr != nil { + fmt.Printf("Failed to write to local file for %s: %v\n", entryName, writeErr) + + return fmt.Errorf("failed to write to local file for %s: %w", entryName, writeErr) + } + case errLine := <-stderrChan: + if errLine != "" { + fmt.Fprintf(os.Stderr, "%s: %s\n", entryName, errLine) + } + case err = <-errChan: + if err != nil { + fmt.Printf("Error while reading from %s: %v\n", entryName, err) + + break loop + } + + break loop + } } - slog.Info("Show tech collected successfully", "entry", entryName, "output", localOutputPath) + // Handle timeout or errors + if !isTimeout { + fmt.Printf("Timeout occurred while fetching file from %s\n", entryName) + + return fmt.Errorf("timeout occurred while fetching file from %s", entryName) //nolint:goerr113 + } + + slog.Debug("Show tech collected successfully", "entry", entryName, "output", localFilePath) return nil } @@ -421,8 +458,6 @@ func (c *Config) createSSHConfig(ctx context.Context, entryName string, entry VL } if entry.SSHPort > 0 { - slog.Info("SSH using local port", "entry", entryName, "port", entry.SSHPort) - return &easyssh.MakeConfig{ User: "core", Server: "127.0.0.1", @@ -433,7 +468,6 @@ func (c *Config) createSSHConfig(ctx context.Context, entryName string, entry VL } if entry.IsSwitch { - slog.Info("SSH through control node", "entry", entryName, "type", "switch") swIP, err := c.getSwitchIP(ctx, entryName) if err != nil { return nil, fmt.Errorf("getting switch IP: %w", err) @@ -449,6 +483,7 @@ func (c *Config) createSSHConfig(ctx context.Context, entryName string, entry VL return &easyssh.MakeConfig{ User: "admin", Server: swIP, + Port: "22", KeyPath: sshKeyPath, Timeout: 60 * time.Second, Proxy: easyssh.DefaultConfig{