terraform-provider-stackitp.../generator/cmd/docCmd.go
Marcel S. Henselin 49ed600f7f
Some checks failed
CI Workflow / Check GoReleaser config (pull_request) Successful in 6s
CI Workflow / Prepare GO cache (pull_request) Successful in 4m57s
CI Workflow / Test readiness for publishing provider (pull_request) Successful in 13m22s
CI Workflow / CI run build and linting (pull_request) Successful in 17m32s
CI Workflow / Code coverage report (pull_request) Successful in 12s
CI Workflow / CI run tests (pull_request) Failing after 19m11s
feat(generator): generate nav file
2026-03-13 10:24:51 +01:00

247 lines
5.2 KiB
Go

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")
}