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