Files
opencloud/docs/helpers/templates/adoc-generator.go.tmpl
Christian Richter 57d59de6e2 fix intendation
Signed-off-by: Christian Richter <crichter@owncloud.com>
2024-07-19 09:54:18 +02:00

273 lines
7.5 KiB
Cheetah

package main
import (
"fmt"
"log"
"os"
"path/filepath"
"reflect"
"regexp"
"strings"
"text/template"
"time"
"sort"
{{- range $key, $value := .}}
pkg{{$key}} "{{$value}}"
{{- end}}
)
// ConfigField is the representation of one configuration field
type ConfigField struct {
EnvVars []string
DefaultValue string
IntroductionVersion string
Type string
Description string
VersionInfo string
DeprecationLink string
}
// DeprecationField holds information about deprecation
type DeprecationField struct {
DeprecationVersion string
DeprecationInfo string
DeprecationReplacement string
RemovalVersion string
}
// EnvVar holds information about one envvar
type EnvVar struct {
Name string
IntroductionVersion string
DefaultValue string
Type string
Description string
Services []string
}
type templateData struct {
ExtensionName string
Fields []ConfigField
Deprecations []DeprecationField
HasDeprecations bool
Timestamp string
}
func main() {
fmt.Println("Generating adoc documentation for environment variables:")
adoc, err := os.ReadFile("../../docs/templates/ADOC.tmpl")
if err != nil {
log.Fatal(err)
}
dpr, err := os.ReadFile("../../docs/templates/ADOC_deprecation.tmpl")
if err != nil {
log.Fatal(err)
}
replacer := strings.NewReplacer(
"github.com/owncloud/ocis/v2/services/", "",
"/pkg/config/defaults", "",
)
var (
fields []ConfigField
deprecations []DeprecationField
adocFile *os.File
dprFile *os.File
)
adoctpl := template.Must(template.New("").Parse(string(adoc)))
dprtpl := template.Must(template.New("").Parse(string(dpr)))
m := map[string]interface{}{
{{- range $key, $value := .}}
"{{$value}}": *pkg{{$key}}.FullDefaultConfig(),
{{- end }}
}
targetFolder := "../../docs/services/_includes/adoc/"
all := make(map[string]EnvVar)
for pkg, conf := range m {
service := replacer.Replace(pkg)
timestamp := time.Now().Format("2006-01-02-15-04-05")
fields, deprecations = GetAnnotatedVariables(conf, timestamp)
var hasDeprecations bool
if len(deprecations) > 0 {
hasDeprecations = true
}
for _, f := range fields {
for _, e := range f.EnvVars {
if env, ok := all[e]; ok {
env.Services = append(env.Services, service)
sort.Slice(env.Services, func(i, j int) bool {
return env.Services[i] < env.Services[j]
})
all[e] = env
} else {
all[e] = EnvVar{
Name: e,
IntroductionVersion: replaceEnvVarPlaceHolder(f.IntroductionVersion),
Description: f.Description,
Type: f.Type,
DefaultValue: f.DefaultValue,
Services: []string{service},
}
}
}
}
if len(fields) > 0 || len(deprecations) > 0 {
fmt.Printf("... %s\n", pkg)
td := templateData{
ExtensionName: service,
Fields: fields,
Deprecations: deprecations,
HasDeprecations: hasDeprecations,
Timestamp: timestamp,
}
adocFile, err = os.Create(filepath.Join(targetFolder, service + "_configvars.adoc"))
if err != nil {
log.Fatalf("Failed to create target file: %s", err)
}
defer adocFile.Close()
if err := adoctpl.Execute(adocFile, td); err != nil {
log.Fatalf("Failed to execute template: %s", err)
}
dprFile, err = os.Create(filepath.Join(targetFolder, service + "_deprecation.adoc"))
if err != nil {
log.Fatalf("Failed to create target file: %s", err)
}
defer dprFile.Close()
if err := dprtpl.Execute(dprFile, td); err != nil {
log.Fatalf("Failed to execute template: %s", err)
}
}
}
// render global env vars
tmplValues := make([]map[string]interface{}, 0)
for _, env := range all {
if len(env.Services) > 1 {
tmplValues = append(tmplValues, map[string]interface{}{
"Name": env.Name,
"IntroductionVersion": replaceEnvVarPlaceHolder(env.IntroductionVersion),
"Services": env.Services,
"Description": env.Description,
"DefaultValue": env.DefaultValue,
"Type": env.Type,
})
}
}
// sort
sort.Slice(tmplValues, func(i, j int) bool {
return tmplValues[i]["Name"].(string) < tmplValues[j]["Name"].(string)
})
glc, err := os.ReadFile("../../docs/templates/ADOC_global.tmpl")
if err != nil {
log.Fatal(err)
}
gltpl := template.Must(template.New("").Parse(string(glc)))
glfile, err := os.Create(filepath.Join(targetFolder, "global_configvars.adoc"))
if err != nil {
log.Fatalf("Failed to create target file: %s", err)
}
if err := gltpl.Execute(glfile, tmplValues); err != nil {
log.Printf("Failed to execute template: %s", err)
}
fmt.Println("done")
}
func replaceEnvVarPlaceHolder(s string) string {
return strings.Replace(
strings.Replace(s, "%%NEXT%%", "next", -1),
"%%NEXT_PRODUCTION_VERSION%%",
"next-prod",
-1,
)
}
func GetAnnotatedVariables(s interface{}, timestamp string) ([]ConfigField, []DeprecationField) {
t := reflect.TypeOf(s)
v := reflect.ValueOf(s)
var fields []ConfigField
var deprecations []DeprecationField
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
value := v.Field(i)
switch value.Kind() {
default:
desc := field.Tag.Get("desc")
env, ok := field.Tag.Lookup("env")
deprecationLink := ""
if !ok {
continue
}
introductionVersion, _ := field.Tag.Lookup("introductionVersion")
deprecationVersion, _ := field.Tag.Lookup("deprecationVersion")
removalVersion, _ := field.Tag.Lookup("removalVersion")
deprecationInfo, _ := field.Tag.Lookup("deprecationInfo")
deprecationReplacement, _ := field.Tag.Lookup("deprecationReplacement")
if deprecationVersion != "" ||
removalVersion != "" ||
deprecationInfo != "" ||
deprecationReplacement != "" {
deprecationLink = fmt.Sprintf("xref:deprecation-note-%s[Deprecation Note]", timestamp)
}
v := fmt.Sprintf("%v", value.Interface())
td := strings.Split(env, ";")
// re := regexp.MustCompile(`^(https?:\/\/)`)
// v = re.ReplaceAllString(v,"\\$1")
re := regexp.MustCompile(`(https?:\/\/)`)
desc = re.ReplaceAllString(desc, "\\$1")
re = regexp.MustCompile(`(\|)`)
v = re.ReplaceAllString(v, "\\$1")
typeName := value.Type().Name()
if typeName == "" {
typeName = value.Type().String()
}
fields = append(fields,
ConfigField{
EnvVars: td,
IntroductionVersion: replaceEnvVarPlaceHolder(introductionVersion),
DefaultValue: v,
Description: desc,
Type: typeName,
DeprecationLink: deprecationLink,
})
if deprecationLink != "" {
deprecations = append(deprecations,
DeprecationField{
DeprecationVersion: replaceEnvVarPlaceHolder(deprecationVersion),
DeprecationInfo: deprecationInfo,
DeprecationReplacement: deprecationReplacement,
RemovalVersion: replaceEnvVarPlaceHolder(removalVersion),
})
}
case reflect.Ptr:
// PolicySelectors in the Proxy are being skipped atm
// they are not configurable via env vars, if that changes
// they are probably added to the Sanitize() function
// and this should not be an issue then
if !value.IsZero() && value.Elem().CanInterface() {
f, d := GetAnnotatedVariables(value.Elem().Interface(), timestamp)
fields = append(fields, f...)
deprecations = append(deprecations, d...)
}
case reflect.Struct:
f, d := GetAnnotatedVariables(value.Interface(), timestamp)
fields = append(fields, f...)
deprecations = append(deprecations, d...)
}
}
return fields, deprecations
}