github.com/caos/orbos@v1.5.14-0.20221103111702-e6cd0cea7ad4/pkg/kubernetes/crds.go (about) 1 package kubernetes 2 3 import ( 4 "bytes" 5 "fmt" 6 "gopkg.in/yaml.v3" 7 "io" 8 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 9 "sigs.k8s.io/controller-tools/pkg/crd" 10 "sigs.k8s.io/controller-tools/pkg/deepcopy" 11 "sigs.k8s.io/controller-tools/pkg/genall" 12 "sigs.k8s.io/controller-tools/pkg/loader" 13 "sigs.k8s.io/controller-tools/pkg/markers" 14 "strings" 15 ) 16 17 var ( 18 buffer = bytes.Buffer{} 19 20 allGenerators = map[string]genall.Generator{ 21 "crd": crd.Generator{}, 22 "object": deepcopy.Generator{}, 23 } 24 25 allOutputRules = map[string]genall.OutputRule{ 26 "dir": genall.OutputToDirectory(""), 27 "none": genall.OutputToNothing, 28 "stdout": genall.OutputToStdout, 29 "buffer": outputToBuffer{}, 30 "artifacts": genall.OutputArtifacts{}, 31 } 32 33 optionsRegistry = &markers.Registry{} 34 ) 35 36 func getYamlsFromBuffer() []string { 37 yamls := strings.Split(buffer.String(), "---") 38 buffer.Reset() 39 return yamls 40 } 41 42 func GetCRDs(boilerplatePath, path string) ([]string, error) { 43 if err := generateDeepCopy(boilerplatePath, path); err != nil { 44 return nil, err 45 } 46 47 if err := generateCrd(path); err != nil { 48 return nil, err 49 } 50 51 return getYamlsFromBuffer(), nil 52 } 53 54 func WriteCRDs(boilerplatePath, path, destinationFolder string) error { 55 if err := generateDeepCopy(boilerplatePath, path); err != nil { 56 return err 57 } 58 59 return generateCrdToFolder(path, destinationFolder) 60 } 61 62 func ApplyCRDs(boilerplatePath, path string, k8sClient ClientInt) error { 63 if err := generateDeepCopy(boilerplatePath, path); err != nil { 64 return err 65 } 66 67 if err := generateCrd(path); err != nil { 68 return err 69 } 70 71 for _, crd := range getYamlsFromBuffer() { 72 if crd == "" || crd == "\n" { 73 continue 74 } 75 76 //crdDefinition := apixv1beta1.CustomResourceDefinition{} 77 crdDefinition := &unstructured.Unstructured{} 78 if err := yaml.Unmarshal([]byte(crd), &crdDefinition.Object); err != nil { 79 return err 80 } 81 82 if err := k8sClient.ApplyCRDResource( 83 crdDefinition, 84 ); err != nil { 85 return err 86 } 87 } 88 return nil 89 } 90 91 type outputToBuffer struct{} 92 93 func (o outputToBuffer) Open(_ *loader.Package, itemPath string) (io.WriteCloser, error) { 94 return nopCloser{&buffer}, nil 95 } 96 97 type nopCloser struct { 98 io.Writer 99 } 100 101 func (n nopCloser) Close() error { 102 return nil 103 } 104 105 func init() { 106 for genName, gen := range allGenerators { 107 // make the generator options marker itself 108 defn := markers.Must(markers.MakeDefinition(genName, markers.DescribesPackage, gen)) 109 if err := optionsRegistry.Register(defn); err != nil { 110 panic(err) 111 } 112 if helpGiver, hasHelp := gen.(genall.HasHelp); hasHelp { 113 if help := helpGiver.Help(); help != nil { 114 optionsRegistry.AddHelp(defn, help) 115 } 116 } 117 118 // make per-generation output rule markers 119 for ruleName, rule := range allOutputRules { 120 ruleMarker := markers.Must(markers.MakeDefinition(fmt.Sprintf("output:%s:%s", genName, ruleName), markers.DescribesPackage, rule)) 121 if err := optionsRegistry.Register(ruleMarker); err != nil { 122 panic(err) 123 } 124 if helpGiver, hasHelp := rule.(genall.HasHelp); hasHelp { 125 if help := helpGiver.Help(); help != nil { 126 optionsRegistry.AddHelp(ruleMarker, help) 127 } 128 } 129 } 130 } 131 132 // make "default output" output rule markers 133 for ruleName, rule := range allOutputRules { 134 ruleMarker := markers.Must(markers.MakeDefinition("output:"+ruleName, markers.DescribesPackage, rule)) 135 if err := optionsRegistry.Register(ruleMarker); err != nil { 136 panic(err) 137 } 138 if helpGiver, hasHelp := rule.(genall.HasHelp); hasHelp { 139 if help := helpGiver.Help(); help != nil { 140 optionsRegistry.AddHelp(ruleMarker, help) 141 } 142 } 143 } 144 145 // add in the common options markers 146 if err := genall.RegisterOptionsMarkers(optionsRegistry); err != nil { 147 panic(err) 148 } 149 } 150 151 func generate(rawOpts []string) error { 152 rt, err := genall.FromOptions(optionsRegistry, rawOpts) 153 if err != nil { 154 panic(err) 155 } 156 if len(rt.Generators) == 0 { 157 return fmt.Errorf("no generators specified") 158 } 159 160 if hadErrs := rt.Run(); hadErrs { 161 return fmt.Errorf("not all generators ran successfully") 162 } 163 164 return nil 165 } 166 167 func generateDeepCopy(boilerplatePath, path string) error { 168 return generate([]string{ 169 "object:headerFile=\"" + boilerplatePath + "\"", 170 "paths=\"" + path + "\"", 171 }) 172 } 173 174 func generateCrd(path string) error { 175 return generate([]string{ 176 "crd:trivialVersions=true", 177 "crd", 178 "paths=\"" + path + "\"", 179 "output:crd:buffer", 180 }) 181 } 182 183 func generateCrdToFolder(path, folder string) error { 184 return generate([]string{ 185 "crd:trivialVersions=true", 186 "crd", 187 "paths=\"" + path + "\"", 188 "output:crd:artifacts:config=\"" + folder + "\"", 189 }) 190 }