github.com/mkimuram/operator-sdk@v0.7.1-0.20190410172100-52ad33a4bda0/cmd/operator-sdk/olmcatalog/gen-csv.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 olmcatalog 16 17 import ( 18 "fmt" 19 "io/ioutil" 20 "path/filepath" 21 "strings" 22 23 "github.com/operator-framework/operator-sdk/internal/pkg/scaffold" 24 "github.com/operator-framework/operator-sdk/internal/pkg/scaffold/input" 25 catalog "github.com/operator-framework/operator-sdk/internal/pkg/scaffold/olm-catalog" 26 "github.com/operator-framework/operator-sdk/internal/util/fileutil" 27 "github.com/operator-framework/operator-sdk/internal/util/projutil" 28 29 "github.com/coreos/go-semver/semver" 30 log "github.com/sirupsen/logrus" 31 "github.com/spf13/cobra" 32 ) 33 34 var ( 35 csvVersion string 36 fromVersion string 37 csvConfigPath string 38 updateCRDs bool 39 ) 40 41 func newGenCSVCmd() *cobra.Command { 42 genCSVCmd := &cobra.Command{ 43 Use: "gen-csv", 44 Short: "Generates a Cluster Service Version yaml file for the operator", 45 Long: `The gen-csv command generates a Cluster Service Version (CSV) YAML manifest 46 for the operator. This file is used to publish the operator to the OLM Catalog. 47 48 A CSV semantic version is supplied via the --csv-version flag. If your operator 49 has already generated a CSV manifest you want to use as a base, supply its 50 version to --from-version. Otherwise the SDK will scaffold a new CSV manifest. 51 52 Configure CSV generation by writing a config file 'deploy/olm-catalog/csv-config.yaml`, 53 RunE: genCSVFunc, 54 } 55 56 genCSVCmd.Flags().StringVar(&csvVersion, "csv-version", "", "Semantic version of the CSV") 57 genCSVCmd.MarkFlagRequired("csv-version") 58 genCSVCmd.Flags().StringVar(&fromVersion, "from-version", "", "Semantic version of an existing CSV to use as a base") 59 genCSVCmd.Flags().StringVar(&csvConfigPath, "csv-config", "", "Path to CSV config file. Defaults to deploy/olm-catalog/csv-config.yaml") 60 genCSVCmd.Flags().BoolVar(&updateCRDs, "update-crds", false, "Update CRD manifests in deploy/{operator-name}/{csv-version} the using latest API's") 61 62 return genCSVCmd 63 } 64 65 func genCSVFunc(cmd *cobra.Command, args []string) error { 66 if len(args) != 0 { 67 return fmt.Errorf("command %s doesn't accept any arguments", cmd.CommandPath()) 68 } 69 70 if err := verifyGenCSVFlags(); err != nil { 71 return err 72 } 73 74 absProjectPath := projutil.MustGetwd() 75 cfg := &input.Config{ 76 AbsProjectPath: absProjectPath, 77 ProjectName: filepath.Base(absProjectPath), 78 } 79 if projutil.IsOperatorGo() { 80 cfg.Repo = projutil.CheckAndGetProjectGoPkg() 81 } 82 83 log.Infof("Generating CSV manifest version %s", csvVersion) 84 85 s := &scaffold.Scaffold{} 86 csv := &catalog.CSV{ 87 CSVVersion: csvVersion, 88 FromVersion: fromVersion, 89 ConfigFilePath: csvConfigPath, 90 } 91 if err := s.Execute(cfg, csv); err != nil { 92 return fmt.Errorf("catalog scaffold failed: (%v)", err) 93 } 94 95 // Write CRD's to the new or updated CSV package dir. 96 if updateCRDs { 97 input, err := csv.GetInput() 98 if err != nil { 99 return err 100 } 101 cfg, err := catalog.GetCSVConfig(csvConfigPath) 102 if err != nil { 103 return err 104 } 105 err = writeCRDsToDir(cfg.CRDCRPaths, filepath.Dir(input.Path)) 106 if err != nil { 107 return err 108 } 109 } 110 111 return nil 112 } 113 114 func verifyGenCSVFlags() error { 115 if err := verifyCSVVersion(csvVersion); err != nil { 116 return err 117 } 118 if fromVersion != "" { 119 if err := verifyCSVVersion(fromVersion); err != nil { 120 return err 121 } 122 } 123 if fromVersion != "" && csvVersion == fromVersion { 124 return fmt.Errorf("from-version (%s) cannot equal csv-version; set only csv-version instead", fromVersion) 125 } 126 return nil 127 } 128 129 func verifyCSVVersion(version string) error { 130 v, err := semver.NewVersion(version) 131 if err != nil { 132 return fmt.Errorf("%s is not a valid semantic version: (%v)", version, err) 133 } 134 // Ensures numerical values composing csvVersion don't contain leading 0's, 135 // ex. 01.01.01 136 if v.String() != version { 137 return fmt.Errorf("provided CSV version %s contains bad values (parses to %s)", version, v) 138 } 139 return nil 140 } 141 142 func writeCRDsToDir(crdPaths []string, toDir string) error { 143 for _, p := range crdPaths { 144 if !strings.HasSuffix(p, "crd.yaml") { 145 continue 146 } 147 b, err := ioutil.ReadFile(p) 148 if err != nil { 149 return err 150 } 151 path := filepath.Join(toDir, filepath.Base(p)) 152 err = ioutil.WriteFile(path, b, fileutil.DefaultFileMode) 153 if err != nil { 154 return err 155 } 156 } 157 return nil 158 }