github.skymusic.top/operator-framework/operator-sdk@v0.8.2/cmd/operator-sdk/internal/genutil/genutil.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 genutil 16 17 import ( 18 "fmt" 19 "io/ioutil" 20 "os" 21 "os/exec" 22 "path/filepath" 23 "strings" 24 25 flags "github.com/operator-framework/operator-sdk/internal/pkg/flags" 26 "github.com/operator-framework/operator-sdk/internal/pkg/scaffold" 27 "github.com/operator-framework/operator-sdk/internal/util/projutil" 28 29 log "github.com/sirupsen/logrus" 30 "github.com/spf13/viper" 31 ) 32 33 func buildCodegenBinaries(genDirs []string, binDir, codegenSrcDir string) error { 34 for _, gd := range genDirs { 35 err := runGoBuildCodegen(binDir, codegenSrcDir, gd) 36 if err != nil { 37 return err 38 } 39 } 40 return nil 41 } 42 43 func runGoBuildCodegen(binDir, repoDir, genDir string) error { 44 binPath := filepath.Join(binDir, filepath.Base(genDir)) 45 cmd := exec.Command("go", "build", "-o", binPath, genDir) 46 cmd.Dir = repoDir 47 if gf, ok := os.LookupEnv(projutil.GoFlagsEnv); ok && len(gf) != 0 { 48 cmd.Env = append(os.Environ(), projutil.GoFlagsEnv+"="+gf) 49 } 50 51 // Only print binary build info if verbosity is explicitly set. 52 if viper.GetBool(flags.VerboseOpt) { 53 return projutil.ExecCmd(cmd) 54 } 55 cmd.Stdout = ioutil.Discard 56 cmd.Stderr = ioutil.Discard 57 return cmd.Run() 58 } 59 60 // ParseGroupVersions parses the layout of pkg/apis to return a map of 61 // API groups to versions. 62 func parseGroupVersions() (map[string][]string, error) { 63 gvs := make(map[string][]string) 64 groups, err := ioutil.ReadDir(scaffold.ApisDir) 65 if err != nil { 66 return nil, fmt.Errorf("could not read pkg/apis directory to find api Versions: %v", err) 67 } 68 69 for _, g := range groups { 70 if g.IsDir() { 71 groupDir := filepath.Join(scaffold.ApisDir, g.Name()) 72 versions, err := ioutil.ReadDir(groupDir) 73 if err != nil { 74 return nil, fmt.Errorf("could not read %s directory to find api Versions: %v", groupDir, err) 75 } 76 77 gvs[g.Name()] = make([]string, 0) 78 for _, v := range versions { 79 if v.IsDir() && scaffold.ResourceVersionRegexp.MatchString(v.Name()) { 80 gvs[g.Name()] = append(gvs[g.Name()], v.Name()) 81 } 82 } 83 } 84 } 85 86 if len(gvs) == 0 { 87 return nil, fmt.Errorf("no groups or versions found in %s", scaffold.ApisDir) 88 } 89 return gvs, nil 90 } 91 92 // CreateFQApis return a string of all fully qualified pkg + groups + versions 93 // of pkg and gvs in the format: 94 // "pkg/groupA/v1,pkg/groupA/v2,pkg/groupB/v1" 95 func createFQApis(pkg string, gvs map[string][]string) string { 96 gn := 0 97 fqb := &strings.Builder{} 98 for g, vs := range gvs { 99 for vn, v := range vs { 100 fqb.WriteString(filepath.Join(pkg, g, v)) 101 if vn < len(vs)-1 { 102 fqb.WriteString(",") 103 } 104 } 105 if gn < len(gvs)-1 { 106 fqb.WriteString(",") 107 } 108 gn++ 109 } 110 return fqb.String() 111 } 112 113 func withHeaderFile(f func(string) error) (err error) { 114 i, err := (&scaffold.Boilerplate{}).GetInput() 115 if err != nil { 116 return err 117 } 118 hf := i.Path 119 if _, err := os.Stat(hf); os.IsNotExist(err) { 120 if hf, err = createEmptyTmpFile(); err != nil { 121 return err 122 } 123 defer func() { 124 if err = os.RemoveAll(hf); err != nil { 125 log.Error(err) 126 } 127 }() 128 } 129 return f(hf) 130 } 131 132 func createEmptyTmpFile() (string, error) { 133 f, err := ioutil.TempFile("", "") 134 if err != nil { 135 return "", err 136 } 137 if err = f.Close(); err != nil { 138 return "", err 139 } 140 return f.Name(), nil 141 }