From cc394874133e7d1930949faac74561379cee276b Mon Sep 17 00:00:00 2001 From: Laird Nelson Date: Mon, 14 Aug 2023 12:33:39 -0700 Subject: [PATCH 1/6] 4.x/main: Adjusts CDI OciExtension to use runtime OciExtension for certain authentication tasks Signed-off-by: Laird Nelson --- integrations/oci/sdk/cdi/pom.xml | 4 + .../oci/sdk/cdi/AdpSelectionStrategy.java | 515 ------------------ .../oci/sdk/cdi/OciExtension.java | 241 ++++---- .../sdk/cdi/src/main/java/module-info.java | 3 +- 4 files changed, 121 insertions(+), 642 deletions(-) delete mode 100644 integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/AdpSelectionStrategy.java diff --git a/integrations/oci/sdk/cdi/pom.xml b/integrations/oci/sdk/cdi/pom.xml index a724f824f51..deb0c6c0adb 100644 --- a/integrations/oci/sdk/cdi/pom.xml +++ b/integrations/oci/sdk/cdi/pom.xml @@ -61,6 +61,10 @@ + + io.helidon.integrations.oci.sdk + helidon-integrations-oci-sdk-runtime + org.glassfish.jersey.connectors diff --git a/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/AdpSelectionStrategy.java b/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/AdpSelectionStrategy.java deleted file mode 100644 index 329de31120a..00000000000 --- a/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/AdpSelectionStrategy.java +++ /dev/null @@ -1,515 +0,0 @@ -/* - * Copyright (c) 2022, 2023 Oracle and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.helidon.integrations.oci.sdk.cdi; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.lang.annotation.Annotation; -import java.net.ConnectException; -import java.net.InetAddress; -import java.net.URI; -import java.net.UnknownHostException; -import java.nio.file.NoSuchFileException; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.EnumSet; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.function.Supplier; -import java.util.logging.Logger; - -import com.oracle.bmc.Region; -import com.oracle.bmc.auth.AbstractAuthenticationDetailsProvider; -import com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider; -import com.oracle.bmc.auth.InstancePrincipalsAuthenticationDetailsProvider; -import com.oracle.bmc.auth.InstancePrincipalsAuthenticationDetailsProvider.InstancePrincipalsAuthenticationDetailsProviderBuilder; -import com.oracle.bmc.auth.ResourcePrincipalAuthenticationDetailsProvider; -import com.oracle.bmc.auth.ResourcePrincipalAuthenticationDetailsProvider.ResourcePrincipalAuthenticationDetailsProviderBuilder; -import com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider; -import com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider.SimpleAuthenticationDetailsProviderBuilder; -import com.oracle.bmc.auth.SimplePrivateKeySupplier; -import com.oracle.bmc.auth.StringPrivateKeySupplier; - -import static com.oracle.bmc.auth.AbstractFederationClientAuthenticationDetailsProviderBuilder.METADATA_SERVICE_BASE_URL; - -/** - * A strategy for finding and building various well-known kinds of - * {@link AbstractAuthenticationDetailsProvider} instances. - */ -enum AdpSelectionStrategy { - - - // - // ------------ - // PLEASE READ: - // ------------ - // - // The ordering of the constants in this enum is *extremely* - // important! It governs the default "auto" case order - // (EnumSets always traverse their members in declaration - // order)! Do not reorder the constants unless you have a good - // reason! - // - - - /* - * Enum constants. - */ - - - /** - * An {@link AdpSelectionStrategy} that works with {@link - * SimpleAuthenticationDetailsProvider} instances configured from - * configuration. - */ - CONFIG(SimpleAuthenticationDetailsProvider.class, - SimpleAuthenticationDetailsProviderBuilder.class) { - - private static final String OCI_AUTH_FINGERPRINT = "oci.auth.fingerprint"; - - private static final String OCI_AUTH_PASSPHRASE = "oci.auth.passphrase"; - - private static final String OCI_AUTH_PRIVATE_KEY = "oci.auth.private-key"; - - private static final String OCI_AUTH_REGION = "oci.auth.region"; - - private static final String OCI_AUTH_TENANT_ID = "oci.auth.tenant-id"; - - private static final String OCI_AUTH_USER_ID = "oci.auth.user-id"; - - @Override // AdpSelectionStrategy - boolean isAvailable(Selector selector, Config c, Annotation[] qualifiersArray) { - // See - // https://docs.oracle.com/en-us/iaas/tools/java/latest/com/oracle/bmc/auth/SimpleAuthenticationDetailsProvider.SimpleAuthenticationDetailsProviderBuilder.html#method.summary - // - // Some fallback logic is for backwards compatibility with - // a prior OCI-related extension. - return - super.isAvailable(selector, c, qualifiersArray) - && c.get(OCI_AUTH_FINGERPRINT, String.class).isPresent() - && c.get(OCI_AUTH_REGION, String.class).isPresent() - && (c.get(OCI_AUTH_TENANT_ID, String.class).isPresent() || c.get("oci.auth.tenancy", String.class).isPresent()) - && (c.get(OCI_AUTH_USER_ID, String.class).isPresent() || c.get("oci.auth.user", String.class).isPresent()); - } - - @Override // AdpSelectionStrategy - @SuppressWarnings("checkstyle:LineLength") - SimpleAuthenticationDetailsProviderBuilder produceBuilder(Selector selector, Config c, Annotation[] qualifiersArray) { - SimpleAuthenticationDetailsProviderBuilder b = SimpleAuthenticationDetailsProvider.builder(); - // See - // https://docs.oracle.com/en-us/iaas/tools/java/latest/com/oracle/bmc/auth/SimpleAuthenticationDetailsProvider.SimpleAuthenticationDetailsProviderBuilder.html#method.summary - // - // See - // https://docs.oracle.com/en-us/iaas/Content/API/Concepts/apisigningkey.htm#apisigningkey_topic_How_to_Generate_an_API_Signing_Key_Mac_Linux__ol_t5v_lwz_zmb - // for default private key file naming rationale used in a - // fallback case below. - // - // Some fallback logic is for backwards compatibility with - // a prior OCI-related extension. - c.get(OCI_AUTH_FINGERPRINT, String.class) - .ifPresent(b::fingerprint); - c.get(OCI_AUTH_PASSPHRASE, String.class).or(() -> c.get(OCI_AUTH_PASSPHRASE + "Characters", String.class)) - .ifPresent(b::passPhrase); - c.get(OCI_AUTH_PRIVATE_KEY, String.class).or(() -> c.get("oci.auth.privateKey", String.class)) - .ifPresentOrElse(pk -> b.privateKeySupplier(new StringPrivateKeySupplier(pk)), - () -> b.privateKeySupplier(new SimplePrivateKeySupplier(c.get(OCI_AUTH_PRIVATE_KEY + "-path", String.class) - .orElse(c.get("oci.auth.keyFile", String.class) - .orElse(Paths.get(System.getProperty("user.home"), ".oci", "oci_api_key.pem").toString()))))); - c.get(OCI_AUTH_REGION, Region.class) - .ifPresent(b::region); - c.get(OCI_AUTH_TENANT_ID, String.class).or(() -> c.get("oci.auth.tenancy", String.class)) - .ifPresent(b::tenantId); - c.get(OCI_AUTH_USER_ID, String.class).or(() -> c.get("oci.auth.user", String.class)) - .ifPresent(b::userId); - return b; - } - - @Override // AdpSelectionStrategy - SimpleAuthenticationDetailsProvider produce(Selector selector, Config c, Annotation[] qualifiersArray) { - return selector.select(SimpleAuthenticationDetailsProviderBuilder.class, qualifiersArray).get().build(); - } - - }, - - /** - * An {@link AdpSelectionStrategy} that works with {@link - * ConfigFileAuthenticationDetailsProvider} instances. - */ - CONFIG_FILE(ConfigFileAuthenticationDetailsProvider.class) { - - @Override // AdpSelectionStrategy - boolean isAvailable(Selector selector, Config c, Annotation[] qualifiersArray) { - if (super.isAvailable(selector, c, qualifiersArray)) { - try { - this.get(selector, c, qualifiersArray); - } catch (UncheckedIOException uncheckedIoException) { - Object cause = uncheckedIoException.getCause(); - if (cause instanceof FileNotFoundException || cause instanceof NoSuchFileException) { - return false; - } - throw uncheckedIoException; - } - return true; - } - return false; - } - - @Override // AdpSelectionStrategy - Void produceBuilder(Selector selector, Config c, Annotation[] qualifiersArray) { - throw new UnsupportedOperationException(); - } - - @Override // AdpSelectionStrategy - ConfigFileAuthenticationDetailsProvider produce(Selector selector, Config c, Annotation[] qualifiersArray) { - return - this.produce(c.get("oci.config.path", String.class).orElse(null), // null on purpose; use OCI defaulting logic - c.get("oci.config.profile", String.class) - .orElse(c.get("oci.auth.profile", String.class) - .orElse("DEFAULT"))); - } - - private ConfigFileAuthenticationDetailsProvider produce(String ociConfigPath, String ociAuthProfile) { - try { - if (ociConfigPath == null) { - // Don't get clever and try to use ~/.oci/config - // as a default value; there is OCI-managed logic - // to figure out the proper default; we want to - // make sure it's used - return new ConfigFileAuthenticationDetailsProvider(ociAuthProfile); - } else { - return new ConfigFileAuthenticationDetailsProvider(ociConfigPath, ociAuthProfile); - } - } catch (FileNotFoundException fileNotFoundException) { - throw new UncheckedIOException(fileNotFoundException.getMessage(), fileNotFoundException); - } catch (NoSuchFileException noSuchFileException) { - throw new UncheckedIOException(noSuchFileException.getMessage(), noSuchFileException); - } catch (IOException ioException) { - // The underlying ConfigFileReader that does the real - // work does not throw a FileNotFoundException in this - // case (as it probably should). We have no choice - // but to parse the error message. See - // https://github.com/oracle/oci-java-sdk/blob/2.19.0/bmc-common/src/main/java/com/oracle/bmc/ConfigFileReader.java#L94-L98. - String message = ioException.getMessage(); - if (message != null - && message.startsWith("Can't load the default config from ") - && message.endsWith(" because it does not exist or it is not a file.")) { - throw new UncheckedIOException(message, - (IOException) new FileNotFoundException(message).initCause(ioException)); - } - throw new UncheckedIOException(message, ioException); - } - } - }, - - /** - * An {@link AdpSelectionStrategy} that works with {@link - * InstancePrincipalsAuthenticationDetailsProvider} instances. - */ - INSTANCE_PRINCIPALS(InstancePrincipalsAuthenticationDetailsProvider.class, - InstancePrincipalsAuthenticationDetailsProviderBuilder.class) { - - private final String defaultImdsHostname = URI.create(METADATA_SERVICE_BASE_URL).getHost(); - - @Override // AdpSelectionStrategy - boolean isAvailable(Selector selector, Config c, Annotation[] qualifiersArray) { - if (super.isAvailable(selector, c, qualifiersArray)) { - InetAddress imds = null; - try { - imds = InetAddress.getByName(c.get("oci.imds.hostname", String.class).orElse(this.defaultImdsHostname)); - } catch (UnknownHostException unknownHostException) { - throw new UncheckedIOException(unknownHostException.getMessage(), unknownHostException); - } - int ociImdsTimeoutMillis = 0; - try { - ociImdsTimeoutMillis = - Math.max(0, c.get("oci.imds.timeout.milliseconds", Integer.class).orElse(Integer.valueOf(100))); - } catch (IllegalArgumentException conversionException) { - ociImdsTimeoutMillis = 100; - } - try { - return imds.isReachable(ociImdsTimeoutMillis); - } catch (ConnectException connectException) { - return false; - } catch (IOException ioException) { - throw new UncheckedIOException(ioException.getMessage(), ioException); - } - } - return false; - } - - @Override // AdpSelectionStrategy - InstancePrincipalsAuthenticationDetailsProviderBuilder produceBuilder(Selector s, Config c, Annotation[] qs) { - return InstancePrincipalsAuthenticationDetailsProvider.builder(); - } - - @Override // AdpSelectionStrategy - InstancePrincipalsAuthenticationDetailsProvider produce(Selector selector, Config c, Annotation[] qualifiersArray) { - return selector.select(InstancePrincipalsAuthenticationDetailsProviderBuilder.class, qualifiersArray).get().build(); - } - }, - - /** - * An {@link AdpSelectionStrategy} that works with {@link - * ResourcePrincipalAuthenticationDetailsProvider} instances. - */ - RESOURCE_PRINCIPAL(ResourcePrincipalAuthenticationDetailsProvider.class, - ResourcePrincipalAuthenticationDetailsProviderBuilder.class) { - - @Override // AdpSelectionStrategy - boolean isAvailable(Selector selector, Config c, Annotation[] qualifiersArray) { - return - super.isAvailable(selector, c, qualifiersArray) - // https://github.com/oracle/oci-java-sdk/blob/v2.19.0/bmc-common/src/main/java/com/oracle/bmc/auth/ResourcePrincipalAuthenticationDetailsProvider.java#L246-L251 - && System.getenv("OCI_RESOURCE_PRINCIPAL_VERSION") != null; - } - - @Override // AdpSelectionStrategy - ResourcePrincipalAuthenticationDetailsProviderBuilder produceBuilder(Selector s, Config c, Annotation[] qualifiersArray) { - return ResourcePrincipalAuthenticationDetailsProvider.builder(); - } - - @Override // AdpSelectionStrategy - ResourcePrincipalAuthenticationDetailsProvider produce(Selector selector, Config c, Annotation[] qualifiersArray) { - return selector.select(ResourcePrincipalAuthenticationDetailsProviderBuilder.class, qualifiersArray).get().build(); - } - }, - - /** - * An {@linkplain #isAbstract() abstract} {@link - * AdpSelectionStrategy} that selects the most appropriate - * concrete {@link AdpSelectionStrategy} by consulting - * configuration. - */ - AUTO(AbstractAuthenticationDetailsProvider.class, true) { - - private final transient Logger logger = Logger.getLogger(this.getClass().getName()); - - @Override // AdpSelectionStrategy - Void produceBuilder(Selector selector, Config c, Annotation[] qualifiersArray) { - throw new UnsupportedOperationException(); - } - - @Override // AdpSelectionStrategy - AbstractAuthenticationDetailsProvider produce(Selector selector, Config c, Annotation[] qualifiersArray) { - Collection strategies = - concreteStrategies(c.get("oci.auth-strategies", String[].class) - .or(() -> c.get("oci.auth-strategy", String[].class)) - .orElse(null)); - for (AdpSelectionStrategy s : strategies) { - if (s == this) { - // concreteStrategies(String[]) bug - throw new IllegalStateException("concreteStrategies(String[]) returned " + this.name()); - } else if (s.isAvailable(selector, c, qualifiersArray)) { - logger.config(() -> "Using authentication strategy " + s.configName() - + "; selected AbstractAuthenticationDetailsProvider " + s.type().getTypeName()); - return s.get(selector, c, qualifiersArray); - } else { - logger.fine(() -> "Skipping authentication strategy " + s.configName() + " because it is not available"); - } - } - throw new NoSuchElementException("No instances of " - + AbstractAuthenticationDetailsProvider.class.getName() - + " available for use"); - } - - }; - - - /* - * Static fields. - */ - - - private static final Collection CONCRETE_STRATEGIES; - - private static final Set> BUILDER_CLASSES; - - static { - EnumSet set = EnumSet.allOf(AdpSelectionStrategy.class); - set.removeIf(AdpSelectionStrategy::isAbstract); - CONCRETE_STRATEGIES = Collections.unmodifiableCollection(set); - Set> builderClasses = new HashSet<>(7); - for (AdpSelectionStrategy s : set) { - Class builderType = s.builderType(); - if (builderType != null) { - builderClasses.add(builderType); - } - } - BUILDER_CLASSES = Collections.unmodifiableSet(builderClasses); - } - - - /* - * Instance fields. - */ - - - private final Class type; - - private final Class builderType; - - private final boolean isAbstract; - - - /* - * Constructors. - */ - - - AdpSelectionStrategy(Class type) { - this(type, null, false); - } - - AdpSelectionStrategy(Class type, boolean isAbstract) { - this(type, null, isAbstract); - } - - AdpSelectionStrategy(Class type, Class builderType) { - this(type, builderType, false); - } - - AdpSelectionStrategy(Class type, Class builderType, boolean isAbstract) { - this.type = Objects.requireNonNull(type, "type"); - this.builderType = builderType; - this.isAbstract = isAbstract; - } - - - /* - * Instance methods. - */ - - - final String configName() { - return this.name().replace('_', '-').toLowerCase(); - } - - final Class type() { - return this.type; - } - - final Class builderType() { - return this.builderType; - } - - final AbstractAuthenticationDetailsProvider get(Selector selector, Config c, Annotation[] qualifiersArray) { - return selector.select(this.type(), qualifiersArray).get(); - } - - final boolean isAbstract() { - return this.isAbstract; - } - - boolean isAvailable(Selector selector, Config c, Annotation[] qualifiersArray) { - return !this.isAbstract(); - } - - abstract Object produceBuilder(Selector selector, Config c, Annotation[] qualifiersArray); - - abstract AbstractAuthenticationDetailsProvider produce(Selector selector, Config c, Annotation[] qualifiersArray); - - - /* - * Static methods. - */ - - - static Set> builderClasses() { - return BUILDER_CLASSES; - } - - private static AdpSelectionStrategy of(String name) { - return valueOf(name.replace('-', '_').toUpperCase()); - } - - private static AdpSelectionStrategy ofConfigString(String strategyString) { - if (strategyString == null) { - return AUTO; - } else { - strategyString = strategyString.strip(); - return strategyString.isBlank() ? AUTO : of(strategyString); - } - } - - private static Collection concreteStrategies() { - return CONCRETE_STRATEGIES; - } - - private static Collection concreteStrategies(String[] strategyStringsArray) { - Collection strategies; - AdpSelectionStrategy strategy; - switch (strategyStringsArray == null ? 0 : strategyStringsArray.length) { - case 0: - strategies = List.of(); - break; - case 1: - strategy = ofConfigString(strategyStringsArray[0]); - strategies = strategy.isAbstract() ? List.of() : EnumSet.of(strategy); - break; - default: - Set strategyStrings = new LinkedHashSet<>(Arrays.asList(strategyStringsArray)); - switch (strategyStrings.size()) { - case 0: - throw new AssertionError(); - case 1: - strategy = ofConfigString(strategyStrings.iterator().next()); - strategies = strategy.isAbstract() ? List.of() : EnumSet.of(strategy); - break; - default: - strategies = new ArrayList<>(strategyStrings.size()); - for (String s : strategyStrings) { - strategy = ofConfigString(s); - if (!strategy.isAbstract()) { - strategies.add(strategy); - } - } - } - break; - } - if (strategies.isEmpty()) { - return concreteStrategies(); - } - return Collections.unmodifiableCollection(strategies); - } - - - /* - * Inner and nested classes. - */ - - - interface Selector { - - Supplier select(Class type, Annotation... qualifiers); - - } - - interface Config { - - Optional get(String name, Class type); - - } - -} diff --git a/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/OciExtension.java b/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/OciExtension.java index f40888e2fea..9818d0d277f 100644 --- a/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/OciExtension.java +++ b/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/OciExtension.java @@ -27,10 +27,8 @@ import java.security.ProtectionDomain; import java.util.Arrays; import java.util.Collection; -import java.util.EnumSet; import java.util.HashSet; import java.util.Objects; -import java.util.Optional; import java.util.Set; import java.util.function.Consumer; import java.util.function.Supplier; @@ -40,6 +38,13 @@ import com.oracle.bmc.Service; import com.oracle.bmc.auth.AbstractAuthenticationDetailsProvider; +import com.oracle.bmc.auth.BasicAuthenticationDetailsProvider; +import com.oracle.bmc.auth.InstancePrincipalsAuthenticationDetailsProvider; +import com.oracle.bmc.auth.InstancePrincipalsAuthenticationDetailsProvider.InstancePrincipalsAuthenticationDetailsProviderBuilder; +import com.oracle.bmc.auth.ResourcePrincipalAuthenticationDetailsProvider; +import com.oracle.bmc.auth.ResourcePrincipalAuthenticationDetailsProvider.ResourcePrincipalAuthenticationDetailsProviderBuilder; +import com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider; +import com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider.SimpleAuthenticationDetailsProviderBuilder; import com.oracle.bmc.common.ClientBuilderBase; import jakarta.enterprise.event.Event; import jakarta.enterprise.event.Observes; @@ -58,6 +63,7 @@ import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.ConfigProvider; +import static io.helidon.integrations.oci.sdk.runtime.OciExtension.ociAuthenticationProvider; import static java.lang.invoke.MethodType.methodType; /** @@ -559,6 +565,11 @@ public final class OciExtension implements Extension { private static final Lookup PUBLIC_LOOKUP = MethodHandles.publicLookup(); + private static final Set> ADP_BUILDER_CLASSES = + Set.of(InstancePrincipalsAuthenticationDetailsProviderBuilder.class, + ResourcePrincipalAuthenticationDetailsProviderBuilder.class, + SimpleAuthenticationDetailsProviderBuilder.class); + private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0]; @@ -634,7 +645,7 @@ private void processInjectionPoint(@Observes ProcessInjectionPoint event) } Set qualifiers = ip.getQualifiers(); if (AbstractAuthenticationDetailsProvider.class.isAssignableFrom(baseClass) - || AdpSelectionStrategy.builderClasses().contains(baseClass)) { + || ADP_BUILDER_CLASSES.contains(baseClass)) { // Use an "empty" ServiceTaqs as an indicator of demand // for some kind of AbstractAuthenticationDetailsProvider // (or a relevant builder). @@ -823,45 +834,115 @@ private Class toClassUnresolved(Consumer erro private static void installAdps(AfterBeanDiscovery event, BeanManager bm, Annotation[] qualifiersArray) { Set qualifiers = Set.of(qualifiersArray); - for (AdpSelectionStrategy s : EnumSet.allOf(AdpSelectionStrategy.class)) { - Type builderType = s.builderType(); - if (builderType != null) { - TypeAndQualifiers builderTaq = new TypeAndQualifiers(builderType, qualifiersArray); - if (isUnsatisfied(bm, builderTaq)) { - event.addBean() - .types(builderType) - .qualifiers(qualifiers) - .scope(Singleton.class) - .produceWith(i -> produceAdpBuilder(s, i, qualifiersArray)); - } - } - Type type = s.type(); - TypeAndQualifiers taq = new TypeAndQualifiers(type, qualifiersArray); - if (isUnsatisfied(bm, taq)) { - event.addBean() - .types(type) - .qualifiers(qualifiers) - .scope(Singleton.class) - .produceWith(i -> produceAdp(s, i, qualifiersArray)); - } + + // AbstractAuthenticationDetailsProvider + if (isUnsatisfied(bm, + new TypeAndQualifiers(AbstractAuthenticationDetailsProvider.class, qualifiersArray))) { + Supplier s = ociAuthenticationProvider(); + event.addBean() + .types(AbstractAuthenticationDetailsProvider.class) + .qualifiers(qualifiers) + .scope(Singleton.class) + .produceWith(i -> + s.get()); + } + + // BasicAuthenticationDetailsProvider + if (isUnsatisfied(bm, + new TypeAndQualifiers(BasicAuthenticationDetailsProvider.class, qualifiersArray))) { + Supplier s = ociAuthenticationProvider(); + event.addBean() + .types(BasicAuthenticationDetailsProvider.class) + .qualifiers(qualifiers) + .scope(Singleton.class) + .produceWith(i -> + (BasicAuthenticationDetailsProvider) s.get()); + } + + // InstancePrincipalsAuthenticationDetailsProvider + if (isUnsatisfied(bm, + new TypeAndQualifiers(InstancePrincipalsAuthenticationDetailsProviderBuilder.class, qualifiersArray))) { + event.addBean() + .types(InstancePrincipalsAuthenticationDetailsProviderBuilder.class) + .qualifiers(qualifiers) + .scope(Singleton.class) + .produceWith(i -> + produceAdpBuilder(InstancePrincipalsAuthenticationDetailsProvider::builder, + i, + qualifiersArray)); + } + if (isUnsatisfied(bm, + new TypeAndQualifiers(InstancePrincipalsAuthenticationDetailsProvider.class, qualifiersArray))) { + event.addBean() + .types(InstancePrincipalsAuthenticationDetailsProvider.class) + .qualifiers(qualifiers) + .scope(Singleton.class) + .produceWith(i -> + i.select(InstancePrincipalsAuthenticationDetailsProviderBuilder.class, + qualifiersArray) + .get() + .build()); + } + + // ResourcePrincipalAuthenticationDetailsProvider + if (isUnsatisfied(bm, + new TypeAndQualifiers(ResourcePrincipalAuthenticationDetailsProviderBuilder.class, qualifiersArray))) { + event.addBean() + .types(ResourcePrincipalAuthenticationDetailsProviderBuilder.class) + .qualifiers(qualifiers) + .scope(Singleton.class) + .produceWith(i -> + produceAdpBuilder(ResourcePrincipalAuthenticationDetailsProvider::builder, + i, + qualifiersArray)); + } + if (isUnsatisfied(bm, + new TypeAndQualifiers(ResourcePrincipalAuthenticationDetailsProvider.class, qualifiersArray))) { + event.addBean() + .types(ResourcePrincipalAuthenticationDetailsProvider.class) + .qualifiers(qualifiers) + .scope(Singleton.class) + .produceWith(i -> + i.select(ResourcePrincipalAuthenticationDetailsProviderBuilder.class, + qualifiersArray) + .get() + .build()); + } + + // SimpleAuthenticationDetailsProvider + if (isUnsatisfied(bm, + new TypeAndQualifiers(SimpleAuthenticationDetailsProviderBuilder.class, qualifiersArray))) { + event.addBean() + .types(SimpleAuthenticationDetailsProviderBuilder.class) + .qualifiers(qualifiers) + .scope(Singleton.class) + .produceWith(i -> + produceAdpBuilder(SimpleAuthenticationDetailsProvider::builder, + i, + qualifiersArray)); + } + if (isUnsatisfied(bm, new TypeAndQualifiers(SimpleAuthenticationDetailsProvider.class, qualifiersArray))) { + event.addBean() + .types(SimpleAuthenticationDetailsProvider.class) + .qualifiers(qualifiers) + .scope(Singleton.class) + .produceWith(i -> + i.select(SimpleAuthenticationDetailsProviderBuilder.class, + qualifiersArray) + .get() + .build()); } } - private static Object produceAdpBuilder(AdpSelectionStrategy s, - Instance instance, - Annotation[] qualifiersArray) { - Object builder = s.produceBuilder(SelectorShim.of(instance), ConfigShim.of(instance), qualifiersArray); + private static T produceAdpBuilder(Supplier s, + Instance instance, + Annotation[] qualifiersArray) { + T builder = s.get(); // Permit arbitrary customization. fire(instance, builder, qualifiersArray); return builder; } - private static AbstractAuthenticationDetailsProvider produceAdp(AdpSelectionStrategy s, - Instance instance, - Annotation[] qualifiersArray) { - return s.produce(SelectorShim.of(instance), ConfigShim.of(instance), qualifiersArray); - } - private static boolean installServiceClientBuilder(AfterBeanDiscovery event, BeanManager bm, TypeAndQualifiers serviceClientBuilder, @@ -1301,96 +1382,4 @@ public final boolean equals(Object other) { } - private static class SelectorShim implements AdpSelectionStrategy.Selector { - - - /* - * Instance fields. - */ - - - private final Instance instance; - - - /* - * Constructors. - */ - - - private SelectorShim(Instance instance) { - super(); - this.instance = Objects.requireNonNull(instance, "instance"); - } - - - /* - * Instance methods. - */ - - - @Override // AdpSelectionStrategy.Selector - public final Supplier select(Class type, Annotation... qualifiers) { - return this.instance.select(type, qualifiers)::get; - } - - - /* - * Static methods. - */ - - - private static SelectorShim of(Instance instance) { - return new SelectorShim(instance); - } - - } - - private static class ConfigShim implements AdpSelectionStrategy.Config { - - - /* - * Instance fields. - */ - - - private final Config config; - - - /* - * Constructors. - */ - - - private ConfigShim(Config config) { - super(); - this.config = Objects.requireNonNull(config, "config"); - } - - - /* - * Instance methods. - */ - - - @Override // AdpSelectionStrategy.Config - public final Optional get(String propertyName, Class propertyType) { - return config.getOptionalValue(propertyName, propertyType); - } - - - /* - * Static methods. - */ - - - private static ConfigShim of(Config config) { - return new ConfigShim(config); - } - - private static ConfigShim of(Instance instance) { - return of(instance.select(Config.class).get()); - } - - } - } diff --git a/integrations/oci/sdk/cdi/src/main/java/module-info.java b/integrations/oci/sdk/cdi/src/main/java/module-info.java index 95961df80cc..a85e31d9b2a 100644 --- a/integrations/oci/sdk/cdi/src/main/java/module-info.java +++ b/integrations/oci/sdk/cdi/src/main/java/module-info.java @@ -30,10 +30,11 @@ requires transitive jakarta.cdi; requires jakarta.inject; requires jakarta.ws.rs; + requires io.helidon.integrations.oci.sdk.runtime; requires microprofile.config.api; requires oci.java.sdk.common; requires oci.java.sdk.common.httpclient; - + exports io.helidon.integrations.oci.sdk.cdi; provides jakarta.enterprise.inject.spi.Extension From 8da139dfeab7477742ff563ef60c50320e8bef73 Mon Sep 17 00:00:00 2001 From: Laird Nelson Date: Mon, 14 Aug 2023 17:07:19 -0700 Subject: [PATCH 2/6] Squashable commit; simplifies code Signed-off-by: Laird Nelson --- .../oci/sdk/cdi/OciExtension.java | 36 +++++-------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/OciExtension.java b/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/OciExtension.java index 9818d0d277f..7cf52e0d12e 100644 --- a/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/OciExtension.java +++ b/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/OciExtension.java @@ -836,8 +836,7 @@ private static void installAdps(AfterBeanDiscovery event, BeanManager bm, Annota Set qualifiers = Set.of(qualifiersArray); // AbstractAuthenticationDetailsProvider - if (isUnsatisfied(bm, - new TypeAndQualifiers(AbstractAuthenticationDetailsProvider.class, qualifiersArray))) { + if (isUnsatisfied(bm, new TypeAndQualifiers(AbstractAuthenticationDetailsProvider.class, qualifiersArray))) { Supplier s = ociAuthenticationProvider(); event.addBean() .types(AbstractAuthenticationDetailsProvider.class) @@ -866,10 +865,7 @@ private static void installAdps(AfterBeanDiscovery event, BeanManager bm, Annota .types(InstancePrincipalsAuthenticationDetailsProviderBuilder.class) .qualifiers(qualifiers) .scope(Singleton.class) - .produceWith(i -> - produceAdpBuilder(InstancePrincipalsAuthenticationDetailsProvider::builder, - i, - qualifiersArray)); + .produceWith(i -> fire(i, InstancePrincipalsAuthenticationDetailsProvider.builder(), qualifiersArray)); } if (isUnsatisfied(bm, new TypeAndQualifiers(InstancePrincipalsAuthenticationDetailsProvider.class, qualifiersArray))) { @@ -891,10 +887,7 @@ private static void installAdps(AfterBeanDiscovery event, BeanManager bm, Annota .types(ResourcePrincipalAuthenticationDetailsProviderBuilder.class) .qualifiers(qualifiers) .scope(Singleton.class) - .produceWith(i -> - produceAdpBuilder(ResourcePrincipalAuthenticationDetailsProvider::builder, - i, - qualifiersArray)); + .produceWith(i -> fire(i, ResourcePrincipalAuthenticationDetailsProvider.builder(), qualifiersArray)); } if (isUnsatisfied(bm, new TypeAndQualifiers(ResourcePrincipalAuthenticationDetailsProvider.class, qualifiersArray))) { @@ -910,16 +903,12 @@ private static void installAdps(AfterBeanDiscovery event, BeanManager bm, Annota } // SimpleAuthenticationDetailsProvider - if (isUnsatisfied(bm, - new TypeAndQualifiers(SimpleAuthenticationDetailsProviderBuilder.class, qualifiersArray))) { + if (isUnsatisfied(bm, new TypeAndQualifiers(SimpleAuthenticationDetailsProviderBuilder.class, qualifiersArray))) { event.addBean() .types(SimpleAuthenticationDetailsProviderBuilder.class) .qualifiers(qualifiers) .scope(Singleton.class) - .produceWith(i -> - produceAdpBuilder(SimpleAuthenticationDetailsProvider::builder, - i, - qualifiersArray)); + .produceWith(i -> fire(i, SimpleAuthenticationDetailsProvider.builder(), qualifiersArray)); } if (isUnsatisfied(bm, new TypeAndQualifiers(SimpleAuthenticationDetailsProvider.class, qualifiersArray))) { event.addBean() @@ -934,15 +923,6 @@ private static void installAdps(AfterBeanDiscovery event, BeanManager bm, Annota } } - private static T produceAdpBuilder(Supplier s, - Instance instance, - Annotation[] qualifiersArray) { - T builder = s.get(); - // Permit arbitrary customization. - fire(instance, builder, qualifiersArray); - return builder; - } - private static boolean installServiceClientBuilder(AfterBeanDiscovery event, BeanManager bm, TypeAndQualifiers serviceClientBuilder, @@ -1044,8 +1024,7 @@ private static Object produceClientBuilder(Instance instance, throw new AssertionError(impossible.getMessage(), impossible); } // Permit arbitrary customization. - fire(instance, builderInstance, qualifiers); - return builderInstance; + return fire(instance, builderInstance, qualifiers); } private static Object produceClient(Instance instance, Class builderClass, Annotation[] qualifiersArray) { @@ -1076,8 +1055,9 @@ private static void close(AutoCloseable autoCloseable) { } @SuppressWarnings("unchecked") - private static void fire(Instance instance, T payload, Annotation[] qualifiers) { + private static T fire(Instance instance, T payload, Annotation[] qualifiers) { instance.select(EVENT_OBJECT_TYPE_LITERAL).get().select((Class) payload.getClass(), qualifiers).fire(payload); + return payload; } private static boolean isUnsatisfied(BeanManager bm, TypeAndQualifiers taq) { From ad85ca5c01dcb19ea01be0535099356571ffebf8 Mon Sep 17 00:00:00 2001 From: Laird Nelson Date: Mon, 14 Aug 2023 17:11:30 -0700 Subject: [PATCH 3/6] Squashable commit; simplifies code Signed-off-by: Laird Nelson --- .../oci/sdk/cdi/OciExtension.java | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/OciExtension.java b/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/OciExtension.java index 7cf52e0d12e..7a4332bec2d 100644 --- a/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/OciExtension.java +++ b/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/OciExtension.java @@ -836,7 +836,7 @@ private static void installAdps(AfterBeanDiscovery event, BeanManager bm, Annota Set qualifiers = Set.of(qualifiersArray); // AbstractAuthenticationDetailsProvider - if (isUnsatisfied(bm, new TypeAndQualifiers(AbstractAuthenticationDetailsProvider.class, qualifiersArray))) { + if (isUnsatisfied(bm, AbstractAuthenticationDetailsProvider.class, qualifiersArray)) { Supplier s = ociAuthenticationProvider(); event.addBean() .types(AbstractAuthenticationDetailsProvider.class) @@ -847,8 +847,7 @@ private static void installAdps(AfterBeanDiscovery event, BeanManager bm, Annota } // BasicAuthenticationDetailsProvider - if (isUnsatisfied(bm, - new TypeAndQualifiers(BasicAuthenticationDetailsProvider.class, qualifiersArray))) { + if (isUnsatisfied(bm, BasicAuthenticationDetailsProvider.class, qualifiersArray)) { Supplier s = ociAuthenticationProvider(); event.addBean() .types(BasicAuthenticationDetailsProvider.class) @@ -859,16 +858,14 @@ private static void installAdps(AfterBeanDiscovery event, BeanManager bm, Annota } // InstancePrincipalsAuthenticationDetailsProvider - if (isUnsatisfied(bm, - new TypeAndQualifiers(InstancePrincipalsAuthenticationDetailsProviderBuilder.class, qualifiersArray))) { + if (isUnsatisfied(bm, InstancePrincipalsAuthenticationDetailsProviderBuilder.class, qualifiersArray)) { event.addBean() .types(InstancePrincipalsAuthenticationDetailsProviderBuilder.class) .qualifiers(qualifiers) .scope(Singleton.class) .produceWith(i -> fire(i, InstancePrincipalsAuthenticationDetailsProvider.builder(), qualifiersArray)); } - if (isUnsatisfied(bm, - new TypeAndQualifiers(InstancePrincipalsAuthenticationDetailsProvider.class, qualifiersArray))) { + if (isUnsatisfied(bm, InstancePrincipalsAuthenticationDetailsProvider.class, qualifiersArray)) { event.addBean() .types(InstancePrincipalsAuthenticationDetailsProvider.class) .qualifiers(qualifiers) @@ -881,16 +878,14 @@ private static void installAdps(AfterBeanDiscovery event, BeanManager bm, Annota } // ResourcePrincipalAuthenticationDetailsProvider - if (isUnsatisfied(bm, - new TypeAndQualifiers(ResourcePrincipalAuthenticationDetailsProviderBuilder.class, qualifiersArray))) { + if (isUnsatisfied(bm, ResourcePrincipalAuthenticationDetailsProviderBuilder.class, qualifiersArray)) { event.addBean() .types(ResourcePrincipalAuthenticationDetailsProviderBuilder.class) .qualifiers(qualifiers) .scope(Singleton.class) .produceWith(i -> fire(i, ResourcePrincipalAuthenticationDetailsProvider.builder(), qualifiersArray)); } - if (isUnsatisfied(bm, - new TypeAndQualifiers(ResourcePrincipalAuthenticationDetailsProvider.class, qualifiersArray))) { + if (isUnsatisfied(bm, ResourcePrincipalAuthenticationDetailsProvider.class, qualifiersArray)) { event.addBean() .types(ResourcePrincipalAuthenticationDetailsProvider.class) .qualifiers(qualifiers) @@ -903,14 +898,14 @@ private static void installAdps(AfterBeanDiscovery event, BeanManager bm, Annota } // SimpleAuthenticationDetailsProvider - if (isUnsatisfied(bm, new TypeAndQualifiers(SimpleAuthenticationDetailsProviderBuilder.class, qualifiersArray))) { + if (isUnsatisfied(bm, SimpleAuthenticationDetailsProviderBuilder.class, qualifiersArray)) { event.addBean() .types(SimpleAuthenticationDetailsProviderBuilder.class) .qualifiers(qualifiers) .scope(Singleton.class) .produceWith(i -> fire(i, SimpleAuthenticationDetailsProvider.builder(), qualifiersArray)); } - if (isUnsatisfied(bm, new TypeAndQualifiers(SimpleAuthenticationDetailsProvider.class, qualifiersArray))) { + if (isUnsatisfied(bm, SimpleAuthenticationDetailsProvider.class, qualifiersArray)) { event.addBean() .types(SimpleAuthenticationDetailsProvider.class) .qualifiers(qualifiers) From f56c82789cfd47573e2104b705b0975914496274 Mon Sep 17 00:00:00 2001 From: Laird Nelson Date: Tue, 12 Sep 2023 10:10:07 -0700 Subject: [PATCH 4/6] Squashable commit; invokes fallbackConfigSupplier per request Signed-off-by: Laird Nelson --- integrations/oci/sdk/cdi/pom.xml | 4 ++++ .../oci/sdk/cdi/OciExtension.java | 21 ++++++++++++------- .../sdk/cdi/src/main/java/module-info.java | 1 + 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/integrations/oci/sdk/cdi/pom.xml b/integrations/oci/sdk/cdi/pom.xml index deb0c6c0adb..7ab71fa16db 100644 --- a/integrations/oci/sdk/cdi/pom.xml +++ b/integrations/oci/sdk/cdi/pom.xml @@ -61,6 +61,10 @@ + + io.helidon.config + helidon-config-mp + io.helidon.integrations.oci.sdk helidon-integrations-oci-sdk-runtime diff --git a/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/OciExtension.java b/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/OciExtension.java index 7a4332bec2d..2882f1e15bd 100644 --- a/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/OciExtension.java +++ b/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/OciExtension.java @@ -63,6 +63,8 @@ import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.ConfigProvider; +import static io.helidon.config.mp.MpConfig.toHelidonConfig; +import static io.helidon.integrations.oci.sdk.runtime.OciExtension.fallbackConfigSupplier; import static io.helidon.integrations.oci.sdk.runtime.OciExtension.ociAuthenticationProvider; import static java.lang.invoke.MethodType.methodType; @@ -663,14 +665,17 @@ private void processInjectionPoint(@Observes ProcessInjectionPoint event) } private void afterBeanDiscovery(@Observes AfterBeanDiscovery event, BeanManager bm) { - for (ServiceTaqs serviceTaqs : this.serviceTaqs) { - if (serviceTaqs.isEmpty()) { - installAdps(event, bm, serviceTaqs.qualifiers()); - } else { - TypeAndQualifiers serviceClientBuilder = serviceTaqs.serviceClientBuilder(); - TypeAndQualifiers serviceClient = serviceTaqs.serviceClient(); - installServiceClientBuilder(event, bm, serviceClientBuilder, serviceClient, this.lenientClassloading); - installServiceClient(event, bm, serviceClient, serviceTaqs.serviceInterface(), serviceClientBuilder); + if (!this.serviceTaqs.isEmpty()) { + fallbackConfigSupplier(() -> toHelidonConfig(ConfigProvider.getConfig())); + for (ServiceTaqs serviceTaqs : this.serviceTaqs) { + if (serviceTaqs.isEmpty()) { + installAdps(event, bm, serviceTaqs.qualifiers()); + } else { + TypeAndQualifiers serviceClientBuilder = serviceTaqs.serviceClientBuilder(); + TypeAndQualifiers serviceClient = serviceTaqs.serviceClient(); + installServiceClientBuilder(event, bm, serviceClientBuilder, serviceClient, this.lenientClassloading); + installServiceClient(event, bm, serviceClient, serviceTaqs.serviceInterface(), serviceClientBuilder); + } } } } diff --git a/integrations/oci/sdk/cdi/src/main/java/module-info.java b/integrations/oci/sdk/cdi/src/main/java/module-info.java index a85e31d9b2a..3336a5ea06e 100644 --- a/integrations/oci/sdk/cdi/src/main/java/module-info.java +++ b/integrations/oci/sdk/cdi/src/main/java/module-info.java @@ -30,6 +30,7 @@ requires transitive jakarta.cdi; requires jakarta.inject; requires jakarta.ws.rs; + requires io.helidon.config.mp; requires io.helidon.integrations.oci.sdk.runtime; requires microprofile.config.api; requires oci.java.sdk.common; From 6aede2170099c6e0439f2ee9a5ff10080c046453 Mon Sep 17 00:00:00 2001 From: Laird Nelson Date: Tue, 12 Sep 2023 14:10:59 -0700 Subject: [PATCH 5/6] Squashable commit; introduces a test that tests the io.helidon.integrations.oci.sdk.runtime.OciExtension class per request Signed-off-by: Laird Nelson --- .../cdi/TestOciSdkRuntimeOciExtension.java | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 integrations/oci/sdk/cdi/src/test/java/io/helidon/integrations/oci/sdk/cdi/TestOciSdkRuntimeOciExtension.java diff --git a/integrations/oci/sdk/cdi/src/test/java/io/helidon/integrations/oci/sdk/cdi/TestOciSdkRuntimeOciExtension.java b/integrations/oci/sdk/cdi/src/test/java/io/helidon/integrations/oci/sdk/cdi/TestOciSdkRuntimeOciExtension.java new file mode 100644 index 00000000000..300fd305702 --- /dev/null +++ b/integrations/oci/sdk/cdi/src/test/java/io/helidon/integrations/oci/sdk/cdi/TestOciSdkRuntimeOciExtension.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.helidon.integrations.oci.sdk.cdi; + +import java.util.Map; +import java.util.Set; + +import io.helidon.config.Config; + +import com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider; +import org.eclipse.microprofile.config.ConfigProvider; +import org.eclipse.microprofile.config.spi.ConfigProviderResolver; +import org.eclipse.microprofile.config.spi.ConfigSource; +import org.junit.jupiter.api.Test; + +import static io.helidon.config.mp.MpConfig.toHelidonConfig; +import static io.helidon.integrations.oci.sdk.runtime.OciExtension.configSupplier; +import static io.helidon.integrations.oci.sdk.runtime.OciExtension.configuredAuthenticationDetailsProvider; +import static io.helidon.integrations.oci.sdk.runtime.OciExtension.fallbackConfigSupplier; +import static io.helidon.integrations.oci.sdk.runtime.OciExtension.isSufficientlyConfigured; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.MatcherAssert.assertThat; + +class TestOciSdkRuntimeOciExtension { + + @Test + void testOciSdkRuntimeOciExtensionUsesEmptyMicroProfileConfigProperly() { + // Create a MicroProfile Config Config object that is almost entirely empty, save for a single property used to + // test that this creation worked. + org.eclipse.microprofile.config.Config emptyMicroProfileConfig = ConfigProviderResolver.instance().getBuilder() + .withSources(new MinimalConfigSource(Map.of("valid", "true"))) + .build(); + + // (Sanity check.) + assertThat(emptyMicroProfileConfig.getValue("valid", String.class), is(equalTo("true"))); + + // Convert the MicroProfile Config Config into a Helidon Config. + Config hc = toHelidonConfig(emptyMicroProfileConfig); + assertThat(hc, not(equalTo(nullValue()))); + + // Pass it to the io.helidon.integrations.oci.sdk.runtime.OciExtension class as its "fallback config supplier". + fallbackConfigSupplier(() -> hc); + + // Assert that this method call worked. + assertThat(configSupplier().get(), is(equalTo(hc))); + + // Assert that the Helidon Config is not "sufficiently configured", for the purposes of the + // io.helidon.integrations.oci.sdk.runtime.OciExtension class, since it does not specify an explicit + // authentication strategy. This effectively tests whether "auto" is + // io.helidon.integrations.oci.sdk.runtime.OciExtension's effective authentication strategy. + assertThat(isSufficientlyConfigured(hc), is(equalTo(false))); + } + + @Test + void testOciSdkRuntimeOciExtensionUsesNonEmptyMicroProfileConfigProperly() { + // Create a MicroProfile Config Config object that contains "oci.auth-strategies" set to "config" only. Note + // that, deliberately, although its value is "config", there are deliberately no other properties. The + // io.helidon.integrations.oci.sdk.runtime.OciExtension class will indicate that this is a valid strategy, but + // (correctly) that it is not available since we didn't set any other properties. + org.eclipse.microprofile.config.Config c = ConfigProviderResolver.instance().getBuilder() + .withSources(new MinimalConfigSource(Map.of("oci.auth-strategies", "config"))) + .build(); + + // (Sanity check.) + assertThat(c.getValue("oci.auth-strategies", String.class), is(equalTo("config"))); + + // Convert the MicroProfile Config Config into a Helidon Config. + Config hc = toHelidonConfig(c); + assertThat(hc, not(equalTo(nullValue()))); + + // Pass it to the io.helidon.integrations.oci.sdk.runtime.OciExtension class as its "fallback config supplier". + fallbackConfigSupplier(() -> hc); + + // Assert that this method call worked. + assertThat(configSupplier().get(), is(equalTo(hc))); + + // Assert that the selected strategy is not, in fact, available, since we didn't supply enough information for + // it to be so. We have to pass "false" for "verifyIsAvailable" because otherwise, despite the fact we have + // specified an unavailable but explicit strategy, it will try to fall back to a different one. + assertThat(configuredAuthenticationDetailsProvider(false), is(equalTo(SimpleAuthenticationDetailsProvider.class))); + } + + private static class MinimalConfigSource implements ConfigSource { + + private final Map properties; + + private MinimalConfigSource(Map properties) { + super(); + this.properties = Map.copyOf(properties); + } + + @Override + public String getName() { + return this.getClass().getName(); + } + + @Override + public Map getProperties() { + return this.properties; + } + + @Override + public Set getPropertyNames() { + return this.getProperties().keySet(); + } + + @Override + public String getValue(String propertyName) { + return propertyName == null ? null : this.getProperties().get(propertyName); + } + + } + +} From 2b84fdf86bafa0937f5ca24cd3796db6cd9160d8 Mon Sep 17 00:00:00 2001 From: Laird Nelson Date: Tue, 12 Sep 2023 15:00:07 -0700 Subject: [PATCH 6/6] Squashable commit; reformats copyright header so that it has the proper number of lines Signed-off-by: Laird Nelson --- .../oci/sdk/cdi/TestOciSdkRuntimeOciExtension.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/integrations/oci/sdk/cdi/src/test/java/io/helidon/integrations/oci/sdk/cdi/TestOciSdkRuntimeOciExtension.java b/integrations/oci/sdk/cdi/src/test/java/io/helidon/integrations/oci/sdk/cdi/TestOciSdkRuntimeOciExtension.java index 300fd305702..f0d17bcb079 100644 --- a/integrations/oci/sdk/cdi/src/test/java/io/helidon/integrations/oci/sdk/cdi/TestOciSdkRuntimeOciExtension.java +++ b/integrations/oci/sdk/cdi/src/test/java/io/helidon/integrations/oci/sdk/cdi/TestOciSdkRuntimeOciExtension.java @@ -1,15 +1,19 @@ /* * Copyright (c) 2023 Oracle and/or its affiliates. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ + package io.helidon.integrations.oci.sdk.cdi; import java.util.Map;