Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- New option for [`operator-sdk build --image-builder`](https://github.com/operator-framework/operator-sdk/blob/master/doc/sdk-cli-reference.md#build), which can be used to specify which image builder to use. Adds support for [buildah](https://github.com/containers/buildah/). ([#1311](https://github.com/operator-framework/operator-sdk/pull/1311))
- Manager is now configured with a new `DynamicRESTMapper`, which accounts for the fact that the default `RESTMapper`, which only checks resource types at startup, can't handle the case of first creating a CRD and then an instance of that CRD. ([#1329](https://github.com/operator-framework/operator-sdk/pull/1329))
- New optional flag `--write-csv-config[=path]` for [`operator-sdk olm-catalog`](https://github.com/operator-framework/operator-sdk/blob/master/doc/sdk-cli-reference.md#olm-catalog) and [`operator-sdk olm-catalog gen-csv`](https://github.com/operator-framework/operator-sdk/blob/master/doc/sdk-cli-reference.md#gen-csv) which writes a default CSV config file to `deploy/olm-catalog/csv-config.yaml` if no value is passed, or `path` if passed. This file can be modified and passed to `--csv-config` to configure `gen-csv`. ([#1346](https://github.com/operator-framework/operator-sdk/pull/1346))

### Changed

Expand Down
56 changes: 55 additions & 1 deletion cmd/operator-sdk/olmcatalog/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,70 @@
package olmcatalog

import (
"fmt"
"path/filepath"

"github.com/operator-framework/operator-sdk/internal/pkg/scaffold"
"github.com/operator-framework/operator-sdk/internal/pkg/scaffold/input"
catalog "github.com/operator-framework/operator-sdk/internal/pkg/scaffold/olm-catalog"
"github.com/operator-framework/operator-sdk/internal/util/projutil"

log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

var (
writeCSVConfigOpt = "write-csv-config"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

space

writeCSVConfigPath string
)

func NewCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "olm-catalog <olm-catalog-command>",
Use: "olm-catalog [flags] <olm-catalog-command>",
Short: "Invokes a olm-catalog command",
Long: `The operator-sdk olm-catalog command invokes a command to perform
Catalog related actions.`,
RunE: olmCatalogFunc,
}
cmd.AddCommand(newGenCSVCmd())

i, err := (&catalog.CSVConfig{}).GetInput()
if err != nil {
log.Fatalf("Error retrieving CSV config path: %v", err)
}
Comment on lines +46 to +49
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could not the path be an attribute of the struct and the check be made in the Validate func of it?

cmd.PersistentFlags().StringVar(&writeCSVConfigPath, writeCSVConfigOpt, "",
"Write a default CSV config file. A default path is used if no value is provided."+
" Set --write-csv-config=<path> to supply a non-default path")
cmd.Flag(writeCSVConfigOpt).NoOptDefVal = i.Path

return cmd
}

func olmCatalogFunc(cmd *cobra.Command, args []string) error {
if cmd.Flags().Changed(writeCSVConfigOpt) {
absProjectPath := projutil.MustGetwd()
cfg := &input.Config{
AbsProjectPath: absProjectPath,
ProjectName: filepath.Base(absProjectPath),
}
if projutil.IsOperatorGo() {
cfg.Repo = projutil.CheckAndGetProjectGoPkg()
}
s := &scaffold.Scaffold{}
if err := writeConfig(s, cfg); err != nil {
return err
}
}
return nil
Copy link
Contributor

@camilamacedo86 camilamacedo86 Nov 19, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it creating a new input.Config? Could not it be a NewConfig in its struct, or at least has a more meaningful name?

}
func writeConfig(s *scaffold.Scaffold, cfg *input.Config) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func writeConfig(s *scaffold.Scaffold, cfg *input.Config) error {
func writeCSVConfig(s *scaffold.Scaffold, cfg *input.Config) error {

log.Info("Writing new default CSV config.")
csvCfg := &catalog.CSVConfig{
Input: input.Input{Path: writeCSVConfigPath},
}
if err := s.Execute(cfg, csvCfg); err != nil {
return fmt.Errorf("error scaffolding CSV config: %v", err)
}
return nil
}
43 changes: 30 additions & 13 deletions cmd/operator-sdk/olmcatalog/gen-csv.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package olmcatalog
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"

Expand Down Expand Up @@ -56,18 +57,18 @@ Configure CSV generation by writing a config file 'deploy/olm-catalog/csv-config
genCSVCmd.Flags().StringVar(&csvVersion, "csv-version", "", "Semantic version of the CSV")
genCSVCmd.MarkFlagRequired("csv-version")
genCSVCmd.Flags().StringVar(&fromVersion, "from-version", "", "Semantic version of an existing CSV to use as a base")
genCSVCmd.Flags().StringVar(&csvConfigPath, "csv-config", "", "Path to CSV config file. Defaults to deploy/olm-catalog/csv-config.yaml")
genCSVCmd.Flags().StringVar(&csvConfigPath, "csv-config", "", "Path to CSV config file. If unset, default file paths are used")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think is good to keep the default path in the info.

genCSVCmd.Flags().BoolVar(&updateCRDs, "update-crds", false, "Update CRD manifests in deploy/{operator-name}/{csv-version} the using latest API's")

return genCSVCmd
}

func genCSVFunc(cmd *cobra.Command, args []string) error {
func genCSVFunc(cmd *cobra.Command, args []string) (err error) {
if len(args) != 0 {
return fmt.Errorf("command %s doesn't accept any arguments", cmd.CommandPath())
}

if err := verifyGenCSVFlags(); err != nil {
if err = verifyGenCSVFlags(); err != nil {
return err
}

Expand All @@ -79,30 +80,46 @@ func genCSVFunc(cmd *cobra.Command, args []string) error {
if projutil.IsOperatorGo() {
cfg.Repo = projutil.CheckAndGetProjectGoPkg()
}
s := &scaffold.Scaffold{}

if cmd.Flags().Changed(writeCSVConfigOpt) {
if err := writeConfig(s, cfg); err != nil {
return err
}
}

var csvCfgFile *catalog.CSVConfigFile
if _, err = os.Stat(csvConfigPath); err == nil {
log.Infof("Using custom CSV config %s.", csvConfigPath)
csvCfgFile, err = catalog.GetCSVConfigFile(csvConfigPath)
if err != nil {
return err
}
} else if err != nil && csvConfigPath != "" {
return fmt.Errorf("error reading CSV config %s: %v", csvConfigPath, err)
} else {
log.Info("Using default CSV config.")
csvCfgFile = &catalog.CSVConfigFile{}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could not it be improved?
By default, the default CSVFile be set then if do not find it or the customized one return an error?
Could not the logic be when the new struct is created?

log.Infof("Generating CSV manifest version %s", csvVersion)

s := &scaffold.Scaffold{}
csv := &catalog.CSV{
CSVVersion: csvVersion,
FromVersion: fromVersion,
ConfigFilePath: csvConfigPath,
CSVVersion: csvVersion,
FromVersion: fromVersion,
CSVConfigFile: csvCfgFile,
}
if err := s.Execute(cfg, csv); err != nil {
return fmt.Errorf("catalog scaffold failed: (%v)", err)
}

// Write CRD's to the new or updated CSV package dir.
if updateCRDs {
input, err := csv.GetInput()
if err != nil {
return err
}
cfg, err := catalog.GetCSVConfig(csvConfigPath)
i, err := csv.GetInput()
if err != nil {
return err
}
err = writeCRDsToDir(cfg.CRDCRPaths, filepath.Dir(input.Path))
err = writeCRDsToDir(csvCfgFile.CRDCRPaths, filepath.Dir(i.Path))
if err != nil {
return err
}
Expand Down
7 changes: 6 additions & 1 deletion doc/sdk-cli-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,10 @@ pkg/apis/app/v1alpha1/

Parent command for all OLM Catalog related commands.

#### Flags

* `--write-csv-config` string or empty - Write a default CSV config file. A default path is used if no value is provided. Set --write-csv-config=<path> to supply a non-default path

### gen-csv

Writes a Cluster Service Version (CSV) manifest and optionally CRD files to `deploy/olm-catalog/{operator-name}/{csv-version}`.
Expand All @@ -188,7 +192,8 @@ Writes a Cluster Service Version (CSV) manifest and optionally CRD files to `dep

* `--csv-version` string - (required) Semantic version of the CSV manifest.
* `--from-version` string - Semantic version of CSV manifest to use as a base for a new version.
* `--csv-config` string - Path to CSV config file. Defaults to deploy/olm-catalog/csv-config.yaml.
* `--csv-config` string - Path to CSV config file. If unset, default file paths are used
* `--write-csv-config` string or empty - Write a default CSV config file. A default path is used if no value is provided. Set --write-csv-config=<path> to supply a non-default path
* `--update-crds` Update CRD manifests in deploy/{operator-name}/{csv-version} using the latest CRD manifests.

#### Example
Expand Down
18 changes: 9 additions & 9 deletions doc/user/olm-catalog/generating-a-csv.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,23 @@ Operator SDK projects have an expected [project layout][doc-project-layout]. In

`gen-csv` reads these files and adds their data to a CSV in an alternate form.

By default, a `deploy/olm-catalog/csv-config.yaml` file is generated when `gen-csv` is first run. The defaults written in the following fields contain paths to the aforementioned files. From the [design doc][doc-csv-design]:
Both `olm-catalog` and `olm-catalog gen-csv` can write a CSV configuration file that configures parts of the CSV generation process. By setting `--write-csv-config`, these commands write a default CSV config file to `deploy/olm-catalog/csv-config.yaml`; setting `--write-csv-confg=<path>` will write a default config file to `path` instead. The defaults written in the following fields contain paths to the aforementioned files:

>Users can configure CSV composition by populating several fields in the file `deploy/olm-catalog/csv-config.yaml`:
>
>- `crd-cr-path-list`: (string(, string)\*) a list of CRD and CR manifest file/directory paths. Defaults to `[deploy/crds]`.
>- `operator-path`: (string) the operator resource manifest file path. Defaults to `deploy/operator.yaml`.
>- `rbac-path-list`: (string(, string)\*) a list of RBAC role manifest file paths. Defaults to `[deploy/role.yaml]`.
- `crd-cr-paths`: string , { string } - a list of CRD and CR manifest file/directory paths. Defaults to `[deploy/crds]`.
- `operator-path`: string - the operator `Deployment` manifest file path. Defaults to `deploy/operator.yaml`.
- `role-path`: string - the RBAC `Role` manifest file path. Defaults to `deploy/role.yaml`.

Fields in this config file can be modified to point towards alternate manifest locations. For example, if I have one set of production CR/CRD manifests under `deploy/crds/production`, and a set of test manifests under `deploy/crds/test`, and I only want to include production manifests in my CSV, I can set `crd-cr-path-list: [deploy/crds/production]`. `gen-csv` will then ignore `deploy/crds/test` when getting CR/CRD data.
**Note**: The [design doc][doc-csv-design] has outdated field information which should not be referenced.

Fields in this config file can be modified to point towards alternate manifest locations, and passed to `gen-csv --csv-config=<path>` to configure CSV generation. For example, if I have one set of production CR/CRD manifests under `deploy/crds/production`, and a set of test manifests under `deploy/crds/test`, and I only want to include production manifests in my CSV, I can set `crd-cr-paths: [deploy/crds/production]`. `gen-csv` will then ignore `deploy/crds/test` when getting CR/CRD data.

## Versioning

CSV's are versioned in path, file name, and in their `metadata.name` field. For example, running `operator-sdk olm-catalog gen-csv --csv-version 0.0.1` will generate a CSV at `deploy/olm-catalog/<operator-name>/0.0.1/<operator-name>.v0.0.1.clusterserviceversion.yaml`. A versioned directory such as `deploy/olm-catalog/<operator-name>/0.0.1` is known as a [*bundle*][doc-bundle]. Versions allow the OLM to upgrade or downgrade your Operator at runtime, i.e. in a cluster. A valid semantic version is required.

`gen-csv` allows you to upgrade your CSV using the `--from-version` flag. If you have an existing CSV with version `0.0.1` and want to write a new version `0.0.2`, you can run `operator-sdk olm-catalog gen-csv --csv-version 0.0.2 --from-version 0.0.1`. This will write a new CSV manifest to `deploy/olm-catalog/<operator-name>/0.0.2/<operator-name>.v0.0.2.clusterserviceversion.yaml` containing user-defined data from `0.0.1` and any modifications you've made to `roles.yaml`, `operator.yaml`, CR's, or CRD's.

The SDK can manage CRD's in your Operator bundle as well. You can pass the `--update-crds` flag to `gen-csv` to add or update your CRD's in your bundle by copying manifests pointed to by `crd-cr-path-list` in your config. CRD's in a bundle are not updated by default.
The SDK can manage CRD's in your Operator bundle as well. You can pass the `--update-crds` flag to `gen-csv` to add or update your CRD's in your bundle by copying manifests pointed to by `crd-cr-paths` in your config. CRD's in a bundle are not updated by default.

## First Generation

Expand Down Expand Up @@ -89,7 +89,7 @@ Required:
* `spec.labels`: (user) a list of `key:value` pairs to be used by Operator internals.
* `spec.version`: semantic version of the Operator, ex. `0.1.1`.
* `spec.installModes`: what mode of [installation namespacing][install-modes] OLM should use. Currently all but `MultiNamespace` are supported by SDK Operators.
* `spec.customresourcedefinitions`: any CRD's the Operator uses. This field will be filled by the SDK if any CRD manifests pointed to by `crd-cr-path-list` in your config.
* `spec.customresourcedefinitions`: any CRD's the Operator uses. This field will be filled by the SDK if any CRD manifests pointed to by `crd-cr-paths` in your config.
* `description`: description of the CRD.
* `resources`: any Kubernetes resources used by the CRD, ex. `Pod`'s and `ConfigMap`'s.
* `specDescriptors`: UI hints for inputs and outputs of the Operator's spec.
Expand Down
1 change: 0 additions & 1 deletion internal/pkg/scaffold/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ const (
BuildBinDir = BuildDir + filePathSep + "_output" + filePathSep + "bin"
BuildScriptDir = BuildDir + filePathSep + "bin"
DeployDir = "deploy"
OLMCatalogDir = DeployDir + filePathSep + "olm-catalog"
CRDsDir = DeployDir + filePathSep + "crds"
VersionDir = "version"
)
60 changes: 50 additions & 10 deletions internal/pkg/scaffold/olm-catalog/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,50 @@ import (
"path/filepath"

"github.com/operator-framework/operator-sdk/internal/pkg/scaffold"
"github.com/operator-framework/operator-sdk/internal/pkg/scaffold/input"

"github.com/ghodss/yaml"
"github.com/spf13/afero"
)

// CSVConfig is a configuration file for CSV composition. Its fields contain
// file path information.
const CSVConfigYamlFile = "csv-config.yaml"

// CSVConfig is a scaffold wrapper for CSVConfig such that CSVConfig's can
// be marshalled and unmarshalled correctly.
type CSVConfig struct {
input.Input
File *CSVConfigFile

// TODO: remove once fs is moved to input.Input.
fs afero.Fs
}

var _ input.File = &CSVConfig{}

func (c *CSVConfig) GetInput() (input.Input, error) {
if c.Path == "" {
c.Path = filepath.Join(OLMCatalogDir, CSVConfigYamlFile)
}
if c.File == nil {
c.File = &CSVConfigFile{}
}
return c.Input, nil
}

var _ scaffold.CustomRenderer = &CSVConfig{}

func (c *CSVConfig) SetFS(fs afero.Fs) { c.fs = fs }

func (c *CSVConfig) CustomRender() ([]byte, error) {
if err := c.File.setFields(); err != nil {
return nil, err
}
return yaml.Marshal(c.File)
}

// CSVConfigFile is a configuration file for CSV composition. Its fields contain
// file path information.
type CSVConfigFile struct {
// The operator manifest file path. Defaults to deploy/operator.yaml.
OperatorPath string `json:"operator-path,omitempty"`
// The RBAC role manifest file path. Defaults to deploy/role.yaml.
Expand All @@ -36,11 +73,10 @@ type CSVConfig struct {
CRDCRPaths []string `json:"crd-cr-paths,omitempty"`
}

// TODO: discuss case of no config file at default path: write new file or not.
func GetCSVConfig(cfgFile string) (*CSVConfig, error) {
cfg := &CSVConfig{}
if _, err := os.Stat(cfgFile); err == nil {
cfgData, err := ioutil.ReadFile(cfgFile)
func GetCSVConfigFile(path string) (*CSVConfigFile, error) {
cfg := &CSVConfigFile{}
if _, err := os.Stat(path); err == nil {
cfgData, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
Expand All @@ -59,7 +95,11 @@ func GetCSVConfig(cfgFile string) (*CSVConfig, error) {

const yamlExt = ".yaml"

func (c *CSVConfig) setFields() error {
func isYAMLFile(path string) bool {
return filepath.Ext(path) == yamlExt
}

func (c *CSVConfigFile) setFields() error {
if c.OperatorPath == "" {
info, err := (&scaffold.Operator{}).GetInput()
if err != nil {
Expand Down Expand Up @@ -101,7 +141,7 @@ func (c *CSVConfig) setFields() error {
seen[p] = struct{}{}
}
}
} else if filepath.Ext(path) == yamlExt {
} else if isYAMLFile(path) {
if _, ok := seen[path]; !ok {
paths = append(paths, path)
seen[path] = struct{}{}
Expand All @@ -122,7 +162,7 @@ func getManifestPathsFromDir(dir string) (paths []string, err error) {
if info == nil {
return fmt.Errorf("file info for %s was nil", path)
}
if !info.IsDir() && filepath.Ext(path) == yamlExt {
if !info.IsDir() && isYAMLFile(path) {
paths = append(paths, path)
}
return nil
Expand Down
6 changes: 2 additions & 4 deletions internal/pkg/scaffold/olm-catalog/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
func TestConfig(t *testing.T) {
crdsDir := filepath.Join(testDataDir, scaffold.CRDsDir)

cfg := &CSVConfig{
cfg := &CSVConfigFile{
CRDCRPaths: []string{crdsDir},
}
if err := cfg.setFields(); err != nil {
Expand All @@ -35,9 +35,7 @@ func TestConfig(t *testing.T) {
t.Errorf("Wanted 3 crd/cr files, got: %v", cfg.CRDCRPaths)
}

cfg = &CSVConfig{
CRDCRPaths: []string{crdsDir, filepath.Join(crdsDir, "app_v1alpha1_app_crd.yaml")},
}
cfg.CRDCRPaths = []string{crdsDir, filepath.Join(crdsDir, "app_v1alpha1_app_crd.yaml")}
if err := cfg.setFields(); err != nil {
t.Errorf("Set fields crd-cr paths dir file mix: (%v)", err)
}
Expand Down
Loading