Skip to content

Commit 689ca61

Browse files
committed
feat: split name into bundle and csv names to avoid confusion
Fixes #738 Signed-off-by: Chris Laprun <[email protected]>
1 parent 7cddc15 commit 689ca61

File tree

7 files changed

+80
-37
lines changed

7 files changed

+80
-37
lines changed

annotations/src/main/java/io/quarkiverse/operatorsdk/annotations/CSVMetadata.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,29 @@
2121
* gradle) name. This name can be used to assign reconcilers to the same bundle by creating a {@link SharedCSVMetadata}
2222
* implementation bearing a {@link CSVMetadata} annotation specifying the CSV metadata to be shared among reconcilers
2323
* assigned to that named bundle.
24+
*
25+
* @deprecated Use {@link #bundleName()} and {@link #csvName()} instead as previously this method was being used for both
26+
* values resulting in confusion or even problems setting the correct CSV name as recommended by OLM. See
27+
* <a href='https://github.com/quarkiverse/quarkus-operator-sdk/issues/738'>this issue</a> for a more detailed
28+
* discussion.
2429
*/
30+
@Deprecated
2531
String name() default "";
2632

33+
/**
34+
* The name which should be used for the generated bundle. If not provided, the name is derived from the project's (maven or
35+
* gradle) name. This name can be used to assign reconcilers to the same bundle by creating a {@link SharedCSVMetadata}
36+
* implementation bearing a {@link CSVMetadata} annotation specifying the CSV metadata to be shared among reconcilers
37+
* assigned to that named bundle.
38+
*/
39+
String bundleName() default "";
40+
41+
/**
42+
* The name used in the CSV metadata stanza. If not provided, this will default to {@code <bundle name>.v<version>}
43+
* as recommended by OLM.
44+
*/
45+
String csvName() default "";
46+
2747
/**
2848
* Extra annotations that should be added to the CSV metadata.
2949
*/

bundle-generator/deployment/src/main/java/io/quarkiverse/operatorsdk/bundle/deployment/BundleGenerator.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,12 @@ public static List<ManifestsBuilder> prepareGeneration(BundleGenerationConfigura
6666
var missing = addCRDManifestBuilder(crds, builders, csvMetadata, csvBuilder.getOwnedCRs());
6767
if (!missing.isEmpty()) {
6868
throw new IllegalStateException(
69-
"Missing owned CRD data for resources: " + missing + " for bundle: " + csvMetadata.name);
69+
"Missing owned CRD data for resources: " + missing + " for bundle: " + csvMetadata.bundleName);
7070
}
7171
// output required CRDs in the manifest, output a warning in case we're missing some
7272
missing = addCRDManifestBuilder(crds, builders, csvMetadata, csvBuilder.getRequiredCRs());
7373
if (!missing.isEmpty()) {
74-
log.warnv("Missing required CRD data for resources: {0} for bundle: {1}", missing, csvMetadata.name);
74+
log.warnv("Missing required CRD data for resources: {0} for bundle: {1}", missing, csvMetadata.bundleName);
7575
}
7676
}
7777

@@ -93,7 +93,7 @@ private static HashSet<String> addCRDManifestBuilder(Map<String, CRDInfo> crds,
9393

9494
private static SortedMap<String, String> generateBundleLabels(CSVMetadataHolder csvMetadata,
9595
BundleGenerationConfiguration bundleConfiguration, Version version) {
96-
var packageName = bundleConfiguration.packageName.orElse(csvMetadata.name);
96+
var packageName = bundleConfiguration.packageName.orElse(csvMetadata.bundleName);
9797

9898
SortedMap<String, String> values = new TreeMap<>();
9999
values.put(join(BUNDLE_PREFIX, CHANNEL, DEFAULT, ANNOTATIONS_VERSION),

bundle-generator/deployment/src/main/java/io/quarkiverse/operatorsdk/bundle/deployment/BundleProcessor.java

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -98,31 +98,31 @@ CSVMetadataBuildItem gatherCSVMetadata(KubernetesConfig kubernetesConfig,
9898
// Check whether the reconciler must be shipped using a custom bundle
9999
final var csvMetadataAnnotation = reconcilerInfo.classInfo()
100100
.declaredAnnotation(CSV_METADATA);
101-
final var maybeCSVMetadataName = getCSVMetadataName(csvMetadataAnnotation);
102-
final var csvMetadataName = maybeCSVMetadataName.orElse(defaultName);
101+
final var sharedMetadataName = getBundleName(csvMetadataAnnotation, defaultName);
102+
final var isNameInferred = defaultName.equals(sharedMetadataName);
103103

104-
var csvMetadata = sharedMetadataHolders.get(csvMetadataName);
104+
var csvMetadata = sharedMetadataHolders.get(sharedMetadataName);
105105
if (csvMetadata == null) {
106106
final var origin = reconcilerInfo.classInfo().name().toString();
107107

108-
if (!csvMetadataName.equals(defaultName)) {
108+
if (!sharedMetadataName.equals(defaultName)) {
109109
final var maybeExistingOrigin = csvGroups.keySet().stream()
110-
.filter(mh -> mh.name.equals(csvMetadataName))
110+
.filter(mh -> mh.bundleName.equals(sharedMetadataName))
111111
.map(CSVMetadataHolder::getOrigin)
112112
.findFirst();
113113
if (maybeExistingOrigin.isPresent()) {
114114
throw new IllegalStateException("Reconcilers '" + maybeExistingOrigin.get()
115115
+ "' and '" + origin
116-
+ "' are using the same bundle name '" + csvMetadataName
116+
+ "' are using the same bundle name '" + sharedMetadataName
117117
+ "' but no SharedCSVMetadata implementation with that name exists. Please create a SharedCSVMetadata with that name to have one single source of truth and reference it via CSVMetadata annotations using that name on your reconcilers.");
118118
}
119119
}
120120
csvMetadata = createMetadataHolder(csvMetadataAnnotation,
121-
new CSVMetadataHolder(csvMetadataName, defaultVersion, defaultReplaces, vcsUrl, origin));
121+
new CSVMetadataHolder(sharedMetadataName, defaultVersion, defaultReplaces, vcsUrl, origin));
122122
}
123123
log.infov("Assigning ''{0}'' reconciler to {1}",
124124
reconcilerInfo.nameOrFailIfUnset(),
125-
getMetadataOriginInformation(csvMetadataAnnotation, maybeCSVMetadataName, csvMetadata));
125+
getMetadataOriginInformation(csvMetadataAnnotation, isNameInferred, csvMetadata));
126126

127127
csvGroups.computeIfAbsent(csvMetadata, m -> new ArrayList<>()).add(
128128
augmentReconcilerInfo(reconcilerInfo));
@@ -192,14 +192,14 @@ private static void augmentResourceInfoIfCR(ReconciledAugmentedClassInfo<?> reco
192192
}
193193
}
194194

195-
private String getMetadataOriginInformation(AnnotationInstance csvMetadataAnnotation, Optional<String> csvMetadataName,
195+
private String getMetadataOriginInformation(AnnotationInstance csvMetadataAnnotation, boolean isNameInferred,
196196
CSVMetadataHolder metadataHolder) {
197197
final var isDefault = csvMetadataAnnotation == null;
198-
final var actualName = metadataHolder.name;
198+
final var actualName = metadataHolder.bundleName;
199199
if (isDefault) {
200200
return "default bundle automatically named '" + actualName + "'";
201201
} else {
202-
return "bundle " + (csvMetadataName.isEmpty() ? "automatically " : "") + "named '"
202+
return "bundle " + (isNameInferred ? "automatically " : "") + "named '"
203203
+ actualName + "' defined by '" + metadataHolder.getOrigin() + "'";
204204
}
205205
}
@@ -295,22 +295,31 @@ private Map<String, CSVMetadataHolder> getSharedMetadataHolders(String name, Str
295295
if (csvMetadataAnn != null) {
296296
final var origin = sharedMetadataImpl.name().toString();
297297
final var metadataHolder = createMetadataHolder(csvMetadataAnn, csvMetadata, origin);
298-
final var existing = result.get(metadataHolder.name);
298+
final var existing = result.get(metadataHolder.bundleName);
299299
if (existing != null) {
300300
throw new IllegalStateException(
301-
"Only one SharedCSVMetadata named " + metadataHolder.name
301+
"Only one SharedCSVMetadata named " + metadataHolder.bundleName
302302
+ " can be defined. Was defined on (at least): " + existing.getOrigin() + " and " + origin);
303303
}
304-
result.put(metadataHolder.name, metadataHolder);
304+
result.put(metadataHolder.bundleName, metadataHolder);
305305
}
306306
});
307307
return result;
308308
}
309309

310-
private Optional<String> getCSVMetadataName(AnnotationInstance csvMetadataAnnotation) {
311-
return Optional.ofNullable(csvMetadataAnnotation)
312-
.map(annotation -> annotation.value("name"))
313-
.map(AnnotationValue::asString);
310+
private static String getBundleName(AnnotationInstance csvMetadata, String defaultName) {
311+
if (csvMetadata == null) {
312+
return defaultName;
313+
} else {
314+
final var bundleName = csvMetadata.value("bundleName");
315+
if (bundleName != null) {
316+
return bundleName.asString();
317+
} else {
318+
return Optional.ofNullable(csvMetadata.value("name"))
319+
.map(AnnotationValue::asString)
320+
.orElse(defaultName);
321+
}
322+
}
314323
}
315324

316325
private CSVMetadataHolder createMetadataHolder(AnnotationInstance csvMetadata,
@@ -325,8 +334,8 @@ private CSVMetadataHolder createMetadataHolder(AnnotationInstance csvMetadata, C
325334
}
326335

327336
final var providerField = csvMetadata.value("provider");
328-
String providerName = null;
329-
String providerURL = null;
337+
String providerName = mh.providerName;
338+
String providerURL = mh.providerURL;
330339
if (providerField != null) {
331340
final var provider = providerField.asNested();
332341
providerName = ConfigurationUtils.annotationValueOrDefault(provider, "name",
@@ -472,8 +481,9 @@ private CSVMetadataHolder createMetadataHolder(AnnotationInstance csvMetadata, C
472481
}
473482

474483
return new CSVMetadataHolder(
475-
ConfigurationUtils.annotationValueOrDefault(csvMetadata, "name",
476-
AnnotationValue::asString, () -> mh.name),
484+
getBundleName(csvMetadata, mh.bundleName),
485+
ConfigurationUtils.annotationValueOrDefault(csvMetadata, "csvName",
486+
AnnotationValue::asString, () -> mh.csvName),
477487
ConfigurationUtils.annotationValueOrDefault(csvMetadata, "description",
478488
AnnotationValue::asString, () -> mh.description),
479489
ConfigurationUtils.annotationValueOrDefault(csvMetadata, "displayName",

bundle-generator/deployment/src/main/java/io/quarkiverse/operatorsdk/bundle/deployment/builders/CsvManifestsBuilder.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public CsvManifestsBuilder(CSVMetadataHolder metadata, BuildTimeOperatorConfigur
5454

5555
csvBuilder = new ClusterServiceVersionBuilder();
5656

57-
final var metadataBuilder = csvBuilder.withNewMetadata().withName(getName());
57+
final var metadataBuilder = csvBuilder.withNewMetadata().withName(metadata.csvName);
5858
if (metadata.annotations != null) {
5959
metadataBuilder.addToAnnotations("olm.skipRange", metadata.annotations.skipRange);
6060
metadataBuilder.addToAnnotations("containerImage", metadata.annotations.containerImage);
@@ -72,7 +72,7 @@ public CsvManifestsBuilder(CSVMetadataHolder metadata, BuildTimeOperatorConfigur
7272
final var csvSpecBuilder = csvBuilder
7373
.editOrNewSpec()
7474
.withDescription(metadata.description)
75-
.withDisplayName(defaultIfEmpty(metadata.displayName, getName()))
75+
.withDisplayName(defaultIfEmpty(metadata.displayName, metadata.csvName))
7676
.withKeywords(metadata.keywords)
7777
.withReplaces(metadata.replaces)
7878
.withVersion(metadata.version)

bundle-generator/deployment/src/main/java/io/quarkiverse/operatorsdk/bundle/deployment/builders/ManifestsBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public abstract byte[] getManifestData(List<ServiceAccount> serviceAccounts, Lis
4545
public abstract String getManifestType();
4646

4747
public String getName() {
48-
return metadata.name;
48+
return metadata.bundleName;
4949
}
5050

5151
@Override

bundle-generator/runtime/src/main/java/io/quarkiverse/operatorsdk/bundle/runtime/BundleGenerationConfiguration.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.util.List;
44
import java.util.Optional;
55

6+
import io.quarkiverse.operatorsdk.annotations.CSVMetadata;
67
import io.quarkus.runtime.annotations.ConfigItem;
78
import io.quarkus.runtime.annotations.ConfigRoot;
89

@@ -28,7 +29,10 @@ public class BundleGenerationConfiguration {
2829

2930
/**
3031
* The name of the package that bundle belongs to.
32+
*
33+
* @deprecated Use {@link CSVMetadata#bundleName()} instead
3134
*/
35+
@Deprecated(forRemoval = true)
3236
@ConfigItem
3337
public Optional<String> packageName;
3438

bundle-generator/runtime/src/main/java/io/quarkiverse/operatorsdk/bundle/runtime/CSVMetadataHolder.java

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
public class CSVMetadataHolder {
1010
private static final Logger log = Logger.getLogger(CSVMetadataHolder.class.getName());
11-
public final String name;
11+
public final String bundleName;
12+
public final String csvName;
1213
private final String origin;
1314
public final String description;
1415
public final String displayName;
@@ -120,27 +121,31 @@ public RequiredCRD(String kind, String name, String version) {
120121

121122
}
122123

123-
public CSVMetadataHolder(String name, String version, String replaces, String providerURL, String origin) {
124-
this(name, null, null, null, null, null, providerURL, replaces, null, version, null, null, null, null, null, null, null,
124+
public CSVMetadataHolder(String bundleName, String version, String replaces, String providerURL, String origin) {
125+
this(bundleName, null, null, null, null, null, null, providerURL, replaces, null, version, null, null, null, null, null,
126+
null, null,
125127
null,
126128
origin);
127129
}
128130

129-
public CSVMetadataHolder(String name, String description, String displayName, Annotations annotations, String[] keywords,
131+
public CSVMetadataHolder(String bundleName, String csvName, String description, String displayName, Annotations annotations,
132+
String[] keywords,
130133
String providerName,
131134
String providerURL, String replaces, String[] skips, String version, String maturity,
132135
String minKubeVersion,
133136
Maintainer[] maintainers, Link[] links, Icon[] icon,
134137
InstallMode[] installModes, PermissionRule[] permissionRules, RequiredCRD[] requiredCRDs, String origin) {
135-
this.name = name;
138+
this.bundleName = bundleName;
139+
assert version != null;
140+
this.version = version;
141+
this.csvName = csvName == null ? bundleName + ".v" + version : csvName;
136142
this.description = description;
137143
this.displayName = displayName;
138144
this.annotations = annotations;
139145
this.keywords = keywords;
140146
this.providerURL = providerURL;
141147
this.replaces = replaces;
142148
this.skips = skips;
143-
this.version = version;
144149
this.maturity = maturity;
145150
this.minKubeVersion = minKubeVersion;
146151
this.maintainers = maintainers;
@@ -159,24 +164,28 @@ public CSVMetadataHolder(String name, String description, String displayName, An
159164
providerName = userName;
160165
msg = ". Using user name " + userName + " as default.";
161166
}
162-
log.warnv("It is recommended that you provide a provider name provided for {0}{1}", name, msg);
167+
log.warnv("It is recommended that you provide a provider name provided for {0}{1}", bundleName, msg);
163168
}
164169
this.providerName = providerName;
165170
}
166171

172+
/**
173+
* CSVMetadataHolders are stored as key in Maps and identified by their associated bundle name, so that's what we use for
174+
* equals and {@link #hashCode()}
175+
*/
167176
@Override
168177
public boolean equals(Object o) {
169178
if (this == o)
170179
return true;
171180
if (o == null || getClass() != o.getClass())
172181
return false;
173182
CSVMetadataHolder that = (CSVMetadataHolder) o;
174-
return Objects.equals(name, that.name);
183+
return Objects.equals(bundleName, that.bundleName);
175184
}
176185

177186
@Override
178187
public int hashCode() {
179-
return Objects.hash(name);
188+
return Objects.hash(bundleName);
180189
}
181190

182191
public String getOrigin() {

0 commit comments

Comments
 (0)