github.com/jmrodri/operator-sdk@v0.5.0/commands/operator-sdk/cmd/generate/k8s.go (about) 1 // Copyright 2018 The Operator-SDK Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package generate 16 17 import ( 18 "fmt" 19 "io/ioutil" 20 "os/exec" 21 "path/filepath" 22 "strings" 23 24 genutil "github.com/operator-framework/operator-sdk/commands/operator-sdk/cmd/generate/internal" 25 "github.com/operator-framework/operator-sdk/internal/util/projutil" 26 "github.com/operator-framework/operator-sdk/pkg/scaffold" 27 28 log "github.com/sirupsen/logrus" 29 "github.com/spf13/cobra" 30 ) 31 32 func NewGenerateK8SCmd() *cobra.Command { 33 return &cobra.Command{ 34 Use: "k8s", 35 Short: "Generates Kubernetes code for custom resource", 36 Long: `k8s generator generates code for custom resources given the API 37 specs in pkg/apis/<group>/<version> directories to comply with kube-API 38 requirements. Go code is generated under 39 pkg/apis/<group>/<version>/zz_generated.deepcopy.go. 40 41 Example: 42 $ operator-sdk generate k8s 43 $ tree pkg/apis 44 pkg/apis/ 45 └── app 46 └── v1alpha1 47 ├── zz_generated.deepcopy.go 48 `, 49 RunE: k8sFunc, 50 } 51 } 52 53 func k8sFunc(cmd *cobra.Command, args []string) error { 54 if len(args) != 0 { 55 return fmt.Errorf("command %s doesn't accept any arguments", cmd.CommandPath()) 56 } 57 58 // Only Go projects can generate k8s deepcopy code. 59 if err := projutil.CheckGoProjectCmd(cmd); err != nil { 60 return err 61 } 62 63 return K8sCodegen() 64 } 65 66 // K8sCodegen performs deepcopy code-generation for all custom resources under pkg/apis 67 func K8sCodegen() error { 68 projutil.MustInProjectRoot() 69 70 wd := projutil.MustGetwd() 71 repoPkg := projutil.CheckAndGetProjectGoPkg() 72 srcDir := filepath.Join(wd, "vendor", "k8s.io", "code-generator") 73 binDir := filepath.Join(wd, scaffold.BuildBinDir) 74 75 if err := buildCodegenBinaries(binDir, srcDir); err != nil { 76 return err 77 } 78 79 gvMap, err := genutil.ParseGroupVersions() 80 if err != nil { 81 return fmt.Errorf("failed to parse group versions: (%v)", err) 82 } 83 gvb := &strings.Builder{} 84 for g, vs := range gvMap { 85 gvb.WriteString(fmt.Sprintf("%s:%v, ", g, vs)) 86 } 87 88 log.Infof("Running deepcopy code-generation for Custom Resource group versions: [%v]\n", gvb.String()) 89 90 if err := deepcopyGen(binDir, repoPkg, gvMap); err != nil { 91 return err 92 } 93 94 if err = defaulterGen(binDir, repoPkg, gvMap); err != nil { 95 return err 96 } 97 98 log.Info("Code-generation complete.") 99 return nil 100 } 101 102 func buildCodegenBinaries(binDir, codegenSrcDir string) error { 103 genDirs := []string{ 104 "./cmd/defaulter-gen", 105 "./cmd/client-gen", 106 "./cmd/lister-gen", 107 "./cmd/informer-gen", 108 "./cmd/deepcopy-gen", 109 } 110 return genutil.BuildCodegenBinaries(genDirs, binDir, codegenSrcDir) 111 } 112 113 func deepcopyGen(binDir, repoPkg string, gvMap map[string][]string) (err error) { 114 apisPkg := filepath.Join(repoPkg, scaffold.ApisDir) 115 args := []string{ 116 "--input-dirs", genutil.CreateFQApis(apisPkg, gvMap), 117 "--output-file-base", "zz_generated.deepcopy", 118 "--bounding-dirs", apisPkg, 119 } 120 cmd := exec.Command(filepath.Join(binDir, "deepcopy-gen"), args...) 121 if projutil.IsGoVerbose() { 122 err = projutil.ExecCmd(cmd) 123 } else { 124 cmd.Stdout = ioutil.Discard 125 cmd.Stderr = ioutil.Discard 126 err = cmd.Run() 127 } 128 if err != nil { 129 return fmt.Errorf("failed to perform deepcopy code-generation: %v", err) 130 } 131 return nil 132 } 133 134 func defaulterGen(binDir, repoPkg string, gvMap map[string][]string) (err error) { 135 apisPkg := filepath.Join(repoPkg, scaffold.ApisDir) 136 args := []string{ 137 "--input-dirs", genutil.CreateFQApis(apisPkg, gvMap), 138 "--output-file-base", "zz_generated.defaults", 139 } 140 cmd := exec.Command(filepath.Join(binDir, "defaulter-gen"), args...) 141 if projutil.IsGoVerbose() { 142 err = projutil.ExecCmd(cmd) 143 } else { 144 cmd.Stdout = ioutil.Discard 145 cmd.Stderr = ioutil.Discard 146 err = cmd.Run() 147 } 148 if err != nil { 149 return fmt.Errorf("failed to perform defaulter code-generation: %v", err) 150 } 151 return nil 152 }