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  }