Skip to content

Commit e2068e0

Browse files
Merge pull request #451 from dinhxuanvu/default-chan
Bug 1878213: Update index add func to handle optional default channel
2 parents 83d95a8 + 4d61b1a commit e2068e0

File tree

6 files changed

+59
-45
lines changed

6 files changed

+59
-45
lines changed

docs/design/operator-bundle.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ We use the following labels to annotate the operator bundle image.
4545
* The value `metadata.v1` implies that this bundle has operator metadata.
4646
* The label `operators.operatorframework.io.bundle.package.v1` reflects the package name of the bundle.
4747
* The label `operators.operatorframework.io.bundle.channels.v1` reflects the list of channels the bundle is subscribing to when added into an operator registry
48-
* The label `operators.operatorframework.io.bundle.channel.default.v1` reflects the default channel an operator should be subscribed to when installed from a registry
48+
* The label `operators.operatorframework.io.bundle.channel.default.v1` reflects the default channel an operator should be subscribed to when installed from a registry. This label is optional if the default channel has been set by previous bundles and the default channel is unchanged for this bundle.
4949

5050
The labels will also be put inside a YAML file, as shown below.
5151

@@ -240,7 +240,7 @@ $ ./opm alpha bundle build --directory /test/0.1.0/ --tag quay.io/coreos/test-op
240240
--image-builder podman --package test-operator --channels stable,beta --default stable
241241
```
242242

243-
The `--package` or `-p` is the name of package for the operator such as `etcd` which maps `channels` to a particular application definition. `channels` allow package authors to write different upgrade paths for different users (e.g. `beta` vs. `stable`). The `channels` list is provided via `--channels` or `-c` flag. Multiple `channels` are separated by a comma (`,`). The default channel is provided optionally via `--default` or `-e` flag. If the default channel is not provided, the first channel in channel list is selected as default.
243+
The `--package` or `-p` is the name of package for the operator such as `etcd` which maps `channels` to a particular application definition. `channels` allow package authors to write different upgrade paths for different users (e.g. `beta` vs. `stable`). The `channels` list is provided via `--channels` or `-c` flag. Multiple `channels` are separated by a comma (`,`). The default channel is provided optionally via `--default` or `-e` flag.
244244

245245
*Notes:*
246246
* If there is `Dockerfile` existing in the directory, it will be overwritten.

pkg/lib/bundle/generate.go

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,6 @@ func GenerateFunc(directory, outputDir, packageName, channels, channelDefault st
112112

113113
if channelDefault == "" {
114114
channelDefault = i.GetDefaultChannel()
115-
if !containsString(strings.Split(channels, ","), channelDefault) {
116-
channelDefault = ""
117-
}
118115
log.Infof("Inferred default channel: %s", channelDefault)
119116
}
120117
}
@@ -299,16 +296,18 @@ func ValidateAnnotations(existing, expected []byte) error {
299296
func GenerateAnnotations(mediaType, manifests, metadata, packageName, channels, channelDefault string) ([]byte, error) {
300297
annotations := &AnnotationMetadata{
301298
Annotations: map[string]string{
302-
MediatypeLabel: mediaType,
303-
ManifestsLabel: manifests,
304-
MetadataLabel: metadata,
305-
PackageLabel: packageName,
306-
ChannelsLabel: channels,
307-
ChannelDefaultLabel: channelDefault,
299+
MediatypeLabel: mediaType,
300+
ManifestsLabel: manifests,
301+
MetadataLabel: metadata,
302+
PackageLabel: packageName,
303+
ChannelsLabel: channels,
308304
},
309305
}
310306

311-
annotations.Annotations[ChannelDefaultLabel] = channelDefault
307+
// Only add defaultChannel annotation if present
308+
if channelDefault != "" {
309+
annotations.Annotations[ChannelDefaultLabel] = channelDefault
310+
}
312311

313312
afile, err := yaml.Marshal(annotations)
314313
if err != nil {
@@ -343,7 +342,11 @@ func GenerateDockerfile(mediaType, manifests, metadata, copyManifestDir, copyMet
343342
fileContent += fmt.Sprintf("LABEL %s=%s\n", MetadataLabel, metadata)
344343
fileContent += fmt.Sprintf("LABEL %s=%s\n", PackageLabel, packageName)
345344
fileContent += fmt.Sprintf("LABEL %s=%s\n", ChannelsLabel, channels)
346-
fileContent += fmt.Sprintf("LABEL %s=%s\n\n", ChannelDefaultLabel, channelDefault)
345+
346+
// Only add defaultChannel annotation if present
347+
if channelDefault != "" {
348+
fileContent += fmt.Sprintf("LABEL %s=%s\n\n", ChannelDefaultLabel, channelDefault)
349+
}
347350

348351
// CONTENT
349352
fileContent += fmt.Sprintf("COPY %s %s\n", relativeManifestDirectory, "/manifests/")
@@ -352,7 +355,7 @@ func GenerateDockerfile(mediaType, manifests, metadata, copyManifestDir, copyMet
352355
return []byte(fileContent), nil
353356
}
354357

355-
// Write `fileName` file with `content` into a `directory`
358+
// WriteFile writes `fileName` file with `content` into a `directory`
356359
// Note: Will overwrite the existing `fileName` file if it exists
357360
func WriteFile(fileName, directory string, content []byte) error {
358361
if _, err := os.Stat(directory); os.IsNotExist(err) {

pkg/lib/bundle/generate_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,6 @@ func TestGenerateDockerfileFunc(t *testing.T) {
170170
"LABEL operators.operatorframework.io.bundle.metadata.v1=%s\n"+
171171
"LABEL operators.operatorframework.io.bundle.package.v1=test4\n"+
172172
"LABEL operators.operatorframework.io.bundle.channels.v1=test5\n"+
173-
"LABEL operators.operatorframework.io.bundle.channel.default.v1=\n\n"+
174173
"COPY test2 /manifests/\n"+
175174
"COPY metadata /metadata/\n", MetadataDir)
176175

@@ -255,7 +254,7 @@ func TestGenerateFunc(t *testing.T) {
255254
os.Remove(filepath.Join("./", DockerFile))
256255

257256
output := fmt.Sprintf("annotations:\n" +
258-
" operators.operatorframework.io.bundle.channel.default.v1: \"\"\n" +
257+
" operators.operatorframework.io.bundle.channel.default.v1: alpha\n" +
259258
" operators.operatorframework.io.bundle.channels.v1: beta\n" +
260259
" operators.operatorframework.io.bundle.manifests.v1: manifests/\n" +
261260
" operators.operatorframework.io.bundle.mediatype.v1: registry+v1\n" +

pkg/lib/bundle/validate.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ func validateAnnotations(mediaType string, fileAnnotations *AnnotationMetadata)
180180

181181
for label, item := range annotations {
182182
val, ok := fileAnnotations.Annotations[label]
183-
if !ok {
183+
if !ok && label != ChannelDefaultLabel {
184184
aErr := fmt.Errorf("Missing annotation %q", label)
185185
validationErrors = append(validationErrors, aErr)
186186
}
@@ -205,11 +205,12 @@ func validateAnnotations(mediaType string, fileAnnotations *AnnotationMetadata)
205205
if val == "" {
206206
aErr := fmt.Errorf("Expecting annotation %q to have non-empty value", label)
207207
validationErrors = append(validationErrors, aErr)
208-
} else {
209-
annotations[label] = val
210208
}
211209
case ChannelDefaultLabel:
212-
annotations[label] = val
210+
if val == "" {
211+
aErr := fmt.Errorf("Expecting annotation %q to have non-empty value", label)
212+
validationErrors = append(validationErrors, aErr)
213+
}
213214
}
214215
}
215216

pkg/registry/populator.go

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -223,22 +223,12 @@ func (i *DirectoryPopulator) loadManifests(imagesToAdd []*ImageInput, imagesToRe
223223
}
224224

225225
func (i *DirectoryPopulator) loadManifestsReplaces(bundle *Bundle, annotationsFile *AnnotationsFile) error {
226-
channels, err := i.querier.ListChannels(context.TODO(), annotationsFile.GetName())
227-
existingPackageChannels := map[string]string{}
228-
for _, c := range channels {
229-
current, err := i.querier.GetCurrentCSVNameForChannel(context.TODO(), annotationsFile.GetName(), c)
230-
if err != nil {
231-
return err
232-
}
233-
existingPackageChannels[c] = current
234-
}
235-
236226
bcsv, err := bundle.ClusterServiceVersion()
237227
if err != nil {
238228
return fmt.Errorf("error getting csv from bundle %s: %s", bundle.Name, err)
239229
}
240230

241-
packageManifest, err := translateAnnotationsIntoPackage(annotationsFile, bcsv, existingPackageChannels)
231+
packageManifest, err := i.translateAnnotationsIntoPackage(annotationsFile, bcsv)
242232
if err != nil {
243233
return fmt.Errorf("Could not translate annotations file into packageManifest %s", err)
244234
}
@@ -430,15 +420,23 @@ func (i *DirectoryPopulator) loadOperatorBundle(manifest PackageManifest, bundle
430420
}
431421

432422
// translateAnnotationsIntoPackage attempts to translate the channels.yaml file at the given path into a package.yaml
433-
func translateAnnotationsIntoPackage(annotations *AnnotationsFile, csv *ClusterServiceVersion, existingPackageChannels map[string]string) (PackageManifest, error) {
423+
func (i *DirectoryPopulator) translateAnnotationsIntoPackage(annotations *AnnotationsFile, csv *ClusterServiceVersion) (PackageManifest, error) {
434424
manifest := PackageManifest{}
425+
existingChannels := map[string]string{}
426+
427+
pkgm, err := i.querier.GetPackage(context.TODO(), annotations.GetName())
428+
if err == nil {
429+
for _, c := range pkgm.Channels {
430+
existingChannels[c.Name] = c.CurrentCSVName
431+
}
432+
}
435433

436434
for _, ch := range annotations.GetChannels() {
437-
existingPackageChannels[ch] = csv.GetName()
435+
existingChannels[ch] = csv.GetName()
438436
}
439437

440438
channels := []PackageChannel{}
441-
for c, current := range existingPackageChannels {
439+
for c, current := range existingChannels {
442440
channels = append(channels,
443441
PackageChannel{
444442
Name: c,
@@ -447,9 +445,29 @@ func translateAnnotationsIntoPackage(annotations *AnnotationsFile, csv *ClusterS
447445
}
448446

449447
manifest = PackageManifest{
450-
PackageName: annotations.GetName(),
451-
DefaultChannelName: annotations.GetDefaultChannelName(),
452-
Channels: channels,
448+
PackageName: annotations.GetName(),
449+
Channels: channels,
450+
}
451+
452+
defaultChan := annotations.GetDefaultChannelName()
453+
if defaultChan != "" {
454+
if _, found := existingChannels[defaultChan]; found {
455+
manifest.DefaultChannelName = annotations.GetDefaultChannelName()
456+
} else {
457+
return manifest, fmt.Errorf("Channel %s is set as default in annotations but not found in existing package channels", defaultChan)
458+
}
459+
} else {
460+
// No default channel is provided in annotations. Attempt to infer from package manifest
461+
if pkgm != nil {
462+
manifest.DefaultChannelName = pkgm.GetDefaultChannel()
463+
} else {
464+
// Infer default channel if only one channel is provided
465+
if len(annotations.GetChannels()) == 1 {
466+
manifest.DefaultChannelName = annotations.GetChannels()[0]
467+
} else {
468+
return manifest, fmt.Errorf("Default channel is missing and can't be inferred")
469+
}
470+
}
453471
}
454472

455473
return manifest, nil

pkg/registry/types.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -342,12 +342,5 @@ func (a *AnnotationsFile) GetChannels() []string {
342342

343343
// GetDefaultChannelName returns the name of the default channel
344344
func (a *AnnotationsFile) GetDefaultChannelName() string {
345-
if a.Annotations.DefaultChannelName != "" {
346-
return a.Annotations.DefaultChannelName
347-
}
348-
channels := a.GetChannels()
349-
if len(channels) == 1 {
350-
return channels[0]
351-
}
352-
return ""
345+
return a.Annotations.DefaultChannelName
353346
}

0 commit comments

Comments
 (0)