github.com/cilium/cilium@v1.16.2/tools/crdlistgen/main.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package main 5 6 import ( 7 "bufio" 8 "errors" 9 "fmt" 10 "io/fs" 11 "log/slog" 12 "os" 13 "path/filepath" 14 "sort" 15 "strings" 16 17 "github.com/cilium/hive/cell" 18 19 operatorServer "github.com/cilium/cilium/api/v1/operator/server" 20 "github.com/cilium/cilium/pkg/hive" 21 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/client" 22 ) 23 24 var ( 25 MainCell = cell.Module( 26 "main", 27 "Main module for generating CRD Lists", 28 cell.Invoke(printCRDList), 29 ) 30 31 Hive = hive.New( 32 operatorServer.SpecCell, 33 MainCell, 34 ) 35 ) 36 37 var ErrorBreakEarly = fmt.Errorf("break early") 38 39 func printCRDList( 40 opSpec *operatorServer.Spec, 41 shutdown hive.Shutdowner, 42 ) error { 43 list := client.CustomResourceDefinitionList() 44 45 crdlist := []string{} 46 47 for _, crd := range list { 48 crdlist = append(crdlist, cleanupCRDName(crd.Name)) 49 } 50 51 // Sort the list 52 sort.Strings(crdlist) 53 54 for idx, name := range crdlist { 55 // We need to walk ../../Documentation rst files to look and see if the CRD name is a header in the format of `.. _ <name>:`, if so 56 // add `ref:` to the name so it will link to the CRD in the docs. 57 err := filepath.WalkDir("./Documentation", func(path string, d fs.DirEntry, err error) error { 58 if err != nil { 59 return err 60 } 61 62 if filepath.Ext(path) == ".rst" { 63 match, err := grepFile(path, ".. _"+name+":") 64 if err != nil { 65 return err 66 } 67 // We can stop walking the documentation as we already know there is a match, so we send an ErrorBreakEarly and ignore that on the other side 68 // as WalkDir will keep running until it returns an error or there are no more files to walk. 69 if match { 70 // Change the name to a ref also specifically override the link text, as a couple headers add " CRD" to the text which causes the link to not be uniform. 71 crdlist[idx] = ":ref:`" + name + "<" + name + ">`" 72 return ErrorBreakEarly 73 } 74 } 75 76 return nil 77 }) 78 if err != nil && !errors.Is(err, ErrorBreakEarly) { 79 return err 80 } 81 } 82 83 f, err := os.Create("Documentation/crdlist.rst") 84 if err != nil { 85 return err 86 } 87 defer f.Close() 88 89 for _, name := range crdlist { 90 _, err := f.WriteString(fmt.Sprintf("- %s\n", name)) 91 if err != nil { 92 return err 93 } 94 } 95 96 shutdown.Shutdown() 97 return nil 98 } 99 100 // Scan file for string 101 func grepFile(path, search string) (bool, error) { 102 //fmt.Printf("searching %s for %s\n", path, search) 103 f, err := os.Open(path) 104 if err != nil { 105 return false, err 106 } 107 defer f.Close() 108 109 scanner := bufio.NewScanner(f) 110 for scanner.Scan() { 111 if strings.Contains(scanner.Text(), search) { 112 return true, nil 113 } 114 } 115 116 return false, scanner.Err() 117 } 118 119 // Remove the /(version) portion from the CRD Name 120 func cleanupCRDName(name string) string { 121 return strings.Split(name, "/")[0] 122 } 123 124 func main() { 125 Hive.Run(slog.Default()) 126 }