github.com/joelanford/operator-sdk@v0.8.2/internal/pkg/scaffold/olm-catalog/config.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 catalog 16 17 import ( 18 "fmt" 19 "io/ioutil" 20 "os" 21 "path/filepath" 22 23 "github.com/operator-framework/operator-sdk/internal/pkg/scaffold" 24 25 "github.com/ghodss/yaml" 26 log "github.com/sirupsen/logrus" 27 ) 28 29 // CSVConfig is a configuration file for CSV composition. Its fields contain 30 // file path information. 31 type CSVConfig struct { 32 // The operator manifest file path. Defaults to deploy/operator.yaml. 33 OperatorPath string `json:"operator-path,omitempty"` 34 // The RBAC role manifest file path. Defaults to deploy/role.yaml. 35 RolePath string `json:"role-path,omitempty"` 36 // A list of CRD and CR manifest file paths. Defaults to deploy/crds. 37 CRDCRPaths []string `json:"crd-cr-paths,omitempty"` 38 } 39 40 // TODO: discuss case of no config file at default path: write new file or not. 41 func GetCSVConfig(cfgFile string) (*CSVConfig, error) { 42 cfg := &CSVConfig{} 43 if _, err := os.Stat(cfgFile); err == nil { 44 cfgData, err := ioutil.ReadFile(cfgFile) 45 if err != nil { 46 return nil, err 47 } 48 if err = yaml.Unmarshal(cfgData, cfg); err != nil { 49 return nil, err 50 } 51 } else if !os.IsNotExist(err) { 52 return nil, err 53 } 54 55 if err := cfg.setFields(); err != nil { 56 return nil, err 57 } 58 return cfg, nil 59 } 60 61 const yamlExt = ".yaml" 62 63 func (c *CSVConfig) setFields() error { 64 if c.OperatorPath == "" { 65 info, err := (&scaffold.Operator{}).GetInput() 66 if err != nil { 67 return err 68 } 69 c.OperatorPath = info.Path 70 } 71 72 if c.RolePath == "" { 73 info, err := (&scaffold.Role{}).GetInput() 74 if err != nil { 75 return err 76 } 77 c.RolePath = info.Path 78 } 79 80 if len(c.CRDCRPaths) == 0 { 81 paths, err := getManifestPathsFromDir(scaffold.CRDsDir) 82 if err != nil && !os.IsNotExist(err) { 83 return err 84 } 85 if os.IsNotExist(err) { 86 log.Infof(`Default CRDs dir "%s" does not exist. Omitting field spec.customresourcedefinitions.owned from CSV.`, scaffold.CRDsDir) 87 } else if len(paths) == 0 { 88 log.Infof(`Default CRDs dir "%s" is empty. Omitting field spec.customresourcedefinitions.owned from CSV.`, scaffold.CRDsDir) 89 } else { 90 c.CRDCRPaths = paths 91 } 92 } else { 93 // Allow user to specify a list of dirs to search. Avoid duplicate files. 94 paths, seen := make([]string, 0), make(map[string]struct{}) 95 for _, path := range c.CRDCRPaths { 96 info, err := os.Stat(path) 97 if err != nil { 98 return err 99 } 100 if info.IsDir() { 101 tmpPaths, err := getManifestPathsFromDir(path) 102 if err != nil { 103 return err 104 } 105 for _, p := range tmpPaths { 106 if _, ok := seen[p]; !ok { 107 paths = append(paths, p) 108 seen[p] = struct{}{} 109 } 110 } 111 } else if filepath.Ext(path) == yamlExt { 112 if _, ok := seen[path]; !ok { 113 paths = append(paths, path) 114 seen[path] = struct{}{} 115 } 116 } 117 } 118 c.CRDCRPaths = paths 119 } 120 121 return nil 122 } 123 124 func getManifestPathsFromDir(dir string) (paths []string, err error) { 125 err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { 126 if err != nil { 127 return err 128 } 129 if info == nil { 130 return fmt.Errorf("file info for %s was nil", path) 131 } 132 if !info.IsDir() && filepath.Ext(path) == yamlExt { 133 paths = append(paths, path) 134 } 135 return nil 136 }) 137 if err != nil { 138 return nil, err 139 } 140 return paths, nil 141 }