@@ -17,13 +17,12 @@ package generate
17
17
import (
18
18
"fmt"
19
19
"io/ioutil"
20
+ "os"
20
21
"path/filepath"
21
22
22
23
"github.com/operator-framework/operator-sdk/internal/generate/gen"
23
24
gencatalog "github.com/operator-framework/operator-sdk/internal/generate/olm-catalog"
24
25
"github.com/operator-framework/operator-sdk/internal/scaffold"
25
- "github.com/operator-framework/operator-sdk/internal/scaffold/input"
26
- catalog "github.com/operator-framework/operator-sdk/internal/scaffold/olm-catalog"
27
26
"github.com/operator-framework/operator-sdk/internal/util/fileutil"
28
27
"github.com/operator-framework/operator-sdk/internal/util/k8sutil"
29
28
"github.com/operator-framework/operator-sdk/internal/util/projutil"
@@ -37,8 +36,11 @@ type csvCmd struct {
37
36
csvVersion string
38
37
csvChannel string
39
38
fromVersion string
40
- csvConfigPath string
41
39
operatorName string
40
+ outputDir string
41
+ deployDir string
42
+ apisDir string
43
+ crdDir string
42
44
updateCRDs bool
43
45
defaultChannel bool
44
46
}
@@ -55,33 +57,133 @@ A CSV semantic version is supplied via the --csv-version flag. If your operator
55
57
has already generated a CSV manifest you want to use as a base, supply its
56
58
version to --from-version. Otherwise the SDK will scaffold a new CSV manifest.
57
59
58
- Configure CSV generation by writing a config file 'deploy/olm-catalog/csv-config.yaml` ,
59
- RunE : func (cmd * cobra.Command , args []string ) error {
60
- // The CSV generator assumes that the deploy and pkg directories are
61
- // present at runtime, so this command must be run in a project's root.
62
- projutil .MustInProjectRoot ()
60
+ CSV input flags:
61
+ --deploy-dir:
62
+ The CSV's install strategy and permissions will be generated from the operator manifests
63
+ (Deployment and Role/ClusterRole) present in this directory.
64
+
65
+ --apis-dir:
66
+ The CSV annotation comments will be parsed from the Go types under this path to
67
+ fill out metadata for owned APIs in spec.customresourcedefinitions.owned.
68
+
69
+ --crd-dir:
70
+ The CSV's spec.customresourcedefinitions.owned field is generated from the CRD manifests
71
+ in this path.These CRD manifests are also copied over to the bundle directory if --update-crds is set.
72
+ Additionally the CR manifests will be used to populate the CSV example CRs.
73
+ ` ,
74
+ Example : `
75
+ ##### Generate CSV from default input paths #####
76
+ $ tree pkg/apis/ deploy/
77
+ pkg/apis/
78
+ ├── ...
79
+ └── cache
80
+ ├── group.go
81
+ └── v1alpha1
82
+ ├── ...
83
+ └── memcached_types.go
84
+ deploy/
85
+ ├── crds
86
+ │ ├── cache.example.com_memcacheds_crd.yaml
87
+ │ └── cache.example.com_v1alpha1_memcached_cr.yaml
88
+ ├── operator.yaml
89
+ ├── role.yaml
90
+ ├── role_binding.yaml
91
+ └── service_account.yaml
92
+
93
+ $ operator-sdk generate csv --csv-version=0.0.1 --update-crds
94
+ INFO[0000] Generating CSV manifest version 0.0.1
95
+ ...
96
+
97
+ $ tree deploy/
98
+ deploy/
99
+ ...
100
+ ├── olm-catalog
101
+ │ └── memcached-operator
102
+ │ ├── 0.0.1
103
+ │ │ ├── cache.example.com_memcacheds_crd.yaml
104
+ │ │ └── memcached-operator.v0.0.1.clusterserviceversion.yaml
105
+ │ └── memcached-operator.package.yaml
106
+ ...
107
+
108
+
63
109
110
+ ##### Generate CSV from custom input paths #####
111
+ $ operator-sdk generate csv --csv-version=0.0.1 --update-crds \
112
+ --deploy-dir=config --apis-dir=api --output-dir=production
113
+ INFO[0000] Generating CSV manifest version 0.0.1
114
+ ...
115
+
116
+ $ tree config/ api/ production/
117
+ config/
118
+ ├── crds
119
+ │ ├── cache.example.com_memcacheds_crd.yaml
120
+ │ └── cache.example.com_v1alpha1_memcached_cr.yaml
121
+ ├── operator.yaml
122
+ ├── role.yaml
123
+ ├── role_binding.yaml
124
+ └── service_account.yaml
125
+ api/
126
+ ├── ...
127
+ └── cache
128
+ ├── group.go
129
+ └── v1alpha1
130
+ ├── ...
131
+ └── memcached_types.go
132
+ production/
133
+ └── olm-catalog
134
+ └── memcached-operator
135
+ ├── 0.0.1
136
+ │ ├── cache.example.com_memcacheds_crd.yaml
137
+ │ └── memcached-operator.v0.0.1.clusterserviceversion.yaml
138
+ └── memcached-operator.package.yaml
139
+ ` ,
140
+
141
+ RunE : func (cmd * cobra.Command , args []string ) error {
64
142
if len (args ) != 0 {
65
143
return fmt .Errorf ("command %s doesn't accept any arguments" , cmd .CommandPath ())
66
144
}
67
145
if err := c .validate (); err != nil {
68
146
return fmt .Errorf ("error validating command flags: %v" , err )
69
147
}
148
+
149
+ if err := projutil .CheckProjectRoot (); err != nil {
150
+ log .Warn ("Could not detect project root. Ensure that this command " +
151
+ "runs from the project root directory." )
152
+ }
153
+
154
+ // Default for crd dir if unset
155
+ if c .crdDir == "" {
156
+ c .crdDir = c .deployDir
157
+ }
70
158
if err := c .run (); err != nil {
71
159
log .Fatal (err )
72
160
}
73
161
return nil
74
162
},
75
163
}
76
164
77
- cmd .Flags ().StringVar (& c .csvVersion , "csv-version" , "" , "Semantic version of the CSV" )
165
+ cmd .Flags ().StringVar (& c .csvVersion , "csv-version" , "" ,
166
+ "Semantic version of the CSV" )
78
167
if err := cmd .MarkFlagRequired ("csv-version" ); err != nil {
79
168
log .Fatalf ("Failed to mark `csv-version` flag for `generate csv` subcommand as required: %v" , err )
80
169
}
81
170
cmd .Flags ().StringVar (& c .fromVersion , "from-version" , "" ,
82
171
"Semantic version of an existing CSV to use as a base" )
83
- cmd .Flags ().StringVar (& c .csvConfigPath , "csv-config" , "" ,
84
- "Path to CSV config file. Defaults to deploy/olm-catalog/csv-config.yaml" )
172
+
173
+ // TODO: Allow multiple paths
174
+ // Deployment and RBAC manifests might be in different dirs e.g kubebuilder
175
+ cmd .Flags ().StringVar (& c .deployDir , "deploy-dir" , "deploy" ,
176
+ `Project relative path to root directory for operator manifests (Deployment and RBAC)` )
177
+ cmd .Flags ().StringVar (& c .apisDir , "apis-dir" , filepath .Join ("pkg" , "apis" ),
178
+ `Project relative path to root directory for API type defintions` )
179
+ // TODO: Allow multiple paths
180
+ // CRD and CR manifests might be in different dirs e.g kubebuilder
181
+ cmd .Flags ().StringVar (& c .crdDir , "crd-dir" , filepath .Join ("deploy" , "crds" ),
182
+ `Project relative path to root directory for CRD and CR manifests` )
183
+
184
+ cmd .Flags ().StringVar (& c .outputDir , "output-dir" , scaffold .DeployDir ,
185
+ "Base directory to output generated CSV. The resulting CSV bundle directory " +
186
+ "will be \" <output-dir>/olm-catalog/<operator-name>/<csv-version>\" ." )
85
187
cmd .Flags ().BoolVar (& c .updateCRDs , "update-crds" , false ,
86
188
"Update CRD manifests in deploy/{operator-name}/{csv-version} the using latest API's" )
87
189
cmd .Flags ().StringVar (& c .operatorName , "operator-name" , "" ,
@@ -96,61 +198,45 @@ Configure CSV generation by writing a config file 'deploy/olm-catalog/csv-config
96
198
}
97
199
98
200
func (c csvCmd ) run () error {
99
-
100
- absProjectPath := projutil .MustGetwd ()
101
- cfg := & input.Config {
102
- AbsProjectPath : absProjectPath ,
103
- ProjectName : filepath .Base (absProjectPath ),
104
- }
105
- if projutil .IsOperatorGo () {
106
- cfg .Repo = projutil .GetGoPkg ()
107
- }
108
-
109
201
log .Infof ("Generating CSV manifest version %s" , c .csvVersion )
110
202
111
- csvCfg , err := catalog .GetCSVConfig (c .csvConfigPath )
112
- if err != nil {
113
- return err
114
- }
115
203
if c .operatorName == "" {
116
- // Use config operator name if not set by CLI, i.e. prefer CLI value over
117
- // config value.
118
- if c .operatorName = csvCfg .OperatorName ; c .operatorName == "" {
119
- // Default to using project name if both are empty.
120
- c .operatorName = filepath .Base (absProjectPath )
121
- }
122
- }
123
-
124
- s := & scaffold.Scaffold {}
125
- csv := & catalog.CSV {
126
- CSVVersion : c .csvVersion ,
127
- FromVersion : c .fromVersion ,
128
- ConfigFilePath : c .csvConfigPath ,
129
- OperatorName : c .operatorName ,
204
+ c .operatorName = filepath .Base (projutil .MustGetwd ())
130
205
}
131
- err = s .Execute (cfg , csv )
132
- if err != nil {
133
- return fmt .Errorf ("catalog scaffold failed: %v" , err )
206
+ cfg := gen.Config {
207
+ OperatorName : c .operatorName ,
208
+ // TODO(hasbro17): Remove the Input key map when the Generator input keys
209
+ // are removed in favour of config fields in the csvGenerator
210
+ Inputs : map [string ]string {
211
+ gencatalog .DeployDirKey : c .deployDir ,
212
+ gencatalog .APIsDirKey : c .apisDir ,
213
+ gencatalog .CRDsDirKey : c .crdDir ,
214
+ },
215
+ OutputDir : c .outputDir ,
134
216
}
135
217
136
- gcfg := gen. Config {
137
- OperatorName : c . operatorName ,
138
- OutputDir : filepath . Join ( gencatalog . OLMCatalogDir , c . operatorName ),
218
+ csv := gencatalog . NewCSV ( cfg , c . csvVersion , c . fromVersion )
219
+ if err := csv . Generate (); err != nil {
220
+ return fmt . Errorf ( "error generating CSV: %v" , err )
139
221
}
140
- pkg := gencatalog .NewPackageManifest (gcfg , c .csvVersion , c .csvChannel , c .defaultChannel )
222
+ pkg := gencatalog .NewPackageManifest (cfg , c .csvVersion , c .csvChannel , c .defaultChannel )
141
223
if err := pkg .Generate (); err != nil {
142
224
return fmt .Errorf ("error generating package manifest: %v" , err )
143
225
}
144
226
145
227
// Write CRD's to the new or updated CSV package dir.
146
228
if c .updateCRDs {
147
- input , err := csv . GetInput ( )
229
+ crdManifestSet , err := findCRDFileSet ( c . crdDir )
148
230
if err != nil {
149
- return err
231
+ return fmt . Errorf ( "failed to update CRD's: %v" , err )
150
232
}
151
- err = writeCRDsToDir (csvCfg .CRDCRPaths , filepath .Dir (input .Path ))
152
- if err != nil {
153
- return err
233
+ // TODO: This path should come from the CSV generator field csvOutputDir
234
+ bundleDir := filepath .Join (c .outputDir , gencatalog .OLMCatalogChildDir , c .operatorName , c .csvVersion )
235
+ for path , b := range crdManifestSet {
236
+ path = filepath .Join (bundleDir , path )
237
+ if err = ioutil .WriteFile (path , b , fileutil .DefaultFileMode ); err != nil {
238
+ return fmt .Errorf ("failed to update CRD's: %v" , err )
239
+ }
154
240
}
155
241
}
156
242
@@ -191,25 +277,45 @@ func validateVersion(version string) error {
191
277
return nil
192
278
}
193
279
194
- func writeCRDsToDir (crdPaths []string , toDir string ) error {
195
- for _ , p := range crdPaths {
196
- b , err := ioutil .ReadFile (p )
280
+ // findCRDFileSet searches files in the given directory path for CRD manifests,
281
+ // returning a map of paths to file contents.
282
+ func findCRDFileSet (crdDir string ) (map [string ][]byte , error ) {
283
+ crdFileSet := map [string ][]byte {}
284
+ info , err := os .Stat (crdDir )
285
+ if err != nil {
286
+ return nil , err
287
+ }
288
+ if ! info .IsDir () {
289
+ return nil , fmt .Errorf ("crd's must be read from a directory. %s is a file" , crdDir )
290
+ }
291
+ files , err := ioutil .ReadDir (crdDir )
292
+ if err != nil {
293
+ return nil , err
294
+ }
295
+
296
+ wd := projutil .MustGetwd ()
297
+ for _ , f := range files {
298
+ if f .IsDir () {
299
+ continue
300
+ }
301
+
302
+ crdPath := filepath .Join (wd , crdDir , f .Name ())
303
+ b , err := ioutil .ReadFile (crdPath )
197
304
if err != nil {
198
- return err
305
+ return nil , fmt . Errorf ( "error reading manifest %s: %v" , crdPath , err )
199
306
}
307
+ // Skip files in crdsDir that aren't k8s manifests since we do not know
308
+ // what other files are in crdsDir.
200
309
typeMeta , err := k8sutil .GetTypeMetaFromBytes (b )
201
310
if err != nil {
202
- return fmt .Errorf ("error in %s : %v" , p , err )
311
+ log .Debugf ("Skipping non-manifest file %s: %v" , crdPath , err )
312
+ continue
203
313
}
204
314
if typeMeta .Kind != "CustomResourceDefinition" {
315
+ log .Debugf ("Skipping non CRD manifest %s" , crdPath )
205
316
continue
206
317
}
207
-
208
- path := filepath .Join (toDir , filepath .Base (p ))
209
- err = ioutil .WriteFile (path , b , fileutil .DefaultFileMode )
210
- if err != nil {
211
- return err
212
- }
318
+ crdFileSet [filepath .Base (crdPath )] = b
213
319
}
214
- return nil
320
+ return crdFileSet , nil
215
321
}
0 commit comments