diff --git a/clustertool/cmd/adv_gentooldocs.go b/clustertool/cmd/adv_gentooldocs.go new file mode 100644 index 000000000000..e487f387d0e6 --- /dev/null +++ b/clustertool/cmd/adv_gentooldocs.go @@ -0,0 +1,35 @@ +package cmd + +import ( + "log" + "os" + + "github.com/spf13/cobra" + "github.com/spf13/cobra/doc" + "github.com/truecharts/public/clustertool/pkg/helper" +) + +var gendocsCmd = &cobra.Command{ + Use: "gentooldocs", + Short: "Generate documentation for the CLI", + Args: cobra.ExactArgs(1), + Hidden: true, + Run: func(cmd *cobra.Command, args []string) { + outdir := args[0] + tmpdir := "./tmp/docs" + + if err := os.MkdirAll(tmpdir, 0o777); err != nil { + log.Fatal(err) + } + + err := doc.GenMarkdownTree(RootCmd, tmpdir) + if err != nil { + log.Fatal(err) + } + helper.ToolDocs(tmpdir, outdir) + }, +} + +func init() { + adv.AddCommand(gendocsCmd) +} diff --git a/clustertool/pkg/helper/tooldocs.go b/clustertool/pkg/helper/tooldocs.go new file mode 100644 index 000000000000..c6a26111cabe --- /dev/null +++ b/clustertool/pkg/helper/tooldocs.go @@ -0,0 +1,143 @@ +package helper + +import ( + "bufio" + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/rs/zerolog/log" +) + +func ToolDocs(tmpDir string, outputDir string) { + + log.Info().Msg("Starting file processing") + + if err := processFiles(tmpDir, outputDir); err != nil { + log.Error().Err(err).Msg("Error processing files") + return + } + if err := moveMatchingFilesToSubdirs(outputDir); err != nil { + log.Error().Err(err).Msg("Error organizing files into subdirectories") + return + } + + log.Info().Msg("File processing completed successfully") +} + +// processFiles reads and processes each file, writing modified content to output directories. +func processFiles(tmpdir string, outputDir string) error { + files, err := os.ReadDir(tmpdir) + if err != nil { + return fmt.Errorf("reading input directory: %w", err) + } + + for _, file := range files { + if file.IsDir() { + log.Debug().Str("file", file.Name()).Msg("Skipping directory") + continue + } + + fileName := strings.Replace(file.Name(), "clustertool_", "", 1) + subDir, newFileName := determinePaths(fileName) + newPath := filepath.Join(outputDir, subDir, newFileName) + + log.Info().Str("file", file.Name()).Str("new_path", newPath).Msg("Processing file") + + content, err := os.ReadFile(filepath.Join(tmpdir, file.Name())) + if err != nil { + log.Error().Err(err).Str("file", file.Name()).Msg("Error reading file") + continue + } + + modifiedContent := addYamlTitle(content, newFileName == "index.md" && subDir == "") + if err := writeToFile(newPath, modifiedContent, file); err != nil { + log.Error().Err(err).Str("path", newPath).Msg("Error writing file") + continue + } + + if err := os.Remove(filepath.Join(tmpdir, file.Name())); err != nil { + log.Error().Err(err).Str("file", file.Name()).Msg("Error deleting original file") + } else { + log.Debug().Str("file", file.Name()).Msg("Original file deleted") + } + } + return nil +} + +// determinePaths sets folder paths based on filename structure. +func determinePaths(filename string) (subDir, newFileName string) { + parts := strings.SplitN(strings.TrimSuffix(filename, ".md"), "_", 2) + if len(parts) < 2 { + return "", filename + } + subDir = parts[0] + newFileName = parts[1] + if newFileName == subDir { + newFileName = "index.md" + } else { + newFileName += ".md" + } + log.Debug().Str("sub_dir", subDir).Str("new_file", newFileName).Msg("Determined file paths") + return +} + +// addYamlTitle adds the YAML front matter with title. +func addYamlTitle(content []byte, isPrimaryIndex bool) []byte { + scanner := bufio.NewScanner(strings.NewReader(string(content))) + var builder strings.Builder + builder.WriteString("---\ntitle: ") + + if isPrimaryIndex { + builder.WriteString("clustertool\n---\n") + log.Debug().Msg("Set primary index title to 'clustertool'") + } else if scanner.Scan() && strings.HasPrefix(scanner.Text(), "## ") { + title := strings.TrimPrefix(scanner.Text(), "## ") + builder.WriteString(title + "\n---\n") + builder.WriteString(scanner.Text() + "\n") + log.Debug().Str("title", title).Msg("Set title from first line") + } + for scanner.Scan() { + builder.WriteString(scanner.Text() + "\n") + } + return []byte(builder.String()) +} + +// writeToFile writes the content to the specified path, creating directories as needed. +func writeToFile(path string, content []byte, file os.DirEntry) error { + if err := os.MkdirAll(filepath.Dir(path), os.ModePerm); err != nil { + return fmt.Errorf("creating directory for path %s: %w", path, err) + } + if err := os.WriteFile(path, content, file.Type()); err != nil { + return fmt.Errorf("writing file to path %s: %w", path, err) + } + log.Info().Str("path", path).Msg("File written successfully") + return nil +} + +// moveMatchingFilesToSubdirs moves files to matching subdirectories as index.md if a subdirectory exists. +func moveMatchingFilesToSubdirs(outputDir string) error { + files, err := os.ReadDir(outputDir) + if err != nil { + return fmt.Errorf("reading output directory: %w", err) + } + + for _, file := range files { + if file.IsDir() { + continue + } + + fileBase := strings.TrimSuffix(file.Name(), ".md") + subDir := filepath.Join(outputDir, fileBase) + if info, err := os.Stat(subDir); err == nil && info.IsDir() { + newPath := filepath.Join(subDir, "index.md") + if err := os.Rename(filepath.Join(outputDir, file.Name()), newPath); err != nil { + log.Error().Err(err).Str("file", file.Name()).Str("new_path", newPath).Msg("Error moving file to subdirectory") + return err + } + log.Info().Str("file", file.Name()).Str("subdirectory", subDir).Msg("Moved file to subdirectory as index.md") + } + } + return nil +} diff --git a/clustertool/pkg/helper/vars.go b/clustertool/pkg/helper/vars.go index 784ea405cf63..52c567164aac 100644 --- a/clustertool/pkg/helper/vars.go +++ b/clustertool/pkg/helper/vars.go @@ -14,6 +14,7 @@ var ( BaseCache = filepath.Join(CacheDir, "base") RootCache = filepath.Join(CacheDir, "root") PatchCache = filepath.Join(CacheDir, "patches") + DocsCache = filepath.Join(CacheDir, "docs") CacheDir = filepath.Join(UserCacheDir, "clustertool") ClusterPath = filepath.Join("./clusters", ClusterName) ClusterEnvFile = filepath.Join(ClusterPath, "/clusterenv.yaml")