io.quarkiverse.operatorsdk.common.ConfigurationUtils Maven / Gradle / Ivy
The newest version!
package io.quarkiverse.operatorsdk.common;
import static io.quarkiverse.operatorsdk.common.Constants.CONTROLLER_CONFIGURATION;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Supplier;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationValue;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.IndexView;
import io.javaoperatorsdk.operator.ReconcilerUtils;
import io.javaoperatorsdk.operator.api.config.Utils;
import io.quarkus.bootstrap.app.ClassChangeInformation;
import io.quarkus.deployment.builditem.LiveReloadBuildItem;
import io.smallrye.config.common.utils.StringUtil;
public class ConfigurationUtils {
private ConfigurationUtils() {
}
/**
* Extracts the appropriate configuration value for the controller checking first any annotation
* configuration, then potentially overriding it by a properties-provided value or returning a
* default value if neither is provided.
*
* @param the expected type of the configuration value we're trying to extract
* @param the type of the external configuration values can be overridden from
* @param annotation the annotation from which a field is to be extracted
* @param extractor a Function extracting the optional value we're interested in from the
* external configuration
* @param annotationField the name of the field we want to retrieve from the specified annotation
* if present
* @param converter a Function converting the annotation value to the type we're expecting
* @param defaultValue a Supplier that computes/retrieve a default value when needed
* @return the extracted configuration value
*/
public static T extract(
C externalConfig,
AnnotationInstance annotation,
Function> extractor,
String annotationField,
Function converter,
Supplier defaultValue) {
// first check if we have an external configuration
if (externalConfig != null) {
// extract value from config if present
return extractor
.apply(externalConfig)
// or get from the annotation or default
.orElse(
annotationValueOrDefault(annotation, annotationField, converter, defaultValue));
} else {
// get from annotation or default
return annotationValueOrDefault(annotation, annotationField, converter, defaultValue);
}
}
public static T annotationValueOrDefault(
AnnotationInstance annotation,
String annotationFieldName,
Function converter,
Supplier defaultValue) {
return annotation != null
?
// get converted annotation value of get default
Optional.ofNullable(annotation.value(annotationFieldName)).map(converter).orElseGet(defaultValue)
:
// get default
defaultValue.get();
}
@SuppressWarnings("unused")
public static ClassInfo getClassInfoForInstantiation(AnnotationValue toInstantiate,
Class interfaceClass,
IndexView index) {
final var expectedTypeDN = toInstantiate.asClass().name();
final var clazz = index.getClassByName(expectedTypeDN);
if (clazz == null) {
throw new IllegalStateException(expectedTypeDN
+ " class was not found in Jandex index. If you see this in a test, don't forget to add the class to the application root when setting up the test.");
}
return clazz;
}
@SuppressWarnings("unchecked")
public static T instantiateImplementationClass(
AnnotationInstance annotation,
String annotationFieldName,
Class interfaceClass,
Class extends T> defaultImplementation,
boolean returnNullIfDefault,
IndexView index) {
defaultImplementation = returnNullIfDefault ? null : defaultImplementation;
final var implementationClass = annotation != null
?
// get converted annotation value of get default
Optional.ofNullable(annotation.value(annotationFieldName))
.map(av -> {
final var expectedTypeInfo = getClassInfoForInstantiation(av,
interfaceClass,
index);
final var typeName = expectedTypeInfo.name().toString();
return ClassLoadingUtils.loadClass(typeName,
interfaceClass);
})
.orElse((Class) defaultImplementation)
:
// get default
defaultImplementation;
if (returnNullIfDefault && implementationClass == null) {
return null;
}
return ClassLoadingUtils.instantiate(implementationClass);
}
/**
* Checks whether CRD presence should be checked on the cluster and if custom resources should be (somewhat) validated.
* If the {@link Utils#CHECK_CRD_ENV_KEY} system property is set, this will be used, regardless of other configuration
* options.
*
* @param validate value from the build time configuration
* @return the value specified by {@link Utils#CHECK_CRD_ENV_KEY} if set, the value specified by the build time
* configuration property otherwise
*/
public static boolean shouldValidateCustomResources(boolean validate) {
if (Utils.isValidateCustomResourcesEnvVarSet()) {
return Utils.shouldCheckCRDAndValidateLocalModel();
}
return validate;
}
public static String getReconcilerName(ClassInfo info) {
final var controllerClassName = info.name().toString();
final var controllerAnnotation = info.declaredAnnotation(CONTROLLER_CONFIGURATION);
return getReconcilerName(controllerClassName, controllerAnnotation);
}
public static String getReconcilerName(String reconcilerClassName, AnnotationInstance configuration) {
final var defaultControllerName = ReconcilerUtils.getDefaultReconcilerName(reconcilerClassName);
return ConfigurationUtils.annotationValueOrDefault(
configuration, "name", AnnotationValue::asString, () -> defaultControllerName);
}
public static Set getChangedClasses(LiveReloadBuildItem liveReload) {
return liveReload.isLiveReload() ? Optional.ofNullable(liveReload.getChangeInformation())
.map(ClassChangeInformation::getChangedClasses)
.orElse(Collections.emptySet()) : Collections.emptySet();
}
public static String getNamespacesPropertyName(String reconcilerName, boolean asEnvVar) {
final var propName = "quarkus.operator-sdk.controllers." + reconcilerName + ".namespaces";
return asEnvVar ? StringUtil.replaceNonAlphanumericByUnderscores(propName.toUpperCase()) : propName;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy