Skip to content

Commit 86241a6

Browse files
committed
docs: fix documentation links
Self links were not fully implemented, so I added them. Not all kubernetes-api references had links, adjusted the code to dynamically generate them. Also some naming inconsistencies in filenames were fixed so they are now the snakecase equivalent of the camelcase structs inside them. Otherwise generating the doc links would be quite difficult. Signed-off-by: Zoltán Reegn <[email protected]>
1 parent 3064a00 commit 86241a6

34 files changed

+372
-332
lines changed

Diff for: cmd/doc-gen/main.go

+70-30
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ import (
1010
"os"
1111
"path/filepath"
1212
"reflect"
13+
"regexp"
1314
"sort"
1415
"strings"
16+
"unicode"
1517
)
1618

1719
const (
@@ -27,18 +29,16 @@ This Document documents the types introduced by the %s Operator.
2729

2830
var (
2931
links = map[string]string{
30-
"metav1.ObjectMeta": "https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#objectmeta-v1-meta",
31-
"metav1.ListMeta": "https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#listmeta-v1-meta",
32-
"metav1.LabelSelector": "https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#labelselector-v1-meta",
33-
"corev1.SecretKeySelector": "https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#secretkeyselector-v1-core",
34-
"corev1.Toleration": "https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#toleration-v1-core",
35-
"corev1.VolumeSource": "https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#volume-v1-core",
36-
"plugins.Secret": "../secret.md",
37-
"Secret": "secret.md",
38-
"plugins.TLS": "../tls.md",
32+
"plugins.Secret": "../secret.md",
33+
"Secret": "secret.md",
34+
"plugins.TLS": "../tls.md",
3935
}
4036

41-
selfLinks = map[string]string{}
37+
kubernetes_link_templates = map[string]string{
38+
"corev1.": "https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#%s-v1-core",
39+
"metav1.": "https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#%s-v1-meta",
40+
"rbacv1.": "https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#%s-v1-rbac-authorization-k8s-io",
41+
}
4242

4343
unincludedKeyWords = []string{
4444
"deepcopy.go",
@@ -55,7 +55,7 @@ type DocumentsLocation struct {
5555

5656
// Inspired by coreos/prometheus-operator: https://github.com/coreos/prometheus-operator
5757
func main() {
58-
var pluginsLocations = []DocumentsLocation{
58+
pluginsLocations := []DocumentsLocation{
5959
{
6060
path: fluentbitPluginPath,
6161
name: "fluentbit",
@@ -67,7 +67,7 @@ func main() {
6767
}
6868
plugins(pluginsLocations)
6969

70-
var crdsLocations = []DocumentsLocation{
70+
crdsLocations := []DocumentsLocation{
7171
{
7272
path: fluentbitCrdsPath,
7373
name: "fluentbit",
@@ -105,7 +105,7 @@ func plugins(docsLocations []DocumentsLocation) {
105105
for _, src := range srcs {
106106
var buffer bytes.Buffer
107107

108-
types := ParseDocumentationFrom(src, true)
108+
types := ParseDocumentationFrom(src, dl.name, true)
109109

110110
for _, t := range types {
111111
strukt := t[0]
@@ -164,7 +164,7 @@ func crds(docsLocations []DocumentsLocation) {
164164
var buffer bytes.Buffer
165165
var types []KubeTypes
166166
for _, src := range srcs {
167-
types = append(types, ParseDocumentationFrom(src, false)...)
167+
types = append(types, ParseDocumentationFrom(src, dl.name, false)...)
168168
}
169169

170170
sort.Slice(types, func(i, j int) bool {
@@ -228,7 +228,7 @@ type Pair struct {
228228
// KubeTypes is an array to represent all available types in a parsed file. [0] is for the type itself
229229
type KubeTypes []Pair
230230

231-
func ParseDocumentationFrom(src string, shouldSort bool) []KubeTypes {
231+
func ParseDocumentationFrom(src string, dl_name string, shouldSort bool) []KubeTypes {
232232
var docForTypes []KubeTypes
233233

234234
pkg := astFrom(src)
@@ -254,7 +254,7 @@ func ParseDocumentationFrom(src string, shouldSort bool) []KubeTypes {
254254
ks = append(ks, Pair{kubType.Name, fmtRawDoc(kubType.Doc), ""})
255255

256256
for _, field := range structType.Fields.List {
257-
typeString := fieldType(field.Type)
257+
typeString := fieldType(field.Type, dl_name)
258258
if n := fieldName(field); n != "-" {
259259
fieldDoc := fmtRawDoc(field.Doc.Text())
260260
ks = append(ks, Pair{n, fieldDoc, typeString})
@@ -314,23 +314,63 @@ func fmtRawDoc(rawDoc string) string {
314314
return postDoc
315315
}
316316

317-
func toLink(typeName string) string {
317+
func tryKubernetesLink(typeName string) (string, bool) {
318+
for prefix, link_template := range kubernetes_link_templates {
319+
if strings.HasPrefix(typeName, prefix) {
320+
typeName = strings.ToLower(strings.TrimPrefix(typeName, prefix))
321+
return fmt.Sprintf(link_template, typeName), true
322+
}
323+
}
324+
return "", false
325+
}
326+
327+
var (
328+
matchFirstCap = regexp.MustCompile("(.)([A-Z][a-z]+)")
329+
matchAllCap = regexp.MustCompile("([a-z0-9])([A-Z])")
330+
)
331+
332+
func ToSnakeCase(str string) string {
333+
snake := matchFirstCap.ReplaceAllString(str, "${1}_${2}")
334+
snake = matchAllCap.ReplaceAllString(snake, "${1}_${2}")
335+
return strings.ToLower(snake)
336+
}
337+
338+
func toLink(typeName string, documentLocationName string) string {
339+
primitiveTypes := map[string]bool{
340+
"string": true,
341+
"bool": true,
342+
"int32": true,
343+
"int64": true,
344+
"map[string]string": true,
345+
}
346+
347+
if _, ok := primitiveTypes[typeName]; ok {
348+
return typeName
349+
}
350+
351+
link, hasLink := links[typeName]
352+
if hasLink {
353+
return wrapInLink(typeName, link)
354+
}
355+
318356
if strings.Contains(typeName, "input.") ||
319357
strings.Contains(typeName, "output.") ||
320358
strings.Contains(typeName, "filter.") ||
321-
strings.Contains(typeName, "parser.") {
359+
strings.Contains(typeName, "parser.") ||
360+
strings.Contains(typeName, "custom.") {
322361
// Eg. *output.Elasticsearch => ../plugins/output/elasticsearch.md
323-
link := fmt.Sprintf("plugins/%s.md", strings.ReplaceAll(strings.ToLower(typeName), ".", "/"))
362+
pluginType, pluginName, _ := strings.Cut(typeName, ".")
363+
link := fmt.Sprintf("plugins/%s/%s/%s.md", documentLocationName, pluginType, ToSnakeCase(pluginName))
324364
return wrapInLink(typeName, link)
325365
}
326366

327-
selfLink, hasSelfLink := selfLinks[typeName]
328-
if hasSelfLink {
329-
return wrapInLink(typeName, selfLink)
367+
k8sLink, hasK8sLink := tryKubernetesLink(typeName)
368+
if hasK8sLink {
369+
return wrapInLink(typeName, k8sLink)
330370
}
331371

332-
link, hasLink := links[typeName]
333-
if hasLink {
372+
if !strings.Contains(typeName, ".") && len(typeName) > 0 && unicode.IsUpper([]rune(typeName)[0]) {
373+
link := fmt.Sprintf("#%s", strings.ToLower(typeName))
334374
return wrapInLink(typeName, link)
335375
}
336376

@@ -362,22 +402,22 @@ func fieldName(field *ast.Field) string {
362402
return jsonTag
363403
}
364404

365-
func fieldType(typ ast.Expr) string {
405+
func fieldType(typ ast.Expr, dl_name string) string {
366406
switch typ.(type) {
367407
case *ast.Ident:
368-
return toLink(typ.(*ast.Ident).Name)
408+
return toLink(typ.(*ast.Ident).Name, dl_name)
369409
case *ast.StarExpr:
370-
return "*" + fieldType(typ.(*ast.StarExpr).X)
410+
return "*" + fieldType(typ.(*ast.StarExpr).X, dl_name)
371411
case *ast.SelectorExpr:
372412
e := typ.(*ast.SelectorExpr)
373413
pkg := e.X.(*ast.Ident)
374414
t := e.Sel
375-
return toLink(pkg.Name + "." + t.Name)
415+
return toLink(pkg.Name+"."+t.Name, dl_name)
376416
case *ast.ArrayType:
377-
return "[]" + toLink(fieldType(typ.(*ast.ArrayType).Elt))
417+
return "[]" + fieldType(typ.(*ast.ArrayType).Elt, dl_name)
378418
case *ast.MapType:
379419
mapType := typ.(*ast.MapType)
380-
return "map[" + toLink(fieldType(mapType.Key)) + "]" + toLink(fieldType(mapType.Value))
420+
return "map[" + toLink(fieldType(mapType.Key, dl_name), dl_name) + "]" + toLink(fieldType(mapType.Value, dl_name), dl_name)
381421
default:
382422
return ""
383423
}

0 commit comments

Comments
 (0)