Skip to content

Commit

Permalink
fix: add proper default install mode derived from watched namespaces
Browse files Browse the repository at this point in the history
Fixes #839

Signed-off-by: Chris Laprun <[email protected]>
  • Loading branch information
metacosm committed Mar 5, 2024
1 parent 5071d8a commit 35df666
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import io.quarkiverse.operatorsdk.common.ReconcilerAugmentedClassInfo;
import io.quarkiverse.operatorsdk.runtime.BuildTimeOperatorConfiguration;
import io.quarkiverse.operatorsdk.runtime.CRDInfo;
import io.quarkiverse.operatorsdk.runtime.QuarkusControllerConfiguration;
import io.quarkiverse.operatorsdk.runtime.Version;
import io.quarkus.container.util.PathsUtil;

Expand Down Expand Up @@ -46,18 +47,19 @@ public class BundleGenerator {
private BundleGenerator() {
}

@SuppressWarnings("rawtypes")
public static List<ManifestsBuilder> prepareGeneration(BundleGenerationConfiguration bundleConfiguration,
BuildTimeOperatorConfiguration operatorConfiguration, Version version,
Map<CSVMetadataHolder, List<ReconcilerAugmentedClassInfo>> csvGroups, Map<String, CRDInfo> crds,
Path outputDirectory, String deploymentName) {
Path outputDirectory, String deploymentName, Map<String, QuarkusControllerConfiguration> controllerConfigs) {
List<ManifestsBuilder> builders = new ArrayList<>();
for (Map.Entry<CSVMetadataHolder, List<ReconcilerAugmentedClassInfo>> entry : csvGroups.entrySet()) {
final var csvMetadata = entry.getKey();
final var labels = generateBundleLabels(csvMetadata, bundleConfiguration, version);

final var mainSourcesRoot = PathsUtil.findMainSourcesRoot(outputDirectory);
final var csvBuilder = new CsvManifestsBuilder(csvMetadata, operatorConfiguration, entry.getValue(),
mainSourcesRoot != null ? mainSourcesRoot.getKey() : null, deploymentName);
mainSourcesRoot != null ? mainSourcesRoot.getKey() : null, deploymentName, controllerConfigs);
builders.add(csvBuilder);
builders.add(new AnnotationsManifestsBuilder(csvMetadata, labels));
builders.add(new BundleDockerfileManifestsBuilder(csvMetadata, labels));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import io.quarkiverse.operatorsdk.bundle.runtime.BundleGenerationConfiguration;
import io.quarkiverse.operatorsdk.bundle.runtime.CSVMetadataHolder;
import io.quarkiverse.operatorsdk.common.*;
import io.quarkiverse.operatorsdk.deployment.ControllerConfigurationsBuildItem;
import io.quarkiverse.operatorsdk.deployment.GeneratedCRDInfoBuildItem;
import io.quarkiverse.operatorsdk.deployment.VersionBuildItem;
import io.quarkiverse.operatorsdk.runtime.BuildTimeOperatorConfiguration;
Expand Down Expand Up @@ -185,7 +186,8 @@ void generateBundle(ApplicationInfoBuildItem configuration,
BuildProducer<GeneratedBundleBuildItem> doneGeneratingCSV,
GeneratedCRDInfoBuildItem generatedCustomResourcesDefinitions,
DeserializedKubernetesResourcesBuildItem generatedKubernetesResources,
BuildProducer<GeneratedFileSystemResourceBuildItem> generatedCSVs) {
BuildProducer<GeneratedFileSystemResourceBuildItem> generatedCSVs,
ControllerConfigurationsBuildItem controllerConfigurationsBuildItem) {
final var crds = generatedCustomResourcesDefinitions.getCRDGenerationInfo().getCrds()
.values().stream()
.flatMap(entry -> entry.values().stream())
Expand Down Expand Up @@ -233,7 +235,8 @@ void generateBundle(ApplicationInfoBuildItem configuration,
final var deploymentName = ResourceNameUtil.getResourceName(kubernetesConfig, configuration);
final var generated = BundleGenerator.prepareGeneration(bundleConfiguration, operatorConfiguration,
versionBuildItem.getVersion(),
csvMetadata.getCsvGroups(), crds, outputTarget.getOutputDirectory(), deploymentName);
csvMetadata.getCsvGroups(), crds, outputTarget.getOutputDirectory(), deploymentName,
controllerConfigurationsBuildItem.getControllerConfigs());
generated.forEach(manifestBuilder -> {
final var fileName = manifestBuilder.getFileName();
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@
import io.quarkiverse.operatorsdk.bundle.runtime.CSVMetadataHolder.RequiredCRD;
import io.quarkiverse.operatorsdk.common.*;
import io.quarkiverse.operatorsdk.runtime.BuildTimeOperatorConfiguration;
import io.quarkiverse.operatorsdk.runtime.QuarkusControllerConfiguration;

public class CsvManifestsBuilder extends ManifestsBuilder {

private static final Logger log = Logger.getLogger(CsvManifestsBuilder.class);

private static final String DEFAULT_INSTALL_MODE = "AllNamespaces";
private static final String ALL_NAMESPACES = "AllNamespaces";
private static final String DEPLOYMENT = "deployment";
private static final String SERVICE_ACCOUNT_KIND = "ServiceAccount";
private static final String CLUSTER_ROLE_KIND = "ClusterRole";
Expand All @@ -37,24 +38,29 @@ public class CsvManifestsBuilder extends ManifestsBuilder {
private static final Logger LOGGER = Logger.getLogger(CsvManifestsBuilder.class.getName());
private static final String IMAGE_PNG = "image/png";
public static final String OLM_TARGET_NAMESPACES = "metadata.annotations['olm.targetNamespaces']";
public static final String OWN_NAMESPACE = "OwnNamespace";
public static final String SINGLE_NAMESPACE = "SingleNamespace";
public static final String MULTI_NAMESPACE = "MultiNamespace";
private ClusterServiceVersionBuilder csvBuilder;
private final Set<CRDDescription> ownedCRs = new HashSet<>();
private final Set<CRDDescription> requiredCRs = new HashSet<>();
private final Path kubernetesResources;
private final String deploymentName;
private final List<ReconcilerAugmentedClassInfo> controllers;

@SuppressWarnings("rawtypes")
public CsvManifestsBuilder(CSVMetadataHolder metadata, BuildTimeOperatorConfiguration operatorConfiguration,
List<ReconcilerAugmentedClassInfo> controllers,
Path mainSourcesRoot, String deploymentName) {
Path mainSourcesRoot, String deploymentName, Map<String, QuarkusControllerConfiguration> controllerConfigs) {
super(metadata);
this.deploymentName = deploymentName;
this.controllers = controllers;
this.kubernetesResources = mainSourcesRoot != null ? mainSourcesRoot.resolve("kubernetes") : null;

csvBuilder = new ClusterServiceVersionBuilder();

final var metadataBuilder = csvBuilder.withNewMetadata().withName(getName());
final var name = getName();
final var metadataBuilder = csvBuilder.withNewMetadata().withName(name);
if (metadata.annotations != null) {
metadataBuilder.addToAnnotations("olm.skipRange", metadata.annotations.skipRange);
metadataBuilder.addToAnnotations("containerImage", metadata.annotations.containerImage);
Expand All @@ -72,7 +78,7 @@ public CsvManifestsBuilder(CSVMetadataHolder metadata, BuildTimeOperatorConfigur
final var csvSpecBuilder = csvBuilder
.editOrNewSpec()
.withDescription(metadata.description)
.withDisplayName(defaultIfEmpty(metadata.displayName, getName()))
.withDisplayName(defaultIfEmpty(metadata.displayName, name))
.withKeywords(metadata.keywords)
.withReplaces(metadata.replaces)
.withVersion(metadata.version)
Expand Down Expand Up @@ -135,14 +141,6 @@ public CsvManifestsBuilder(CSVMetadataHolder metadata, BuildTimeOperatorConfigur
}
}

if (metadata.installModes == null || metadata.installModes.length == 0) {
csvSpecBuilder.addNewInstallMode(true, DEFAULT_INSTALL_MODE);
} else {
for (CSVMetadataHolder.InstallMode installMode : metadata.installModes) {
csvSpecBuilder.addNewInstallMode(installMode.supported, installMode.type);
}
}

// add owned and required CRD, also collect them
final var nativeApis = new ArrayList<GroupVersionKind>();
controllers.forEach(raci -> {
Expand Down Expand Up @@ -181,6 +179,29 @@ public CsvManifestsBuilder(CSVMetadataHolder metadata, BuildTimeOperatorConfigur
}
});
}

// deal with install modes
// use watched namespaces information for default install mode
// fixme: multiple, incompatible controller configurations in the same bundle will result in inconsistent runs
final var config = controllerConfigs.get(raci.nameOrFailIfUnset());
if (config.watchAllNamespaces()) {
csvSpecBuilder.withInstallModes(new InstallMode(true, ALL_NAMESPACES));
} else if (config.watchCurrentNamespace()) {
csvSpecBuilder.withInstallModes(new InstallMode(true, OWN_NAMESPACE));
} else {
final var namespaces = config.getNamespaces();
if (namespaces.size() == 1) {
csvSpecBuilder.withInstallModes(new InstallMode(true, SINGLE_NAMESPACE));
} else {
csvSpecBuilder.withInstallModes(new InstallMode(true, MULTI_NAMESPACE));
}
}
// then process metadata
if (metadata.installModes != null) {
for (CSVMetadataHolder.InstallMode installMode : metadata.installModes) {
csvSpecBuilder.addNewInstallMode(installMode.supported, installMode.type);
}
}
});

// add required CRDs from CSV metadata
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package io.quarkiverse.operatorsdk.bundle;

import static io.quarkiverse.operatorsdk.bundle.Utils.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.*;

import java.io.IOException;

Expand Down Expand Up @@ -49,6 +48,13 @@ public void shouldWriteBundleForTheOperators() throws IOException {
assertEquals(FirstReconciler.REPLACES, csv.getSpec().getReplaces());
var bundleMeta = getAnnotationsFor(bundle, "first-operator");
assertEquals(BUNDLE_PACKAGE, bundleMeta.getAnnotations().get("operators.operatorframework.io.bundle.package.v1"));
assertEquals(2, csv.getSpec().getInstallModes().size());
var installMode = csv.getSpec().getInstallModes().get(0);
assertEquals("AllNamespaces", installMode.getType());
assertTrue(installMode.getSupported());
installMode = csv.getSpec().getInstallModes().get(1);
assertEquals("MultiNamespace", installMode.getType());
assertFalse(installMode.getSupported());

checkBundleFor(bundle, "second-operator", Second.class);
csv = getCSVFor(bundle, "second-operator");
Expand All @@ -59,6 +65,10 @@ public void shouldWriteBundleForTheOperators() throws IOException {
.addToResources(SecondReconciler.RBAC_RULE_RES)
.addToVerbs(SecondReconciler.RBAC_RULE_VERBS)
.build()));
assertEquals(1, csv.getSpec().getInstallModes().size());
installMode = csv.getSpec().getInstallModes().get(0);
assertEquals("SingleNamespace", installMode.getType());
assertTrue(installMode.getSupported());

checkBundleFor(bundle, "third-operator", Third.class);
// also check that external CRD is present
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
import io.quarkiverse.operatorsdk.annotations.CSVMetadata;

@CSVMetadata(name = "first-operator", version = FirstReconciler.VERSION)
@CSVMetadata(name = "first-operator", version = FirstReconciler.VERSION, installModes = @CSVMetadata.InstallMode(type = "MultiNamespace", supported = false))
public class FirstReconciler implements Reconciler<First> {

public static final String VERSION = "first-version";
Expand Down

0 comments on commit 35df666

Please sign in to comment.