From 1dd886f28a2031b43f1e24072ded9eef4e93ed06 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Wed, 27 Aug 2025 11:53:44 +0200 Subject: [PATCH] fix: improve mapresponses and profiles extraction in hi tool - Fix directory hierarchy flattening by using full paths instead of filepath.Base() - Remove redundant container hostname prefixes from directory names - Strip top-level directory from tar extraction to avoid nested structure - Ensure parent directories exist before creating files - Results in clean structure: control_logs/mapresponses/1-ts-client/file.json --- cmd/hi/tar_utils.go | 7 ++++++- integration/hsic/hsic.go | 45 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/cmd/hi/tar_utils.go b/cmd/hi/tar_utils.go index 060b3cf4..f0e1e86b 100644 --- a/cmd/hi/tar_utils.go +++ b/cmd/hi/tar_utils.go @@ -68,7 +68,7 @@ func extractDirectoryFromTar(tarReader io.Reader, targetDir string) error { continue // Skip potentially dangerous paths } - targetPath := filepath.Join(targetDir, filepath.Base(cleanName)) + targetPath := filepath.Join(targetDir, cleanName) switch header.Typeflag { case tar.TypeDir: @@ -77,6 +77,11 @@ func extractDirectoryFromTar(tarReader io.Reader, targetDir string) error { return fmt.Errorf("failed to create directory %s: %w", targetPath, err) } case tar.TypeReg: + // Ensure parent directories exist + if err := os.MkdirAll(filepath.Dir(targetPath), 0o755); err != nil { + return fmt.Errorf("failed to create parent directories for %s: %w", targetPath, err) + } + // Create file outFile, err := os.Create(targetPath) if err != nil { diff --git a/integration/hsic/hsic.go b/integration/hsic/hsic.go index e77d2fbe..fbbd9cb8 100644 --- a/integration/hsic/hsic.go +++ b/integration/hsic/hsic.go @@ -622,6 +622,27 @@ func extractTarToDirectory(tarData []byte, targetDir string) error { } tarReader := tar.NewReader(bytes.NewReader(tarData)) + + // Find the top-level directory to strip + var topLevelDir string + firstPass := tar.NewReader(bytes.NewReader(tarData)) + for { + header, err := firstPass.Next() + if err == io.EOF { + break + } + if err != nil { + return fmt.Errorf("failed to read tar header: %w", err) + } + + if header.Typeflag == tar.TypeDir && topLevelDir == "" { + topLevelDir = strings.TrimSuffix(header.Name, "/") + break + } + } + + // Second pass: extract files, stripping the top-level directory + tarReader = tar.NewReader(bytes.NewReader(tarData)) for { header, err := tarReader.Next() if err == io.EOF { @@ -637,7 +658,20 @@ func extractTarToDirectory(tarData []byte, targetDir string) error { continue // Skip potentially dangerous paths } - targetPath := filepath.Join(targetDir, filepath.Base(cleanName)) + // Strip the top-level directory + if topLevelDir != "" && strings.HasPrefix(cleanName, topLevelDir+"/") { + cleanName = strings.TrimPrefix(cleanName, topLevelDir+"/") + } else if cleanName == topLevelDir { + // Skip the top-level directory itself + continue + } + + // Skip empty paths after stripping + if cleanName == "" { + continue + } + + targetPath := filepath.Join(targetDir, cleanName) switch header.Typeflag { case tar.TypeDir: @@ -646,6 +680,11 @@ func extractTarToDirectory(tarData []byte, targetDir string) error { return fmt.Errorf("failed to create directory %s: %w", targetPath, err) } case tar.TypeReg: + // Ensure parent directories exist + if err := os.MkdirAll(filepath.Dir(targetPath), 0o755); err != nil { + return fmt.Errorf("failed to create parent directories for %s: %w", targetPath, err) + } + // Create file outFile, err := os.Create(targetPath) if err != nil { @@ -674,7 +713,7 @@ func (t *HeadscaleInContainer) SaveProfile(savePath string) error { return err } - targetDir := path.Join(savePath, t.hostname+"-pprof") + targetDir := path.Join(savePath, "pprof") return extractTarToDirectory(tarFile, targetDir) } @@ -685,7 +724,7 @@ func (t *HeadscaleInContainer) SaveMapResponses(savePath string) error { return err } - targetDir := path.Join(savePath, t.hostname+"-mapresponses") + targetDir := path.Join(savePath, "mapresponses") return extractTarToDirectory(tarFile, targetDir) }