Skip to content

Commit 3332819

Browse files
committed
Replace input keys bundleDirKey and manifestsDirKey with private fields
bundleDirKey and manifestsDirKey were not suited to be generator input keys. Much simpler to have them as private fields. Plus some linter and cli docs cleanup.
1 parent d4c4637 commit 3332819

File tree

8 files changed

+96
-75
lines changed

8 files changed

+96
-75
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
- Add Prometheus metrics support to Ansible-based operators. ([#2179](https://github.com/operator-framework/operator-sdk/pull/2179))
99
- On `generate csv`, populate a CSV manifest’s `spec.icon`, `spec.keywords`, and `spec.mantainers` fields with empty values to better inform users how to add data. ([#2521](https://github.com/operator-framework/operator-sdk/pull/2521))
1010
- Added the [`generate csv --include`](doc/cli/operator-sdk_generate_csv.md#options) option to include files as input to the CSV generator in lieu of a config. ([#2249](https://github.com/operator-framework/operator-sdk/pull/2249))
11+
- Added the [`generate csv --inputs`](doc/cli/operator-sdk_generate_csv.md#options) option to allow configuring input locations for operator manifests and API types directories and input to the CSV generator in lieu of a config. ([#2511](https://github.com/operator-framework/operator-sdk/pull/2511))
1112

1213
### Changed
1314
- Ansible scaffolding has been rewritten to be simpler and make use of newer features of Ansible and Molecule.
@@ -23,7 +24,7 @@
2324

2425
### Removed
2526

26-
- **Breaking Change:** Removed CSV configuration file support (defaulting to deploy/olm-catalog/csv-config.yaml) in favor of including files as input to the generator using [`generate csv --include`](doc/cli/operator-sdk_generate_csv.md#options), defaulting to the `deploy/` directory. ([#2249](https://github.com/operator-framework/operator-sdk/pull/2249))
27+
- **Breaking Change:** Removed CSV configuration file support (defaulting to deploy/olm-catalog/csv-config.yaml) in favor of specifying inputs to the generator via [`generate csv --input`](doc/cli/operator-sdk_generate_csv.md#options), and configuring output locations via [`generate csv --outputDir`](doc/cli/operator-sdk_generate_csv.md#options). ([#2511](https://github.com/operator-framework/operator-sdk/pull/2511))
2728

2829
### Bug Fixes
2930

cmd/operator-sdk/generate/csv.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ version to --from-version. Otherwise the SDK will scaffold a new CSV manifest.`,
8989
Use this to set custom paths for operator manifests and API type definitions
9090
E.g: --inputs deploy=config/production,apis=pkg/myapp/apis
9191
Supported input keys:
92-
- deploy=<path to root directory for operator manifests (Deployment, RBAC, CRDs)>
93-
- apis=<path to root directory for API type defintions>
92+
- deploy=<project-relative path to root directory for operator manifests (Deployment, RBAC, CRDs)>
93+
- apis=<project-relative path to root directory for API type defintions>
9494
`)
9595
cmd.Flags().StringVar(&c.outputDir, "output-dir", scaffold.DeployDir,
9696
"Base directory to output generated CSV. The resulting CSV bundle directory"+
@@ -139,7 +139,7 @@ func (c csvCmd) run() error {
139139
if err != nil {
140140
return fmt.Errorf("failed to update CRD's: %v", err)
141141
}
142-
// TODO: This path should come from the CSV generator
142+
// TODO: This path should come from the CSV generator field csvOutputDir
143143
bundleDir := filepath.Join(c.outputDir, gencatalog.OLMCatalogChildDir, c.operatorName, c.csvVersion)
144144
for path, b := range crdManifestSet {
145145
path = filepath.Join(bundleDir, path)

doc/cli/operator-sdk_generate_csv.md

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,21 @@ operator-sdk generate csv [flags]
1818
### Options
1919

2020
```
21-
--csv-channel string Channel the CSV should be registered under in the package manifest
22-
--csv-version string Semantic version of the CSV
23-
--default-channel Use the channel passed to --csv-channel as the package manifests' default channel. Only valid when --csv-channel is set
24-
--from-version string Semantic version of an existing CSV to use as a base
25-
-h, --help help for csv
26-
--include strings 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 (default [deploy])
27-
--operator-name string Operator name to use while generating CSV
28-
--output-dir string Base directory to output generated CSV. The resulting CSV bundle directory will be "<output-dir>/olm-catalog/<operator-name>/<csv-version>" (default "deploy")
29-
--update-crds Update CRD manifests in deploy/{operator-name}/{csv-version} the using latest API's
21+
--csv-channel string Channel the CSV should be registered under in the package manifest
22+
--csv-version string Semantic version of the CSV
23+
--default-channel Use the channel passed to --csv-channel as the package manifests' default channel. Only valid when --csv-channel is set
24+
--from-version string Semantic version of an existing CSV to use as a base
25+
-h, --help help for csv
26+
--inputs stringToString Key value input paths used in CSV generation.
27+
Use this to set custom paths for operator manifests and API type definitions
28+
E.g: --inputs deploy=config/production,apis=pkg/myapp/apis
29+
Supported input keys:
30+
- deploy=<project-relative path to root directory for operator manifests (Deployment, RBAC, CRDs)>
31+
- apis=<project-relative path to root directory for API type defintions>
32+
(default [apis=pkg/apis,deploy=deploy])
33+
--operator-name string Operator name to use while generating CSV
34+
--output-dir string Base directory to output generated CSV. The resulting CSV bundle directorywill be "<output-dir>/olm-catalog/<operator-name>/<csv-version>" (default "deploy")
35+
--update-crds Update CRD manifests in deploy/{operator-name}/{csv-version} the using latest API's
3036
```
3137

3238
### SEE ALSO

internal/generate/olm-catalog/csv.go

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,6 @@ const (
5151

5252
// Input keys for CSV generator whose values are the filepaths for the respective input directories
5353

54-
// DEBUG: Why is this an input key? Users don't need to configure this.
55-
// bundleDirKey is for the location of the bundle manifests directory
56-
bundleDirKey = "bundle"
5754
// DeployDirKey is for the location of the operator manifests directory e.g "deploy/production"
5855
DeployDirKey = "deploy"
5956
// APIsDirKey is for the location of the API types directory e.g "pkg/apis"
@@ -68,6 +65,12 @@ type csvGenerator struct {
6865
// manifest with this version should exist at:
6966
// deploy/olm-catalog/{from_version}/operator-name.v{from_version}.{csvYamlFileExt}
7067
fromVersion string
68+
// existingCSVBundleDir is set if the generator needs to update from
69+
// an existing CSV bundle directory
70+
existingCSVBundleDir string
71+
// csvOutputDir is the bundle directory filepath where the CSV will be generated
72+
// This is set according to the generator's OutputDir
73+
csvOutputDir string
7174
}
7275

7376
func NewCSV(cfg gen.Config, csvVersion, fromVersion string) gen.Generator {
@@ -88,22 +91,23 @@ func NewCSV(cfg gen.Config, csvVersion, fromVersion string) gen.Generator {
8891
// Set to non-standard location.
8992
olmCatalogDir = filepath.Join(g.Inputs[DeployDirKey], OLMCatalogChildDir)
9093
}
91-
if bundle, ok := g.Inputs[bundleDirKey]; !ok || bundle == "" {
92-
// Initialize so we don't have to check for key existence elsewhere.
93-
g.Inputs[bundleDirKey] = ""
94-
parentDir := filepath.Join(olmCatalogDir, g.OperatorName)
95-
if isBundleDirExist(parentDir, g.fromVersion) {
96-
g.Inputs[bundleDirKey] = filepath.Join(olmCatalogDir, g.OperatorName, g.fromVersion)
97-
} else if isBundleDirExist(parentDir, g.csvVersion) {
98-
g.Inputs[bundleDirKey] = filepath.Join(olmCatalogDir, g.OperatorName, g.csvVersion)
99-
}
94+
95+
parentDir := filepath.Join(olmCatalogDir, g.OperatorName)
96+
if isBundleDirExist(parentDir, g.fromVersion) {
97+
g.existingCSVBundleDir = filepath.Join(olmCatalogDir, g.OperatorName, g.fromVersion)
98+
} else if isBundleDirExist(parentDir, g.csvVersion) {
99+
g.existingCSVBundleDir = filepath.Join(olmCatalogDir, g.OperatorName, g.csvVersion)
100100
}
101+
101102
if apisDir, ok := g.Inputs[APIsDirKey]; !ok || apisDir == "" {
102103
g.Inputs[APIsDirKey] = scaffold.ApisDir
103104
}
104105
if g.OutputDir == "" {
105106
g.OutputDir = scaffold.DeployDir
106107
}
108+
109+
// Set the CSV bundle dir output path under the generator's OutputDir
110+
g.csvOutputDir = filepath.Join(g.OutputDir, OLMCatalogChildDir, g.OperatorName, g.csvVersion)
107111
return g
108112
}
109113

@@ -112,8 +116,13 @@ func isBundleDirExist(parentDir, version string) bool {
112116
if parentDir == "" || version == "" {
113117
return false
114118
}
115-
_, err := os.Stat(filepath.Join(parentDir, version))
116-
return err == nil || os.IsExist(err)
119+
bundleDir := filepath.Join(parentDir, version)
120+
_, err := os.Stat(bundleDir)
121+
if !os.IsNotExist(err) {
122+
// TODO: return and handle this error
123+
log.Fatalf("Failed to stat existing bundle directory %s: %v", bundleDir, err)
124+
}
125+
return err == nil
117126
}
118127

119128
func getCSVName(name, version string) string {
@@ -135,12 +144,11 @@ func (g csvGenerator) Generate() error {
135144
return errors.New("error generating CSV manifest: no generated file found")
136145
}
137146

138-
csvOutputDir := filepath.Join(g.OutputDir, OLMCatalogChildDir, g.OperatorName, g.csvVersion)
139-
if err = os.MkdirAll(csvOutputDir, fileutil.DefaultDirFileMode); err != nil {
140-
return errors.Wrapf(err, "error mkdir %s", csvOutputDir)
147+
if err = os.MkdirAll(g.csvOutputDir, fileutil.DefaultDirFileMode); err != nil {
148+
return errors.Wrapf(err, "error mkdir %s", g.csvOutputDir)
141149
}
142150
for fileName, b := range fileMap {
143-
path := filepath.Join(csvOutputDir, fileName)
151+
path := filepath.Join(g.csvOutputDir, fileName)
144152
log.Debugf("CSV generator writing %s", path)
145153
if err = ioutil.WriteFile(path, b, fileutil.DefaultFileMode); err != nil {
146154
return err
@@ -150,11 +158,12 @@ func (g csvGenerator) Generate() error {
150158
}
151159

152160
func (g csvGenerator) generate() (fileMap map[string][]byte, err error) {
153-
bundle := g.Inputs[bundleDirKey]
154161
// Get current CSV to update, otherwise start with a fresh CSV.
155162
var csv *olmapiv1alpha1.ClusterServiceVersion
156-
if bundle != "" {
157-
if csv, err = getCSVFromDir(bundle); err != nil {
163+
if g.existingCSVBundleDir != "" {
164+
// TODO: If bundle dir exists, but the CSV file does not
165+
// then we should create a new one and not return an error.
166+
if csv, err = getCSVFromDir(g.existingCSVBundleDir); err != nil {
158167
return nil, err
159168
}
160169
// TODO: validate existing CSV.
@@ -173,7 +182,8 @@ func (g csvGenerator) generate() (fileMap map[string][]byte, err error) {
173182

174183
path := getCSVFileName(g.OperatorName, g.csvVersion)
175184
if fields := getEmptyRequiredCSVFields(csv); len(fields) != 0 {
176-
if bundle != "" {
185+
if g.existingCSVBundleDir != "" {
186+
// An existing csv should have several required fields populated.
177187
log.Warnf("Required csv fields not filled in file %s:%s\n", path, joinFields(fields))
178188
} else {
179189
// A new csv won't have several required fields populated.
@@ -357,8 +367,6 @@ func (g csvGenerator) updateCSVFromManifests(csv *olmapiv1alpha1.ClusterServiceV
357367
kindManifestMap := map[schema.GroupVersionKind][][]byte{}
358368
crGVKSet := map[schema.GroupVersionKind]struct{}{}
359369
err = filepath.Walk(g.Inputs[DeployDirKey], func(path string, info os.FileInfo, werr error) error {
360-
// DEBUG: How is this walking to read deploy/crds/... manifests
361-
// if it's not walking directories?
362370
if werr != nil || info.IsDir() {
363371
return werr
364372
}

internal/generate/olm-catalog/csv_go_test.go

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
package olmcatalog
1616

1717
import (
18-
"fmt"
1918
"io/ioutil"
2019
"os"
2120
"path/filepath"
@@ -35,16 +34,10 @@ import (
3534
)
3635

3736
const (
38-
sdkCmd = "operator-sdk"
39-
40-
testProjectName = "memcached-operator"
41-
csvVersion = "0.0.3"
42-
fromVersion = "0.0.2"
43-
notExistVersion = "1.0.0"
44-
scratchBundleDir = "scratch"
45-
testGroup = "cache.example.com"
46-
testKind1 = "Memcached"
47-
testVersion1 = "v1alpha1"
37+
testProjectName = "memcached-operator"
38+
csvVersion = "0.0.3"
39+
fromVersion = "0.0.2"
40+
notExistVersion = "1.0.0"
4841
)
4942

5043
var (
@@ -68,7 +61,7 @@ func setupTestEnvWithCleanup(t *testing.T, dataDir string) (cleanupFuncs []func(
6861
return cleanupFuncs
6962
}
7063

71-
func TestGoCSVGoNew(t *testing.T) {
64+
func TestGoCSVFromNew(t *testing.T) {
7265
for _, cleanupFunc := range setupTestEnvWithCleanup(t, testGoDataDir) {
7366
defer cleanupFunc()
7467
}
@@ -77,6 +70,8 @@ func TestGoCSVGoNew(t *testing.T) {
7770
OperatorName: testProjectName,
7871
}
7972
g := NewCSV(cfg, csvVersion, "")
73+
// TODO: Expand this test to test the g.Generate() method
74+
// so we can test the CSV generator's input/out paths.
8075
fileMap, err := g.(csvGenerator).generate()
8176
if err != nil {
8277
t.Fatalf("Failed to execute CSV generator: %v", err)
@@ -153,14 +148,6 @@ func TestGoCSVIncludeAll(t *testing.T) {
153148
}
154149
}
155150

156-
func getTestCRDFile(g, k string) string {
157-
return fmt.Sprintf("%s_%s_crd.yaml", g, strings.ToLower(k)+"s")
158-
}
159-
160-
func getTestCRFile(g, v, k string) string {
161-
return fmt.Sprintf("%s_%s_%s_cr.yaml", g, v, strings.ToLower(k))
162-
}
163-
164151
func TestUpdateVersion(t *testing.T) {
165152
csv, err := getCSVFromDir(filepath.Join(testGoDataDir, OLMCatalogDir, testProjectName, fromVersion))
166153
if err != nil {

internal/generate/olm-catalog/csv_updaters.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,9 @@ func (us crds) apply(csv *olmapiv1alpha1.ClusterServiceVersion) error {
269269
return nil
270270
}
271271

272-
func updateDescriptions(csv *olmapiv1alpha1.ClusterServiceVersion, searchDir string, opType projutil.OperatorType) error {
272+
func updateDescriptions(csv *olmapiv1alpha1.ClusterServiceVersion,
273+
searchDir string,
274+
opType projutil.OperatorType) error {
273275
ownedCRDs := []olmapiv1alpha1.CRDDescription{}
274276
for _, ownedCRD := range csv.Spec.CustomResourceDefinitions.Owned {
275277
name := ownedCRD.Name

internal/generate/olm-catalog/package_manifest.go

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,6 @@ import (
3535

3636
const (
3737
packageManifestFileExt = ".package.yaml"
38-
39-
// TODO: Is this an input that needs to be set via the csv generator inputs flag?
40-
manifestsDirKey = "manifests"
4138
)
4239

4340
type pkgGenerator struct {
@@ -52,6 +49,10 @@ type pkgGenerator struct {
5249
channelIsDefault bool
5350
// PackageManifest file name
5451
fileName string
52+
53+
// existingPkgManifestDir is set to the package manifest root directory
54+
// if the generator needs to update from an existing package manifest file.
55+
existingPkgManifestDir string
5556
}
5657

5758
func NewPackageManifest(cfg gen.Config, csvVersion, channel string, isDefault bool) gen.Generator {
@@ -73,8 +74,11 @@ func NewPackageManifest(cfg gen.Config, csvVersion, channel string, isDefault bo
7374
olmCatalogDir = filepath.Join(g.Inputs[DeployDirKey], OLMCatalogChildDir)
7475
}
7576

76-
if manifests, ok := g.Inputs[manifestsDirKey]; !ok || manifests == "" {
77-
g.Inputs[manifestsDirKey] = filepath.Join(olmCatalogDir, g.OperatorName)
77+
// Check if the generator should update from an existing package manifest file
78+
pkgManifestDirPath := filepath.Join(olmCatalogDir, g.OperatorName)
79+
pkgManifestFilePath := filepath.Join(pkgManifestDirPath, g.fileName)
80+
if isFileExist(pkgManifestFilePath) {
81+
g.existingPkgManifestDir = pkgManifestDirPath
7882
}
7983

8084
if g.OutputDir == "" {
@@ -83,6 +87,15 @@ func NewPackageManifest(cfg gen.Config, csvVersion, channel string, isDefault bo
8387
return g
8488
}
8589

90+
func isFileExist(path string) bool {
91+
_, err := os.Stat(path)
92+
if !os.IsNotExist(err) {
93+
// TODO: return and handle this error
94+
log.Fatalf("Failed to stat %s: %v", path, err)
95+
}
96+
return err == nil
97+
}
98+
8699
// getPkgFileName will return the name of the PackageManifestFile
87100
func getPkgFileName(operatorName string) string {
88101
return strings.ToLower(operatorName) + packageManifestFileExt
@@ -138,23 +151,21 @@ func (g pkgGenerator) generate() (map[string][]byte, error) {
138151
return fileMap, nil
139152
}
140153

141-
// buildPackageManifest will create a registry.PackageManifest from scratch, or modify
154+
// buildPackageManifest will create a registry.PackageManifest from scratch, or reads
142155
// an existing one if found at the expected path.
143156
func (g pkgGenerator) buildPackageManifest() (registry.PackageManifest, error) {
144157
pkg := registry.PackageManifest{}
145-
path := filepath.Join(g.Inputs[manifestsDirKey], g.fileName)
146-
if _, err := os.Stat(path); err == nil {
147-
b, err := ioutil.ReadFile(path)
158+
if g.existingPkgManifestDir != "" {
159+
existingPkgManifest := filepath.Join(g.existingPkgManifestDir, g.fileName)
160+
b, err := ioutil.ReadFile(existingPkgManifest)
148161
if err != nil {
149-
return pkg, fmt.Errorf("failed to read package manifest %s: %v", path, err)
162+
return pkg, fmt.Errorf("failed to read package manifest %s: %v", existingPkgManifest, err)
150163
}
151164
if err = yaml.Unmarshal(b, &pkg); err != nil {
152-
return pkg, fmt.Errorf("failed to unmarshal package manifest %s: %v", path, err)
165+
return pkg, fmt.Errorf("failed to unmarshal package manifest %s: %v", existingPkgManifest, err)
153166
}
154-
} else if os.IsNotExist(err) {
155-
pkg = newPackageManifest(g.OperatorName, g.channel, g.csvVersion)
156167
} else {
157-
return pkg, fmt.Errorf("error reading package manifest %s: %v", path, err)
168+
pkg = newPackageManifest(g.OperatorName, g.channel, g.csvVersion)
158169
}
159170
return pkg, nil
160171
}

internal/generate/olm-catalog/package_manifest_test.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,19 @@ import (
2727

2828
// newTestPackageManifestGenerator returns a package manifest Generator populated with test values.
2929
func newTestPackageManifestGenerator() gen.Generator {
30-
inputDir := filepath.Join(testGoDataDir, OLMCatalogDir, testProjectName)
3130
cfg := gen.Config{
3231
OperatorName: testProjectName,
33-
Inputs: map[string]string{manifestsDirKey: inputDir},
3432
}
3533
g := NewPackageManifest(cfg, csvVersion, "stable", true)
36-
return g
34+
35+
// TODO: The deploy dir input should be the way to point the generator to test data
36+
// E.g: Inputs: map[string]string{DeployDirKey: testGoDataDir}
37+
38+
// Override the generator to point to the package manifest in testGoDataDir
39+
testPkgManifestDir := filepath.Join(testGoDataDir, OLMCatalogDir, testProjectName)
40+
pkgGen := g.(pkgGenerator)
41+
pkgGen.existingPkgManifestDir = testPkgManifestDir
42+
return pkgGen
3743
}
3844

3945
func TestGeneratePackageManifest(t *testing.T) {

0 commit comments

Comments
 (0)