package cmd import ( "fmt" "log/slog" "os" "path" "regexp" "sort" "strings" "text/template" "github.com/spf13/cobra" "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/generator/cmd/tools" ) var outFile string var docsCmd = &cobra.Command{ Use: "docs", Short: "handle documentation", Long: `...`, RunE: func(_ *cobra.Command, _ []string) error { // filePathStr := "stackit/internal/services/postgresflexalpha/database/datasources_gen/database_data_source_gen.go" // // src, err := os.ReadFile(filePathStr) // if err != nil { // return err //} // // i := interp.New( // interp.Options{ // GoPath: "/home/henselinm/.asdf/installs/golang/1.25.6/packages", // BuildTags: nil, // Stdin: nil, // Stdout: nil, // Stderr: nil, // Args: nil, // Env: nil, // SourcecodeFilesystem: nil, // Unrestricted: false, // }, //) // err = i.Use(i.Symbols("github.com/hashicorp/terraform-plugin-framework-validators")) // if err != nil { // return err //} // err = i.Use(stdlib.Symbols) // if err != nil { // return err //} // _, err = i.Eval(string(src)) // if err != nil { // return err //} // // v, err := i.Eval("DatabaseDataSourceSchema") // if err != nil { // return err //} // // bar := v.Interface().(func(string) string) // // r := bar("Kung") // println(r) // // evalPath, err := i.EvalPath(filePathStr) // if err != nil { // return err //} // // fmt.Printf("%+v\n", evalPath) // _, err = i.Eval(`import "fmt"`) // if err != nil { // return err //} // _, err = i.Eval(`func Hallo() { fmt.Println("Hi!") }`) // if err != nil { // return err //} // v = i.Symbols("Hallo") // fmt.Println(v) return workDocs() }, } type NavDocs struct { PageTitle string Description string NavigationTitle string ProviderTitle string IndexFound bool Services []Service } type Service struct { ServiceTitle string DataSources []ResItem Resources []ResItem } type ResItem struct { ItemName string ItemLink string } func workDocs() error { slog.Info("creating docs navigation") root, err := tools.GetGitRoot() if err != nil { slog.Error("ERROR", "err", err) return err } nav := NavDocs{ PageTitle: "STACKIT terraform provider PRIVATE-PREVIEW", Description: "", NavigationTitle: "Navigation", ProviderTitle: "Provider", IndexFound: false, } startPath := path.Join(root, "docs") docs, err := os.ReadDir(startPath) if err != nil { return err } services := make(map[string]Service) dataSources := make(map[string][]ResItem) resources := make(map[string][]ResItem) for _, entry := range docs { if !entry.IsDir() { if entry.Name() == "index.md" { slog.Debug(" found provider index file") nav.IndexFound = true continue } slog.Debug(" found am ignored file", "fileName", entry.Name()) continue } if entry.Name() != "data-sources" && entry.Name() != "resources" { slog.Error("unable to handle entry, skipping", "entry", entry.Name()) continue } elements, err := os.ReadDir(path.Join(startPath, entry.Name())) if err != nil { return err } for _, res := range elements { if res.IsDir() { slog.Warn("found unexpected directory", "dir", res.Name()) continue } re := regexp.MustCompile(`([a-z]+)_([a-z]+).md`) matches := re.FindAllStringSubmatch(res.Name(), -1) if matches == nil { slog.Error("unable to identify resource", "item", res.Name()) continue } services[matches[0][1]] = Service{ ServiceTitle: matches[0][1], } switch entry.Name() { case "data-sources": dataSources[matches[0][1]] = append(dataSources[matches[0][1]], ResItem{ ItemName: matches[0][2], ItemLink: fmt.Sprintf("docs/%s/%s", entry.Name(), matches[0][0]), }) case "resources": resources[matches[0][1]] = append(resources[matches[0][1]], ResItem{ ItemName: matches[0][2], ItemLink: fmt.Sprintf("docs/%s/%s", entry.Name(), matches[0][0]), }) default: return fmt.Errorf("this should never have happened") } } } keys := make([]string, 0, len(services)) for k := range services { keys = append(keys, k) } sort.Strings(keys) for _, name := range keys { item := services[name] item.DataSources = dataSources[name] item.Resources = resources[name] nav.Services = append(nav.Services, item) } fn := template.FuncMap{ "ucfirst": ucfirst, } tmpl, err := template. New("nav.md.gompl"). Funcs(fn). ParseFiles(path.Join(root, "generator", "cmd", "docs", "templates", "nav.md.gompl")) if err != nil { return err } var f *os.File f, err = os.Create(outFile) if err != nil { return err } err = tmpl.Execute(f, nav) if err != nil { return err } err = f.Close() if err != nil { return err } slog.Info("finished") return nil } func NewDocsCmd() *cobra.Command { return docsCmd } func ucfirst(s string) string { if s == "" { return "" } return strings.ToUpper(s[:1]) + s[1:] } func init() { // nolint: gochecknoinits docsCmd.Flags().StringVarP(&outFile, "outFile", "o", "nav.md", "nav.md") }