-
Notifications
You must be signed in to change notification settings - Fork 1.8k
internal/generator/olm-catalog: implement CSV generator #2407
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
422c4d9
19f3eae
bd53fde
88910c1
7ca8662
f4778df
6fab2c9
8679db1
ba3bfa6
b46264e
5f3699c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,13 +17,13 @@ package generate | |
import ( | ||
"fmt" | ||
"io/ioutil" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
|
||
"github.com/operator-framework/operator-sdk/internal/generate/gen" | ||
gencatalog "github.com/operator-framework/operator-sdk/internal/generate/olm-catalog" | ||
"github.com/operator-framework/operator-sdk/internal/scaffold" | ||
"github.com/operator-framework/operator-sdk/internal/scaffold/input" | ||
catalog "github.com/operator-framework/operator-sdk/internal/scaffold/olm-catalog" | ||
"github.com/operator-framework/operator-sdk/internal/util/fileutil" | ||
"github.com/operator-framework/operator-sdk/internal/util/k8sutil" | ||
"github.com/operator-framework/operator-sdk/internal/util/projutil" | ||
|
@@ -37,8 +37,8 @@ type csvCmd struct { | |
csvVersion string | ||
csvChannel string | ||
fromVersion string | ||
csvConfigPath string | ||
operatorName string | ||
includePaths []string | ||
updateCRDs bool | ||
defaultChannel bool | ||
} | ||
|
@@ -53,9 +53,7 @@ for the operator. This file is used to publish the operator to the OLM Catalog. | |
|
||
A CSV semantic version is supplied via the --csv-version flag. If your operator | ||
has already generated a CSV manifest you want to use as a base, supply its | ||
version to --from-version. Otherwise the SDK will scaffold a new CSV manifest. | ||
|
||
Configure CSV generation by writing a config file 'deploy/olm-catalog/csv-config.yaml`, | ||
version to --from-version. Otherwise the SDK will scaffold a new CSV manifest.`, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
// The CSV generator assumes that the deploy and pkg directories are | ||
// present at runtime, so this command must be run in a project's root. | ||
|
@@ -74,76 +72,63 @@ Configure CSV generation by writing a config file 'deploy/olm-catalog/csv-config | |
}, | ||
} | ||
|
||
cmd.Flags().StringVar(&c.csvVersion, "csv-version", "", "Semantic version of the CSV") | ||
cmd.Flags().StringVar(&c.csvVersion, "csv-version", "", | ||
"Semantic version of the CSV") | ||
if err := cmd.MarkFlagRequired("csv-version"); err != nil { | ||
log.Fatalf("Failed to mark `csv-version` flag for `generate csv` subcommand as required: %v", err) | ||
} | ||
cmd.Flags().StringVar(&c.fromVersion, "from-version", "", "Semantic version of an existing CSV to use as a base") | ||
cmd.Flags().StringVar(&c.csvConfigPath, "csv-config", "", "Path to CSV config file. Defaults to deploy/olm-catalog/csv-config.yaml") | ||
cmd.Flags().BoolVar(&c.updateCRDs, "update-crds", false, "Update CRD manifests in deploy/{operator-name}/{csv-version} the using latest API's") | ||
cmd.Flags().StringVar(&c.operatorName, "operator-name", "", "Operator name to use while generating CSV") | ||
cmd.Flags().StringVar(&c.csvChannel, "csv-channel", "", "Channel the CSV should be registered under in the package manifest") | ||
cmd.Flags().BoolVar(&c.defaultChannel, "default-channel", false, "Use the channel passed to --csv-channel as the package manifests' default channel. Only valid when --csv-channel is set") | ||
cmd.Flags().StringVar(&c.fromVersion, "from-version", "", | ||
"Semantic version of an existing CSV to use as a base") | ||
cmd.Flags().StringSliceVar(&c.includePaths, "include", []string{scaffold.DeployDir}, | ||
"Paths to include in CSV generation, ex. \"deploy/prod,deploy/test\". "+ | ||
"If this flag is set and you want to enable default behavior, "+ | ||
"you must include \"deploy/\" in the argument list") | ||
cmd.Flags().BoolVar(&c.updateCRDs, "update-crds", false, | ||
"Update CRD manifests in deploy/{operator-name}/{csv-version} the using latest API's") | ||
cmd.Flags().StringVar(&c.operatorName, "operator-name", "", | ||
"Operator name to use while generating CSV") | ||
cmd.Flags().StringVar(&c.csvChannel, "csv-channel", "", | ||
"Channel the CSV should be registered under in the package manifest") | ||
cmd.Flags().BoolVar(&c.defaultChannel, "default-channel", false, | ||
"Use the channel passed to --csv-channel as the package manifests' default channel. "+ | ||
"Only valid when --csv-channel is set") | ||
|
||
return cmd | ||
} | ||
|
||
func (c csvCmd) run() error { | ||
|
||
absProjectPath := projutil.MustGetwd() | ||
cfg := &input.Config{ | ||
AbsProjectPath: absProjectPath, | ||
ProjectName: filepath.Base(absProjectPath), | ||
} | ||
if projutil.IsOperatorGo() { | ||
cfg.Repo = projutil.GetGoPkg() | ||
} | ||
|
||
log.Infof("Generating CSV manifest version %s", c.csvVersion) | ||
|
||
csvCfg, err := catalog.GetCSVConfig(c.csvConfigPath) | ||
if err != nil { | ||
return err | ||
} | ||
if c.operatorName == "" { | ||
// Use config operator name if not set by CLI, i.e. prefer CLI value over | ||
// config value. | ||
if c.operatorName = csvCfg.OperatorName; c.operatorName == "" { | ||
// Default to using project name if both are empty. | ||
c.operatorName = filepath.Base(absProjectPath) | ||
} | ||
c.operatorName = filepath.Base(projutil.MustGetwd()) | ||
} | ||
|
||
s := &scaffold.Scaffold{} | ||
csv := &catalog.CSV{ | ||
CSVVersion: c.csvVersion, | ||
FromVersion: c.fromVersion, | ||
ConfigFilePath: c.csvConfigPath, | ||
OperatorName: c.operatorName, | ||
} | ||
err = s.Execute(cfg, csv) | ||
if err != nil { | ||
return fmt.Errorf("catalog scaffold failed: %v", err) | ||
cfg := gen.Config{ | ||
OperatorName: c.operatorName, | ||
Filters: gen.MakeFilters(c.includePaths...), | ||
} | ||
|
||
gcfg := gen.Config{ | ||
OperatorName: c.operatorName, | ||
OutputDir: filepath.Join(gencatalog.OLMCatalogDir, c.operatorName), | ||
csv := gencatalog.NewCSV(cfg, c.csvVersion, c.fromVersion) | ||
if err := csv.Generate(); err != nil { | ||
return fmt.Errorf("error generating CSV: %v", err) | ||
} | ||
pkg := gencatalog.NewPackageManifest(gcfg, c.csvVersion, c.csvChannel, c.defaultChannel) | ||
pkg := gencatalog.NewPackageManifest(cfg, c.csvVersion, c.csvChannel, c.defaultChannel) | ||
if err := pkg.Generate(); err != nil { | ||
return fmt.Errorf("error generating package manifest: %v", err) | ||
} | ||
|
||
// Write CRD's to the new or updated CSV package dir. | ||
if c.updateCRDs { | ||
input, err := csv.GetInput() | ||
crdManifestSet, err := findCRDs(c.includePaths...) | ||
if err != nil { | ||
return err | ||
} | ||
err = writeCRDsToDir(csvCfg.CRDCRPaths, filepath.Dir(input.Path)) | ||
if err != nil { | ||
return err | ||
bundleDir := filepath.Join(gencatalog.OLMCatalogDir, strings.ToLower(c.operatorName), c.csvVersion) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @estroz I might have missed this from previous PRs but if the CSV generator inputs are meant to be configurable i.e change Is there any way we can stop using that constant, and instead use the generator's input for Not sure if any other cmds that need to have a configurable "deploy" directory are using this constant as well. That could be another thing to watch out for. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Going to reconsider how inputs/filters are set up. |
||
for name, b := range crdManifestSet { | ||
path := filepath.Join(bundleDir, name) | ||
if err = ioutil.WriteFile(path, b, fileutil.DefaultFileMode); err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
|
||
|
@@ -183,25 +168,41 @@ func validateVersion(version string) error { | |
return nil | ||
} | ||
|
||
func writeCRDsToDir(crdPaths []string, toDir string) error { | ||
for _, p := range crdPaths { | ||
b, err := ioutil.ReadFile(p) | ||
if err != nil { | ||
return err | ||
} | ||
typeMeta, err := k8sutil.GetTypeMetaFromBytes(b) | ||
// findCRDs searches directories and files in paths for CRD manifest paths, | ||
// returning a map of paths to file contents. | ||
func findCRDs(paths ...string) (map[string][]byte, error) { | ||
crdFileSet := map[string][]byte{} | ||
for _, path := range paths { | ||
info, err := os.Stat(path) | ||
if err != nil { | ||
return err | ||
} | ||
if typeMeta.Kind != "CustomResourceDefinition" { | ||
continue | ||
return nil, err | ||
} | ||
|
||
path := filepath.Join(toDir, filepath.Base(p)) | ||
err = ioutil.WriteFile(path, b, fileutil.DefaultFileMode) | ||
if err != nil { | ||
return err | ||
if info.IsDir() { | ||
subsetPaths, err := k8sutil.GetCRDManifestPaths(path) | ||
if err != nil { | ||
return nil, err | ||
} | ||
for _, crdPath := range subsetPaths { | ||
b, err := ioutil.ReadFile(crdPath) | ||
if err != nil { | ||
return nil, err | ||
} | ||
crdFileSet[filepath.Base(crdPath)] = b | ||
} | ||
} else { | ||
b, err := ioutil.ReadFile(path) | ||
if err != nil { | ||
return nil, err | ||
} | ||
typeMeta, err := k8sutil.GetTypeMetaFromBytes(b) | ||
if err != nil { | ||
log.Infof("Skipping non-manifest file %s", path) | ||
continue | ||
} | ||
if typeMeta.Kind == "CustomResourceDefinition" { | ||
crdFileSet[filepath.Base(path)] = b | ||
} | ||
} | ||
} | ||
return nil | ||
return crdFileSet, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.