diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/main/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/AppConfigurationWebAutoConfiguration.java b/sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/main/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/AppConfigurationWebAutoConfiguration.java
index 8e1376a46045..fd08cc653354 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/main/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/AppConfigurationWebAutoConfiguration.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/main/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/AppConfigurationWebAutoConfiguration.java
@@ -42,15 +42,18 @@ AppConfigurationEventListener configListener(AppConfigurationRefresh appConfigur
"org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties",
"org.springframework.cloud.endpoint.RefreshEndpoint"
})
+ @Deprecated
static class AppConfigurationPushRefreshConfiguration {
@Bean
+ @Deprecated
AppConfigurationRefreshEndpoint appConfigurationRefreshEndpoint(ContextRefresher contextRefresher,
AppConfigurationProperties appConfiguration) {
return new AppConfigurationRefreshEndpoint(contextRefresher, appConfiguration);
}
@Bean
+ @Deprecated
AppConfigurationRefreshEventListener appConfigurationRefreshEventListener(
AppConfigurationRefresh appConfigurationRefresh) {
return new AppConfigurationRefreshEventListener(appConfigurationRefresh);
@@ -63,15 +66,18 @@ AppConfigurationRefreshEventListener appConfigurationRefreshEventListener(
"org.springframework.cloud.bus.BusProperties",
"org.springframework.cloud.bus.event.RefreshRemoteApplicationEvent",
"org.springframework.cloud.endpoint.RefreshEndpoint" })
+ @Deprecated
static class AppConfigurationBusConfiguration {
@Bean
+ @Deprecated
AppConfigurationBusRefreshEndpoint appConfigurationBusRefreshEndpoint(ApplicationContext context,
BusProperties bus, AppConfigurationProperties appConfiguration, Destination.Factory destinationFactory) {
return new AppConfigurationBusRefreshEndpoint(context, bus.getId(), destinationFactory, appConfiguration);
}
@Bean
+ @Deprecated
AppConfigurationBusRefreshEventListener appConfigurationBusRefreshEventListener(
AppConfigurationRefresh appConfigurationRefresh) {
return new AppConfigurationBusRefreshEventListener(appConfigurationRefresh);
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/main/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/pullrefresh/AppConfigurationEventListener.java b/sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/main/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/pullrefresh/AppConfigurationEventListener.java
index 1b00e0f55600..8771558968af 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/main/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/pullrefresh/AppConfigurationEventListener.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/main/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/pullrefresh/AppConfigurationEventListener.java
@@ -9,6 +9,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
+import org.springframework.lang.NonNull;
import org.springframework.web.context.support.ServletRequestHandledEvent;
import com.azure.spring.cloud.appconfiguration.config.AppConfigurationRefresh;
@@ -32,7 +33,7 @@ public AppConfigurationEventListener(AppConfigurationRefresh appConfigurationRef
}
@Override
- public void onApplicationEvent(ServletRequestHandledEvent event) {
+ public void onApplicationEvent(@NonNull ServletRequestHandledEvent event) {
try {
if (!(event.getRequestUrl().equals(ACTUATOR + APPCONFIGURATION_REFRESH)
|| event.getRequestUrl().equals(ACTUATOR + APPCONFIGURATION_REFRESH_BUS))) {
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/main/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/pushbusrefresh/AppConfigurationBusRefreshEventListener.java b/sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/main/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/pushbusrefresh/AppConfigurationBusRefreshEventListener.java
index bf846e6418df..296f554f51ec 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/main/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/pushbusrefresh/AppConfigurationBusRefreshEventListener.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/main/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/pushbusrefresh/AppConfigurationBusRefreshEventListener.java
@@ -5,6 +5,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
+import org.springframework.lang.NonNull;
import com.azure.spring.cloud.appconfiguration.config.AppConfigurationRefresh;
@@ -31,7 +32,7 @@ public AppConfigurationBusRefreshEventListener(AppConfigurationRefresh appConfig
* @param event Event Triggering refresh, contains valid config store endpoint.
*/
@Override
- public void onApplicationEvent(AppConfigurationBusRefreshEvent event) {
+ public void onApplicationEvent(@NonNull AppConfigurationBusRefreshEvent event) {
try {
appConfigurationRefresh.expireRefreshInterval(event.getEndpoint(), event.getSyncToken());
} catch (Exception e) {
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/main/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/pushrefresh/AppConfigurationRefreshEndpoint.java b/sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/main/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/pushrefresh/AppConfigurationRefreshEndpoint.java
index 139f2a18b433..1a97678e0cd9 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/main/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/pushrefresh/AppConfigurationRefreshEndpoint.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/main/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/pushrefresh/AppConfigurationRefreshEndpoint.java
@@ -10,11 +10,12 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpoint;
+import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.cloud.context.refresh.ContextRefresher;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.http.HttpStatus;
+import org.springframework.lang.NonNull;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@@ -29,8 +30,7 @@
/**
* Endpoint for requesting new configurations to be loaded.
*/
-@SuppressWarnings("removal")
-@ControllerEndpoint(id = APPCONFIGURATION_REFRESH)
+@Endpoint(id = APPCONFIGURATION_REFRESH)
public class AppConfigurationRefreshEndpoint implements ApplicationEventPublisherAware {
private static final Logger LOGGER = LoggerFactory.getLogger(AppConfigurationRefreshEndpoint.class);
@@ -105,7 +105,7 @@ public String refresh(HttpServletRequest request, HttpServletResponse response,
}
@Override
- public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
+ public void setApplicationEventPublisher(@NonNull ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/main/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/pushrefresh/AppConfigurationRefreshEventListener.java b/sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/main/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/pushrefresh/AppConfigurationRefreshEventListener.java
index 187946abbf02..cfaf05050bc9 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/main/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/pushrefresh/AppConfigurationRefreshEventListener.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/main/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/pushrefresh/AppConfigurationRefreshEventListener.java
@@ -5,6 +5,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
+import org.springframework.lang.NonNull;
import com.azure.spring.cloud.appconfiguration.config.AppConfigurationRefresh;
@@ -32,7 +33,7 @@ public AppConfigurationRefreshEventListener(AppConfigurationRefresh appConfigura
* @param event Event Triggering refresh, contains valid config store endpoint.
*/
@Override
- public void onApplicationEvent(AppConfigurationRefreshEvent event) {
+ public void onApplicationEvent(@NonNull AppConfigurationRefreshEvent event) {
try {
appConfigurationRefresh.expireRefreshInterval(event.getEndpoint(), event.getSyncToken());
} catch (Exception e) {
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/test/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/AppConfigurationWebAutoConfigurationTest.java b/sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/test/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/AppConfigurationWebAutoConfigurationTest.java
deleted file mode 100644
index 2f861d46ad5d..000000000000
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/test/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/AppConfigurationWebAutoConfigurationTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-package com.azure.spring.cloud.appconfiguration.config.web.implementation;
-
-import static com.azure.spring.cloud.appconfiguration.config.web.implementation.TestConstants.CONN_STRING_PROP;
-import static com.azure.spring.cloud.appconfiguration.config.web.implementation.TestConstants.STORE_ENDPOINT_PROP;
-import static com.azure.spring.cloud.appconfiguration.config.web.implementation.TestConstants.TEST_CONN_STRING;
-import static com.azure.spring.cloud.appconfiguration.config.web.implementation.TestConstants.TEST_STORE_NAME;
-import static com.azure.spring.cloud.appconfiguration.config.web.implementation.TestUtils.propPair;
-import static org.assertj.core.api.Assertions.assertThat;
-
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
-import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.test.context.FilteredClassLoader;
-import org.springframework.boot.test.context.runner.ApplicationContextRunner;
-import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
-import org.springframework.cloud.bus.BusProperties;
-import org.springframework.cloud.bus.event.PathDestinationFactory;
-import org.springframework.cloud.bus.event.RefreshRemoteApplicationEvent;
-import org.springframework.cloud.endpoint.RefreshEndpoint;
-
-import com.azure.spring.cloud.appconfiguration.config.AppConfigurationAutoConfiguration;
-import com.azure.spring.cloud.appconfiguration.config.implementation.config.AppConfigurationBootstrapConfiguration;
-import com.azure.spring.cloud.autoconfigure.implementation.context.AzureGlobalPropertiesAutoConfiguration;
-
-public class AppConfigurationWebAutoConfigurationTest {
-
- private static final ApplicationContextRunner CONTEXT_RUNNER = new ApplicationContextRunner()
- .withPropertyValues(propPair(CONN_STRING_PROP, TEST_CONN_STRING),
- propPair(STORE_ENDPOINT_PROP, TEST_STORE_NAME))
- .withConfiguration(AutoConfigurations.of(AppConfigurationBootstrapConfiguration.class,
- AppConfigurationAutoConfiguration.class, AppConfigurationWebAutoConfiguration.class,
- RefreshAutoConfiguration.class, PathDestinationFactory.class, AzureGlobalPropertiesAutoConfiguration.class))
- .withUserConfiguration(BusProperties.class);
-
- @Test
- public void refreshMissing() {
- CONTEXT_RUNNER
- .withClassLoader(new FilteredClassLoader(WebEndpointProperties.class))
- .run(context -> {
- assertThat(context)
- .doesNotHaveBean("appConfigurationRefreshBusEndpoint");
- assertThat(context)
- .doesNotHaveBean("appConfigurationRefreshEndpoint");
- assertThat(context)
- .hasBean("configListener");
- });
- }
-
- @Test
- public void busRefreshMissing() {
- CONTEXT_RUNNER
- .withClassLoader(new FilteredClassLoader(RefreshRemoteApplicationEvent.class))
- .run(context -> {
- assertThat(context)
- .doesNotHaveBean("appConfigurationBusRefreshEndpoint");
- assertThat(context)
- .hasBean("appConfigurationRefreshEndpoint");
- assertThat(context)
- .hasBean("configListener");
- });
- }
-
- @Test
- public void pullRefreshListenerMissing() {
- CONTEXT_RUNNER.withClassLoader(new FilteredClassLoader(RefreshEndpoint.class))
- .run(context -> assertThat(context)
- .doesNotHaveBean("configListener"));
- }
-
- @Test
- public void pushRefresh() {
- CONTEXT_RUNNER
- .run(context -> {
- assertThat(context)
- .hasBean("appConfigurationRefreshEndpoint");
- });
- }
-
- @Test
- public void busRefresh() {
- CONTEXT_RUNNER
- .run(context -> assertThat(context)
- .hasBean("appConfigurationBusRefreshEndpoint"));
- }
-
- @Test
- public void fullRefresh() {
- CONTEXT_RUNNER
- .run(context -> {
- assertThat(context)
- .hasBean("configListener");
- assertThat(context)
- .hasBean("appConfigurationRefreshEndpoint");
- assertThat(context)
- .hasBean("appConfigurationBusRefreshEndpoint");
- });
- }
-}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/pom.xml b/sdk/spring/spring-cloud-azure-appconfiguration-config/pom.xml
index ca003da589e4..b04d37285fc6 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/pom.xml
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/pom.xml
@@ -29,11 +29,6 @@
3.4.1
true
-
- org.springframework.cloud
- spring-cloud-starter-bootstrap
- 4.2.0
-
org.springframework.cloud
spring-cloud-context
@@ -45,6 +40,11 @@
3.4.1
compile
+
+ jakarta.annotation
+ jakarta.annotation-api
+ 3.0.0
+
com.azure
@@ -177,13 +177,14 @@
- com.fasterxml.jackson.core:jackson-annotations:[2.18.2]
- com.fasterxml.jackson.core:jackson-databind:[2.18.2]
+ jakarta.annotation:jakarta.annotation-api:[3.0.0]
+ com.fasterxml.jackson.core:jackson-annotations:[2.17.2]
+ com.fasterxml.jackson.core:jackson-databind:[2.17.2]
org.springframework.boot:spring-boot-actuator:[3.4.1]
org.springframework.boot:spring-boot-autoconfigure:[3.4.1]
org.springframework.cloud:spring-cloud-context:[4.2.0]
org.springframework.boot:spring-boot-configuration-processor:[3.4.1]
- org.springframework.cloud:spring-cloud-starter-bootstrap:[4.2.0]
+ org.springframework.cloud:spring-cloud-starter-bootstrap:[4.1.4]
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/AppConfigurationAutoConfiguration.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/AppConfigurationWatchAutoConfiguration.java
similarity index 55%
rename from sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/AppConfigurationAutoConfiguration.java
rename to sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/AppConfigurationWatchAutoConfiguration.java
index dde0e852d65a..d2d7262e439e 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/AppConfigurationAutoConfiguration.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/AppConfigurationWatchAutoConfiguration.java
@@ -2,12 +2,14 @@
// Licensed under the MIT License.
package com.azure.spring.cloud.appconfiguration.config;
+import org.springframework.boot.BootstrapContext;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.endpoint.RefreshEndpoint;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationPullRefresh;
@@ -20,36 +22,28 @@
/**
* Setup AppConfigurationRefresh when spring.cloud.azure.appconfiguration.enabled is enabled.
*/
-@Configuration
@EnableAsync
@ConditionalOnProperty(prefix = AppConfigurationProperties.CONFIG_PREFIX, name = "enabled", matchIfMissing = true)
-public class AppConfigurationAutoConfiguration {
+@EnableConfigurationProperties({ AppConfigurationProperties.class, AppConfigurationProviderProperties.class })
+@AutoConfiguration
+@ConditionalOnClass(RefreshEndpoint.class)
+public class AppConfigurationWatchAutoConfiguration {
/**
- * Creates an instance of {@link AppConfigurationAutoConfiguration}
+ * Creates an instance of {@link AppConfigurationWatchAutoConfiguration}
*/
- public AppConfigurationAutoConfiguration() {
+ public AppConfigurationWatchAutoConfiguration() {
}
- /**
- * Auto Watch
- */
- @Configuration
- @ConditionalOnClass(RefreshEndpoint.class)
- public static class AppConfigurationWatchAutoConfiguration {
-
- /**
- * Creates an instance of {@link AppConfigurationWatchAutoConfiguration}
- */
- public AppConfigurationWatchAutoConfiguration() {
- }
+ @Bean
+ @ConditionalOnMissingBean
+ AppConfigurationRefresh appConfigurationRefresh(AppConfigurationProperties properties,
+ AppConfigurationProviderProperties appProperties, BootstrapContext context) {
+ AppConfigurationReplicaClientFactory clientFactory = context
+ .get(AppConfigurationReplicaClientFactory.class);
+ ReplicaLookUp replicaLookUp = context.get(ReplicaLookUp.class);
- @Bean
- @ConditionalOnMissingBean
- AppConfigurationRefresh appConfigurationRefresh(AppConfigurationProperties properties,
- AppConfigurationProviderProperties appProperties, AppConfigurationReplicaClientFactory clientFactory, ReplicaLookUp replicaLookUp) {
- return new AppConfigurationPullRefresh(clientFactory, properties.getRefreshInterval(),
- appProperties.getDefaultMinBackoff(), replicaLookUp, new AppConfigurationRefreshUtil());
- }
+ return new AppConfigurationPullRefresh(clientFactory, properties.getRefreshInterval(),
+ appProperties.getDefaultMinBackoff(), replicaLookUp, new AppConfigurationRefreshUtil());
}
}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationApplicationSettingPropertySource.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationApplicationSettingPropertySource.java
index 5d410ab33151..f7c2a6c90f8b 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationApplicationSettingPropertySource.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationApplicationSettingPropertySource.java
@@ -107,7 +107,7 @@ protected void processConfigurationSettings(List settings,
* @return Key Vault Secret Value
* @throws InvalidConfigurationPropertyValueException
*/
- protected void handleKeyVaultReference(String key, SecretReferenceConfigurationSetting secretReference)
+ private void handleKeyVaultReference(String key, SecretReferenceConfigurationSetting secretReference)
throws InvalidConfigurationPropertyValueException {
// Parsing Key Vault Reference for URI
try {
@@ -129,7 +129,7 @@ void handleFeatureFlag(String key, FeatureFlagConfigurationSetting setting, List
handleJson(setting, trimStrings);
}
- void handleJson(ConfigurationSetting setting, List keyPrefixTrimValues)
+ private void handleJson(ConfigurationSetting setting, List keyPrefixTrimValues)
throws InvalidConfigurationPropertyValueException {
Map jsonSettings = JsonConfigurationParser.parseJsonSetting(setting);
for (Entry jsonSetting : jsonSettings.entrySet()) {
@@ -138,7 +138,7 @@ void handleJson(ConfigurationSetting setting, List keyPrefixTrimValues)
}
}
- protected String trimKey(String key, List trimStrings) {
+ private String trimKey(String key, List trimStrings) {
key = key.trim();
if (trimStrings != null) {
for (String trim : trimStrings) {
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationConstants.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationConstants.java
index 44a8db8df3cc..2daacc4bfd41 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationConstants.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationConstants.java
@@ -12,16 +12,6 @@ public class AppConfigurationConstants {
*/
public static final String FEATURE_FLAG_CONTENT_TYPE = "application/vnd.microsoft.appconfig.ff+json;charset=utf-8";
- /**
- * App Configurations Key Vault Reference Content Type
- */
- public static final String KEY_VAULT_CONTENT_TYPE = "application/vnd.microsoft.appconfig.keyvaultref+json;charset=utf-8";
-
- /**
- * Feature Management Key Prefix
- */
- public static final String FEATURE_MANAGEMENT_KEY = "feature-management.";
-
/**
* Feature Flag Prefix
*/
@@ -47,16 +37,11 @@ public class AppConfigurationConstants {
*/
public static final String KEY_VAULT_CONFIGURED_TRACING = "UsesKeyVault";
- /**
- * Constant for tracing for Replica Count
- */
- public static final String REPLICA_COUNT = "ReplicaCount";
-
/**
* Http Header User Agent
*/
public static final String USER_AGENT_TYPE = "User-Agent";
-
+
/**
* Http Header Correlation Context
*/
@@ -71,28 +56,10 @@ public class AppConfigurationConstants {
public static final String TELEMETRY = "telemetry";
- public static final String USERS = "users";
-
- public static final String USERS_CAPS = "Users";
-
- public static final String AUDIENCE = "Audience";
-
- public static final String GROUPS = "groups";
-
- public static final String GROUPS_CAPS = "Groups";
-
- public static final String TARGETING_FILTER = "targetingFilter";
-
- public static final String DEFAULT_ROLLOUT_PERCENTAGE = "defaultRolloutPercentage";
-
- public static final String DEFAULT_ROLLOUT_PERCENTAGE_CAPS = "DefaultRolloutPercentage";
-
public static final String DEFAULT_REQUIREMENT_TYPE = "Any";
public static final String REQUIREMENT_TYPE_SERVICE = "requirement_type";
- public static final String REQUIREMENT_TYPE = "requirement-type";
-
public static final String FEATURE_FLAG_ID = "FeatureFlagId";
public static final String FEATURE_FLAG_REFERENCE = "FeatureFlagReference";
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationKeyVaultClientFactory.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationKeyVaultClientFactory.java
index 2cc9fbffe363..6a27f783285f 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationKeyVaultClientFactory.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationKeyVaultClientFactory.java
@@ -10,7 +10,7 @@
import com.azure.spring.cloud.appconfiguration.config.implementation.stores.AppConfigurationSecretClientManager;
import com.azure.spring.cloud.service.implementation.keyvault.secrets.SecretClientBuilderFactory;
-public class AppConfigurationKeyVaultClientFactory {
+class AppConfigurationKeyVaultClientFactory {
private final Map keyVaultClients;
@@ -26,7 +26,7 @@ public class AppConfigurationKeyVaultClientFactory {
private final int timeout;
- public AppConfigurationKeyVaultClientFactory(SecretClientCustomizer keyVaultClientProvider,
+ AppConfigurationKeyVaultClientFactory(SecretClientCustomizer keyVaultClientProvider,
KeyVaultSecretProvider keyVaultSecretProvider, SecretClientBuilderFactory secretClientFactory,
boolean credentialsConfigured, int timeout) {
this.keyVaultClientProvider = keyVaultClientProvider;
@@ -38,7 +38,7 @@ public AppConfigurationKeyVaultClientFactory(SecretClientCustomizer keyVaultClie
this.timeout = timeout;
}
- public AppConfigurationSecretClientManager getClient(String host) {
+ AppConfigurationSecretClientManager getClient(String host) {
// Check if we already have a client for this key vault, if not we will make
// one
if (!keyVaultClients.containsKey(host)) {
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationPropertySource.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationPropertySource.java
index c31069689625..3a3c84907e22 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationPropertySource.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationPropertySource.java
@@ -2,7 +2,6 @@
// Licensed under the MIT License.
package com.azure.spring.cloud.appconfiguration.config.implementation;
-import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -12,7 +11,6 @@
import org.springframework.core.env.EnumerablePropertySource;
import com.azure.data.appconfiguration.ConfigurationClient;
-import com.azure.data.appconfiguration.models.ConfigurationSetting;
/**
* Azure App Configuration PropertySource unique per Store Label(Profile) combo.
@@ -26,8 +24,6 @@ abstract class AppConfigurationPropertySource extends EnumerablePropertySource properties = new LinkedHashMap<>();
- protected final List featureConfigurationSettings = new ArrayList<>();
-
protected final AppConfigurationReplicaClient replicaClient;
AppConfigurationPropertySource(String name, AppConfigurationReplicaClient replicaClient) {
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationPropertySourceLocator.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationPropertySourceLocator.java
deleted file mode 100644
index 04de646b0631..000000000000
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationPropertySourceLocator.java
+++ /dev/null
@@ -1,304 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-package com.azure.spring.cloud.appconfiguration.config.implementation;
-
-import static org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration.BOOTSTRAP_PROPERTY_SOURCE_NAME;
-
-import java.time.Duration;
-import java.time.Instant;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
-import org.springframework.core.env.CompositePropertySource;
-import org.springframework.core.env.ConfigurableEnvironment;
-import org.springframework.core.env.Environment;
-import org.springframework.core.env.PropertySource;
-import org.springframework.util.StringUtils;
-
-import com.azure.data.appconfiguration.models.ConfigurationSetting;
-import com.azure.spring.cloud.appconfiguration.config.implementation.autofailover.ReplicaLookUp;
-import com.azure.spring.cloud.appconfiguration.config.implementation.feature.FeatureFlags;
-import com.azure.spring.cloud.appconfiguration.config.implementation.properties.AppConfigurationKeyValueSelector;
-import com.azure.spring.cloud.appconfiguration.config.implementation.properties.AppConfigurationProviderProperties;
-import com.azure.spring.cloud.appconfiguration.config.implementation.properties.AppConfigurationStoreMonitoring;
-import com.azure.spring.cloud.appconfiguration.config.implementation.properties.ConfigStore;
-import com.azure.spring.cloud.appconfiguration.config.implementation.properties.FeatureFlagKeyValueSelector;
-
-/**
- * Locates Azure App Configuration Property Sources.
- */
-public final class AppConfigurationPropertySourceLocator implements PropertySourceLocator {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(AppConfigurationPropertySourceLocator.class);
-
- private static final String PROPERTY_SOURCE_NAME = "azure-config-store";
-
- private static final String REFRESH_ARGS_PROPERTY_SOURCE = "refreshArgs";
-
- private final List configStores;
-
- private final AppConfigurationProviderProperties appProperties;
-
- private final AppConfigurationReplicaClientFactory clientFactory;
-
- private final AppConfigurationKeyVaultClientFactory keyVaultClientFactory;
-
- private final FeatureFlagClient featureFlagClient;
-
- private final ReplicaLookUp replicaLookUp;
-
- private Duration refreshInterval;
-
- static final AtomicBoolean STARTUP = new AtomicBoolean(true);
-
- /**
- * Loads all Azure App Configuration Property Sources configured.
- *
- * @param properties Configurations for stores to be loaded.
- * @param appProperties Configurations for the library.
- * @param clientFactory factory for creating clients for connecting to Azure App Configuration.
- * @param keyVaultClientFactory factory for creating clients for connecting to Azure Key Vault
- * @param featureFlagLoader service for loadingFeatureFlags.
- */
- public AppConfigurationPropertySourceLocator(AppConfigurationProviderProperties appProperties,
- AppConfigurationReplicaClientFactory clientFactory, AppConfigurationKeyVaultClientFactory keyVaultClientFactory,
- Duration refreshInterval, List configStores, ReplicaLookUp replicaLookUp,
- FeatureFlagClient featureFlagLoader) {
- this.refreshInterval = refreshInterval;
- this.appProperties = appProperties;
- this.configStores = configStores;
- this.clientFactory = clientFactory;
- this.keyVaultClientFactory = keyVaultClientFactory;
- this.replicaLookUp = replicaLookUp;
- this.featureFlagClient = featureFlagLoader;
-
- BackoffTimeCalculator.setDefaults(appProperties.getDefaultMaxBackoff(), appProperties.getDefaultMinBackoff());
- }
-
- @Override
- public PropertySource> locate(Environment environment) {
- if (!(environment instanceof ConfigurableEnvironment)) {
- return null;
- }
- replicaLookUp.updateAutoFailoverEndpoints();
-
- ConfigurableEnvironment env = (ConfigurableEnvironment) environment;
- boolean currentlyLoaded = env.getPropertySources().stream().anyMatch(source -> {
- String storeName = configStores.get(0).getEndpoint();
- if (configStores.get(0).getSelects().size() == 0) {
- return false;
- }
- AppConfigurationKeyValueSelector selectedKey = configStores.get(0).getSelects().get(0);
- return source.getName()
- .startsWith(BOOTSTRAP_PROPERTY_SOURCE_NAME + "-" + selectedKey.getKeyFilter() + storeName + "/");
- });
- if (currentlyLoaded && !env.getPropertySources().contains(REFRESH_ARGS_PROPERTY_SOURCE)) {
- return null;
- }
-
- List profiles = Arrays.asList(env.getActiveProfiles());
-
- CompositePropertySource composite = new CompositePropertySource(PROPERTY_SOURCE_NAME);
- Collections.reverse(configStores); // Last store has the highest precedence
-
- StateHolder newState = new StateHolder();
- newState.setNextForcedRefresh(refreshInterval);
-
- // Feature Management needs to be set in the last config store.
- for (ConfigStore configStore : configStores) {
- boolean loadNewPropertySources = STARTUP.get() || StateHolder.getLoadState(configStore.getEndpoint());
-
- if (configStore.isEnabled() && loadNewPropertySources) {
- // There is only one Feature Set for all AppConfigurationPropertySources
-
- List clients = clientFactory
- .getAvailableClients(configStore.getEndpoint(), true);
-
- boolean generatedPropertySources = false;
-
- List sourceList = new ArrayList<>();
- boolean reloadFailed = false;
-
- for (AppConfigurationReplicaClient client : clients) {
- sourceList = new ArrayList<>();
-
- if (!STARTUP.get() && reloadFailed && !AppConfigurationRefreshUtil
- .checkStoreAfterRefreshFailed(client, clientFactory, configStore.getFeatureFlags())) {
- // This store doesn't have any changes where to refresh store did. Skipping Checking next.
- continue;
- }
-
- // Reverse in order to add Profile specific properties earlier, and last profile comes first
- try {
- List sources = createSettings(client, configStore, profiles);
- List featureFlags = createFeatureFlags(client, configStore, profiles);
- sourceList.addAll(sources);
-
- LOGGER.debug("PropertySource context.");
- setupMonitoring(configStore, client, sources, newState, featureFlags);
-
- generatedPropertySources = true;
- } catch (AppConfigurationStatusException e) {
- reloadFailed = true;
- clientFactory.backoffClientClient(configStore.getEndpoint(), client.getEndpoint());
- } catch (Exception e) {
- newState = failedToGeneratePropertySource(configStore, newState, e);
-
- // Not a retiable error
- break;
- }
- if (generatedPropertySources) {
- break;
- }
- }
-
- if (generatedPropertySources) {
- // Updating list of propertySources
- sourceList.forEach(composite::addPropertySource);
- } else if (!STARTUP.get() || (configStore.isFailFast() && STARTUP.get())) {
- String message = "Failed to generate property sources for " + configStore.getEndpoint();
-
- // Refresh failed for a config store ending attempt
- failedToGeneratePropertySource(configStore, newState, new RuntimeException(message));
- }
-
- if (featureFlagClient.getProperties().size() > 0) {
- // This can be true if feature flags are enabled or if a Snapshot contained feature flags
- AppConfigurationFeatureManagementPropertySource acfmps = new AppConfigurationFeatureManagementPropertySource(
- featureFlagClient);
- composite.addPropertySource(acfmps);
- }
-
- } else if (!configStore.isEnabled() && loadNewPropertySources) {
- LOGGER.info("Not loading configurations from {} as it is not enabled.", configStore.getEndpoint());
- } else {
- LOGGER.warn("Not loading configurations from {} as it failed on startup.", configStore.getEndpoint());
- }
- }
-
- StateHolder.updateState(newState);
- STARTUP.set(false);
-
- return composite;
- }
-
- private void setupMonitoring(ConfigStore configStore, AppConfigurationReplicaClient client,
- List sources, StateHolder newState, List featureFlags) {
- AppConfigurationStoreMonitoring monitoring = configStore.getMonitoring();
-
- if (configStore.getFeatureFlags().getEnabled()) {
- newState.setStateFeatureFlag(configStore.getEndpoint(), featureFlags,
- monitoring.getFeatureFlagRefreshInterval());
- }
-
- if (monitoring.isEnabled()) {
- // Setting new ETag values for Watch
- List watchKeysSettings = monitoring.getTriggers().stream()
- .map(trigger -> client.getWatchKey(trigger.getKey(), trigger.getLabel(), !STARTUP.get())).toList();
-
- newState.setState(configStore.getEndpoint(), watchKeysSettings, monitoring.getRefreshInterval());
- }
- newState.setLoadState(configStore.getEndpoint(), true, configStore.isFailFast());
- }
-
- private StateHolder failedToGeneratePropertySource(ConfigStore configStore, StateHolder newState, Exception e) {
- String message = "Failed to generate property sources for " + configStore.getEndpoint();
- if (!STARTUP.get()) {
- // Need to check for refresh first, or reset will never happen if fail fast is true.
- LOGGER.error("Refreshing failed while reading configuration from Azure App Configuration store "
- + configStore.getEndpoint() + ".");
-
- if (refreshInterval != null) {
- // The next refresh will happen sooner if refresh interval is expired.
- newState.updateNextRefreshTime(refreshInterval, appProperties.getDefaultMinBackoff());
- }
- throw new RuntimeException(message, e);
- } else if (configStore.isFailFast()) {
- LOGGER.error("Fail fast is set and there was an error reading configuration from Azure App "
- + "Configuration store " + configStore.getEndpoint() + ".");
- delayException();
- throw new RuntimeException(message, e);
- } else {
- LOGGER.warn(
- "Unable to load configuration from Azure AppConfiguration store " + configStore.getEndpoint() + ".", e);
- newState.setLoadState(configStore.getEndpoint(), false, configStore.isFailFast());
- }
- return newState;
- }
-
- /**
- * Creates a new set of AppConfigurationPropertySources, 1 per Label.
- *
- * @param client client for connecting to App Configuration
- * @param store Config Store the PropertySource is being generated from
- * @param profiles active profiles to be used as labels. it needs to be in the last one.
- * @return a list of AppConfigurationPropertySources
- * @throws Exception creating a property source failed
- */
- private List createSettings(AppConfigurationReplicaClient client, ConfigStore store,
- List profiles) throws Exception {
- List sourceList = new ArrayList<>();
- List selects = store.getSelects();
-
- for (AppConfigurationKeyValueSelector selectedKeys : selects) {
- AppConfigurationPropertySource propertySource = null;
-
- if (StringUtils.hasText(selectedKeys.getSnapshotName())) {
- propertySource = new AppConfigurationSnapshotPropertySource(
- selectedKeys.getSnapshotName() + "/" + store.getEndpoint(), client, keyVaultClientFactory,
- selectedKeys.getSnapshotName(), featureFlagClient);
- } else {
- propertySource = new AppConfigurationApplicationSettingPropertySource(
- selectedKeys.getKeyFilter() + store.getEndpoint() + "/", client, keyVaultClientFactory,
- selectedKeys.getKeyFilter(), selectedKeys.getLabelFilter(profiles));
- }
- propertySource.initProperties(store.getTrimKeyPrefix(), !STARTUP.get());
- sourceList.add(propertySource);
-
- }
-
- return sourceList;
- }
-
- /**
- * Creates a new set of AppConfigurationPropertySources, 1 per Label.
- *
- * @param client client for connecting to App Configuration
- * @param store Config Store the PropertySource is being generated from
- * @param profiles active profiles to be used as labels. it needs to be in the last one.
- * @return a list of AppConfigurationPropertySources
- * @throws Exception creating a property source failed
- */
- private List createFeatureFlags(AppConfigurationReplicaClient client, ConfigStore store,
- List profiles) throws Exception {
- List featureFlagWatchKeys = new ArrayList<>();
- if (store.getFeatureFlags().getEnabled()) {
- for (FeatureFlagKeyValueSelector selectedKeys : store.getFeatureFlags().getSelects()) {
- List storesFeatureFlags = featureFlagClient.loadFeatureFlags(client,
- selectedKeys.getKeyFilter(), selectedKeys.getLabelFilter(profiles), !STARTUP.get());
- storesFeatureFlags.forEach(featureFlags -> featureFlags.setConfigStore(store));
- featureFlagWatchKeys.addAll(storesFeatureFlags);
- }
- }
- return featureFlagWatchKeys;
- }
-
- private void delayException() {
- Instant currentDate = Instant.now();
- Instant preKillTIme = appProperties.getStartDate().plusSeconds(appProperties.getPrekillTime());
- if (currentDate.isBefore(preKillTIme)) {
- long diffInMillies = Math.abs(preKillTIme.toEpochMilli() - currentDate.toEpochMilli());
- try {
- Thread.sleep(diffInMillies);
- } catch (InterruptedException e) {
- LOGGER.error("Failed to wait before fast fail.");
- }
- }
- }
-}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationRefreshUtil.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationRefreshUtil.java
index ca1cc33c3905..94c1b9c8550f 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationRefreshUtil.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationRefreshUtil.java
@@ -108,12 +108,6 @@ RefreshEventData refreshStoresCheck(AppConfigurationReplicaClientFactory clientF
return eventData;
}
- static boolean checkStoreAfterRefreshFailed(AppConfigurationReplicaClient client,
- AppConfigurationReplicaClientFactory clientFactory, FeatureFlagStore featureStore) {
- return refreshStoreCheck(client, clientFactory.findOriginForEndpoint(client.getEndpoint()))
- || refreshStoreFeatureFlagCheck(featureStore, client);
- }
-
/**
* This is for a refresh fail only.
*
@@ -121,7 +115,7 @@ static boolean checkStoreAfterRefreshFailed(AppConfigurationReplicaClient client
* @param originEndpoint config store origin endpoint
* @return A refresh should be triggered.
*/
- private static boolean refreshStoreCheck(AppConfigurationReplicaClient client, String originEndpoint) {
+ static boolean refreshStoreCheck(AppConfigurationReplicaClient client, String originEndpoint) {
RefreshEventData eventData = new RefreshEventData();
if (StateHolder.getLoadState(originEndpoint)) {
refreshWithoutTime(client, StateHolder.getState(originEndpoint).getWatchKeys(), eventData);
@@ -136,12 +130,12 @@ private static boolean refreshStoreCheck(AppConfigurationReplicaClient client, S
* @param client Client checking for refresh
* @return true if a refresh should be triggered.
*/
- private static boolean refreshStoreFeatureFlagCheck(FeatureFlagStore featureStore,
+ static boolean refreshStoreFeatureFlagCheck(Boolean featureStoreEnabled,
AppConfigurationReplicaClient client) {
RefreshEventData eventData = new RefreshEventData();
String endpoint = client.getEndpoint();
- if (featureStore.getEnabled() && StateHolder.getStateFeatureFlag(endpoint) != null) {
+ if (featureStoreEnabled && StateHolder.getStateFeatureFlag(endpoint) != null) {
refreshWithoutTimeFeatureFlags(client, StateHolder.getStateFeatureFlag(endpoint), eventData);
} else {
LOGGER.debug("Skipping feature flag refresh check for " + endpoint);
@@ -197,7 +191,6 @@ private static void refreshWithTimeFeatureFlags(AppConfigurationReplicaClient cl
replicaLookUp.updateAutoFailoverEndpoints();
for (FeatureFlags featureFlags : state.getWatchKeys()) {
-
if (client.checkWatchKeys(featureFlags.getSettingSelector(), true)) {
String eventDataInfo = ".appconfig.featureflag/*";
@@ -219,7 +212,6 @@ private static void refreshWithoutTimeFeatureFlags(AppConfigurationReplicaClient
RefreshEventData eventData) throws AppConfigurationStatusException {
for (FeatureFlags featureFlags : watchKeys.getWatchKeys()) {
-
if (client.checkWatchKeys(featureFlags.getSettingSelector(), true)) {
String eventDataInfo = ".appconfig.featureflag/*";
@@ -273,7 +265,7 @@ RefreshEventData setMessage(String prefix) {
return this;
}
- RefreshEventData setFullMessage(String message) {
+ private RefreshEventData setFullMessage(String message) {
this.message = message;
this.doRefresh = true;
return this;
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClient.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClient.java
index 9c43522cafcb..5eea371940c2 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClient.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClient.java
@@ -22,7 +22,6 @@
import com.azure.data.appconfiguration.models.SettingSelector;
import com.azure.data.appconfiguration.models.SnapshotComposition;
import com.azure.spring.cloud.appconfiguration.config.implementation.feature.FeatureFlags;
-import com.azure.spring.cloud.appconfiguration.config.implementation.http.policy.TracingInfo;
import io.netty.handler.codec.http.HttpResponseStatus;
@@ -39,19 +38,16 @@ class AppConfigurationReplicaClient {
private int failedAttempts;
- private final TracingInfo tracingInfo;
-
/**
* Holds Configuration Client and info needed to manage backoff.
* @param endpoint client endpoint
* @param client Configuration Client to App Configuration store
*/
- AppConfigurationReplicaClient(String endpoint, ConfigurationClient client, TracingInfo tracingInfo) {
+ AppConfigurationReplicaClient(String endpoint, ConfigurationClient client) {
this.endpoint = endpoint;
this.client = client;
this.backoffEndTime = Instant.now().minusMillis(1);
this.failedAttempts = 0;
- this.tracingInfo = tracingInfo;
}
/**
@@ -92,7 +88,7 @@ String getEndpoint() {
* @param label String value of the watch key, use \0 for null.
* @return The first returned configuration.
*/
- ConfigurationSetting getWatchKey(String key, String label, Boolean isRefresh)
+ ConfigurationSetting getWatchKey(String key, String label, boolean isRefresh)
throws HttpResponseException {
try {
Context context = new Context("refresh", isRefresh);
@@ -115,7 +111,7 @@ ConfigurationSetting getWatchKey(String key, String label, Boolean isRefresh)
* @param settingSelector Information on which setting to pull. i.e. number of results, key value...
* @return List of Configuration Settings.
*/
- List listSettings(SettingSelector settingSelector, Boolean isRefresh)
+ List listSettings(SettingSelector settingSelector, boolean isRefresh)
throws HttpResponseException {
List configurationSettings = new ArrayList<>();
try {
@@ -134,7 +130,7 @@ List listSettings(SettingSelector settingSelector, Boolean
}
}
- FeatureFlags listFeatureFlags(SettingSelector settingSelector, Boolean isRefresh) throws HttpResponseException {
+ FeatureFlags listFeatureFlags(SettingSelector settingSelector, boolean isRefresh) throws HttpResponseException {
List configurationSettings = new ArrayList<>();
List checks = new ArrayList<>();
try {
@@ -159,10 +155,13 @@ FeatureFlags listFeatureFlags(SettingSelector settingSelector, Boolean isRefresh
}
}
- List listSettingSnapshot(String snapshotName) {
+ List listSettingSnapshot(String snapshotName, boolean isRefresh) {
List configurationSettings = new ArrayList<>();
try {
- ConfigurationSnapshot snapshot = client.getSnapshot(snapshotName);
+ // Because Spring always refreshes all we still have to load snapshots on refresh to build the property
+ // sources.
+ Context context = new Context("refresh", isRefresh);
+ ConfigurationSnapshot snapshot = client.getSnapshotWithResponse(snapshotName, null, context).getValue();
if (!SnapshotComposition.KEY.equals(snapshot.getSnapshotComposition())) {
throw new IllegalArgumentException("Snapshot " + snapshotName + " needs to be of type Key.");
}
@@ -178,8 +177,8 @@ List listSettingSnapshot(String snapshotName) {
}
}
- Boolean checkWatchKeys(SettingSelector settingSelector, Boolean isRefresh) {
- Context context = new Context("refresh", isRefresh);
+ boolean checkWatchKeys(SettingSelector settingSelector, boolean isRefresh) {
+ Context context = new Context("refresh", false);
List> results = client.listConfigurationSettings(settingSelector, context)
.streamByPage().filter(pagedResponse -> pagedResponse.getStatusCode() != 304).toList();
return results.size() > 0;
@@ -208,8 +207,4 @@ private HttpResponseException hanndleHttpResponseException(HttpResponseException
return e;
}
- TracingInfo getTracingInfo() {
- return tracingInfo;
- }
-
}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClientFactory.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClientFactory.java
index 4f3fd987cc2f..1aef5729e617 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClientFactory.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClientFactory.java
@@ -25,7 +25,7 @@ public class AppConfigurationReplicaClientFactory {
* @param clientBuilder builder for app configuration replica clients
* @param configStores configuration info for config stores
*/
- public AppConfigurationReplicaClientFactory(AppConfigurationReplicaClientsBuilder clientBuilder,
+ AppConfigurationReplicaClientFactory(AppConfigurationReplicaClientsBuilder clientBuilder,
List configStores, ReplicaLookUp replicaLookUp) {
this.configStores = configStores;
if (CONNECTIONS.size() == 0) {
@@ -99,23 +99,6 @@ String findOriginForEndpoint(String endpoint) {
return endpoint;
}
- /**
- * Checks if a given endpoint has any configured replicas.
- * @param endpoint Endpoint to check for replicas
- * @return true if at least one other unique endpoint connects to the same configuration store
- */
- boolean hasReplicas(String endpoint) {
- String originEndpoint = findOriginForEndpoint(endpoint);
- for (ConfigStore store : configStores) {
- if (store.getEndpoint().equals(originEndpoint)) {
- if (store.getConnectionStrings().size() > 0 || store.getEndpoints().size() > 0) {
- return true;
- }
- }
- }
- return false;
- }
-
/**
* Sets the replica as the currently used endpoint for connecting to the config store.
* @param originEndpoint Origin Configuration Store
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClientsBuilder.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClientsBuilder.java
index 3e225980e1fd..4f28d5297f28 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClientsBuilder.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClientsBuilder.java
@@ -14,8 +14,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.convert.DurationStyle;
-import org.springframework.context.EnvironmentAware;
-import org.springframework.core.env.Environment;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -25,7 +23,8 @@
import com.azure.core.util.Configuration;
import com.azure.core.util.CoreUtils;
import com.azure.data.appconfiguration.ConfigurationClientBuilder;
-import com.azure.identity.ManagedIdentityCredentialBuilder;
+import com.azure.identity.DefaultAzureCredential;
+import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.spring.cloud.appconfiguration.config.ConfigurationClientCustomizer;
import com.azure.spring.cloud.appconfiguration.config.implementation.http.policy.BaseAppConfigurationPolicy;
import com.azure.spring.cloud.appconfiguration.config.implementation.http.policy.TracingInfo;
@@ -37,22 +36,22 @@
import com.azure.spring.cloud.core.service.AzureServiceType.AppConfiguration;
import com.azure.spring.cloud.service.implementation.appconfiguration.ConfigurationClientBuilderFactory;
-public class AppConfigurationReplicaClientsBuilder implements EnvironmentAware {
+public class AppConfigurationReplicaClientsBuilder {
private static final Logger LOGGER = LoggerFactory.getLogger(AppConfigurationReplicaClientsBuilder.class);
/**
* Invalid Connection String error message
*/
- public static final String NON_EMPTY_MSG = "%s property should not be null or empty in the connection string of Azure Config Service.";
+ private static final String NON_EMPTY_MSG = "%s property should not be null or empty in the connection string of Azure Config Service.";
- public static final String RETRY_MODE_PROPERTY_NAME = "retry.mode";
+ private static final String RETRY_MODE_PROPERTY_NAME = "retry.mode";
- public static final String MAX_RETRIES_PROPERTY_NAME = "retry.exponential.max-retries";
+ private static final String MAX_RETRIES_PROPERTY_NAME = "retry.exponential.max-retries";
- public static final String BASE_DELAY_PROPERTY_NAME = "retry.exponential.base-delay";
+ private static final String BASE_DELAY_PROPERTY_NAME = "retry.exponential.base-delay";
- public static final String MAX_DELAY_PROPERTY_NAME = "retry.exponential.max-delay";
+ private static final String MAX_DELAY_PROPERTY_NAME = "retry.exponential.max-delay";
private static final Duration DEFAULT_MIN_RETRY_POLICY = Duration.ofMillis(800);
@@ -66,30 +65,28 @@ public class AppConfigurationReplicaClientsBuilder implements EnvironmentAware {
/**
* Invalid Formatted Connection String Error message
*/
- public static final String ENDPOINT_ERR_MSG = String.format("Connection string does not follow format %s.",
+ private static final String ENDPOINT_ERR_MSG = String.format("Connection string does not follow format %s.",
CONN_STRING_REGEXP);
private static final Pattern CONN_STRING_PATTERN = Pattern.compile(CONN_STRING_REGEXP);
- private ConfigurationClientCustomizer clientProvider;
+ private ConfigurationClientCustomizer clientCustomizer;
private final ConfigurationClientBuilderFactory clientFactory;
- private Environment env;
-
- private boolean isDev = false;
-
- private boolean isKeyVaultConfigured = false;
+ private boolean isKeyVaultConfigured;
private final boolean credentialConfigured;
private final int defaultMaxRetries;
- public AppConfigurationReplicaClientsBuilder(int defaultMaxRetries, ConfigurationClientBuilderFactory clientFactory,
- boolean credentialConfigured) {
+ AppConfigurationReplicaClientsBuilder(int defaultMaxRetries, ConfigurationClientBuilderFactory clientFactory,
+ ConfigurationClientCustomizer clientCustomizer, boolean credentialConfigured, boolean isKeyVaultConfigured) {
this.defaultMaxRetries = defaultMaxRetries;
- this.clientFactory = clientFactory;
this.credentialConfigured = credentialConfigured;
+ this.clientFactory = clientFactory;
+ this.clientCustomizer = clientCustomizer;
+ this.isKeyVaultConfigured = isKeyVaultConfigured;
}
/**
@@ -114,17 +111,6 @@ public static String getEndpointFromConnectionString(String connectionString) {
return endpoint;
}
- /**
- * @param clientProvider the clientProvider to set
- */
- public void setClientProvider(ConfigurationClientCustomizer clientProvider) {
- this.clientProvider = clientProvider;
- }
-
- public void setIsKeyVaultConfigured(boolean isKeyVaultConfigured) {
- this.isKeyVaultConfigured = isKeyVaultConfigured;
- }
-
/**
* Builds all the clients for a connection.
*
@@ -172,13 +158,11 @@ List buildClients(ConfigStore configStore) {
clients.add(modifyAndBuildClient(builder, endpoint, connectionStrings.size() - 1));
}
} else {
+ DefaultAzureCredential defautAzureCredential = new DefaultAzureCredentialBuilder().build();
for (String endpoint : endpoints) {
ConfigurationClientBuilder builder = this.createBuilderInstance();
if (!credentialConfigured) {
- // System Assigned Identity. Needs to be checked last as all of the above should
- // have an Endpoint.
- LOGGER.debug("Connecting to {} using Azure System Assigned Identity.", endpoint);
- builder.credential(new ManagedIdentityCredentialBuilder().build());
+ builder.credential(defautAzureCredential);
}
builder.endpoint(endpoint);
@@ -189,7 +173,7 @@ List buildClients(ConfigStore configStore) {
return clients;
}
- public AppConfigurationReplicaClient buildClient(String failoverEndpoint, ConfigStore configStore) {
+ AppConfigurationReplicaClient buildClient(String failoverEndpoint, ConfigStore configStore) {
if (StringUtils.hasText(configStore.getConnectionString())) {
ConnectionString connectionString = new ConnectionString(configStore.getConnectionString());
@@ -204,10 +188,7 @@ public AppConfigurationReplicaClient buildClient(String failoverEndpoint, Config
} else {
ConfigurationClientBuilder builder = createBuilderInstance();
if (!credentialConfigured) {
- // System Assigned Identity. Needs to be checked last as all of the above should
- // have an Endpoint.
- LOGGER.debug("Connecting to {} using Azure System Assigned Identity.", failoverEndpoint);
- builder.credential(new ManagedIdentityCredentialBuilder().build());
+ builder.credential(new DefaultAzureCredentialBuilder().build());
}
builder.endpoint(failoverEndpoint);
return modifyAndBuildClient(builder, failoverEndpoint, 0);
@@ -216,32 +197,22 @@ public AppConfigurationReplicaClient buildClient(String failoverEndpoint, Config
private AppConfigurationReplicaClient modifyAndBuildClient(ConfigurationClientBuilder builder, String endpoint,
Integer replicaCount) {
- TracingInfo tracingInfo = new TracingInfo(isDev, isKeyVaultConfigured, replicaCount,
+ TracingInfo tracingInfo = new TracingInfo(isKeyVaultConfigured, replicaCount,
Configuration.getGlobalConfiguration());
builder.addPolicy(new BaseAppConfigurationPolicy(tracingInfo));
- if (clientProvider != null) {
- clientProvider.customize(builder, endpoint);
- }
- return new AppConfigurationReplicaClient(endpoint, builder.buildClient(), tracingInfo);
- }
-
- @Override
- public void setEnvironment(Environment environment) {
- for (String profile : environment.getActiveProfiles()) {
- if ("dev".equalsIgnoreCase(profile)) {
- this.isDev = true;
- break;
- }
+ if (clientCustomizer != null) {
+ clientCustomizer.customize(builder, endpoint);
}
- this.env = environment;
+ return new AppConfigurationReplicaClient(endpoint, builder.buildClient());
}
- protected ConfigurationClientBuilder createBuilderInstance() {
+ private ConfigurationClientBuilder createBuilderInstance() {
RetryStrategy retryStatagy = null;
- String mode = env.getProperty(AzureGlobalProperties.PREFIX + "." + RETRY_MODE_PROPERTY_NAME);
- String modeService = env.getProperty(AzureAppConfigurationProperties.PREFIX + "." + RETRY_MODE_PROPERTY_NAME);
+ String mode = System.getProperty(AzureGlobalProperties.PREFIX + "." + RETRY_MODE_PROPERTY_NAME);
+ String modeService = System
+ .getProperty(AzureAppConfigurationProperties.PREFIX + "." + RETRY_MODE_PROPERTY_NAME);
if ("exponential".equals(mode) || "exponential".equals(modeService) || (mode == null && modeService == null)) {
Function checkPropertyInt = parameter -> (Integer.parseInt(parameter));
@@ -322,7 +293,6 @@ private static class ConnectionString {
private final String secret;
- @SuppressWarnings("deprecation")
ConnectionString(String connectionString) {
if (CoreUtils.isNullOrEmpty(connectionString)) {
throw new IllegalArgumentException("'connectionString' cannot be null or empty.");
@@ -358,7 +328,6 @@ private static class ConnectionString {
}
}
- @SuppressWarnings("deprecation")
protected ConnectionString setUri(String uri) {
try {
this.baseUri = new URL(uri);
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationSnapshotPropertySource.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationSnapshotPropertySource.java
index e4569b384150..853db7e8ab11 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationSnapshotPropertySource.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationSnapshotPropertySource.java
@@ -42,10 +42,11 @@ final class AppConfigurationSnapshotPropertySource extends AppConfigurationAppli
*
*
* @param trim prefix to trim
+ * @param isRefresh true if a refresh triggered the loading of the Snapshot.
* @throws InvalidConfigurationPropertyValueException thrown if fails to parse Json content type
*/
- public void initProperties(List trim) throws InvalidConfigurationPropertyValueException {
- processConfigurationSettings(replicaClient.listSettingSnapshot(snapshotName), null, trim);
+ public void initProperties(List trim, boolean isRefresh) throws InvalidConfigurationPropertyValueException {
+ processConfigurationSettings(replicaClient.listSettingSnapshot(snapshotName, isRefresh), null, trim);
FeatureFlags featureFlags = new FeatureFlags(null, featureFlagsList);
featureFlagClient.proccessFeatureFlags(featureFlags, replicaClient.getEndpoint());
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AzureAppConfigBoostrapRegistrar.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AzureAppConfigBoostrapRegistrar.java
new file mode 100644
index 000000000000..be7d90bb5e06
--- /dev/null
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AzureAppConfigBoostrapRegistrar.java
@@ -0,0 +1,136 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.spring.cloud.appconfiguration.config.implementation;
+
+import org.springframework.boot.BootstrapRegistry.InstanceSupplier;
+import org.springframework.boot.context.config.ConfigDataLocationResolverContext;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.context.properties.bind.Bindable;
+import org.springframework.boot.context.properties.bind.Binder;
+import org.springframework.util.StringUtils;
+
+import com.azure.data.appconfiguration.ConfigurationClientBuilder;
+import com.azure.spring.cloud.appconfiguration.config.ConfigurationClientCustomizer;
+import com.azure.spring.cloud.appconfiguration.config.KeyVaultSecretProvider;
+import com.azure.spring.cloud.appconfiguration.config.SecretClientCustomizer;
+import com.azure.spring.cloud.appconfiguration.config.implementation.autofailover.ReplicaLookUp;
+import com.azure.spring.cloud.appconfiguration.config.implementation.properties.AppConfigurationProperties;
+import com.azure.spring.cloud.appconfiguration.config.implementation.properties.AppConfigurationProviderProperties;
+import com.azure.spring.cloud.autoconfigure.implementation.appconfiguration.AzureAppConfigurationProperties;
+import com.azure.spring.cloud.autoconfigure.implementation.context.properties.AzureGlobalProperties;
+import com.azure.spring.cloud.autoconfigure.implementation.properties.core.AbstractAzureHttpConfigurationProperties;
+import com.azure.spring.cloud.autoconfigure.implementation.properties.core.authentication.TokenCredentialConfigurationProperties;
+import com.azure.spring.cloud.autoconfigure.implementation.properties.utils.AzureGlobalPropertiesUtils;
+import com.azure.spring.cloud.core.customizer.AzureServiceClientBuilderCustomizer;
+import com.azure.spring.cloud.core.implementation.util.AzureSpringIdentifier;
+import com.azure.spring.cloud.service.implementation.appconfiguration.ConfigurationClientBuilderFactory;
+import com.azure.spring.cloud.service.implementation.keyvault.secrets.SecretClientBuilderFactory;
+
+@EnableConfigurationProperties(AppConfigurationProviderProperties.class)
+class AzureAppConfigurationBootstrapRegistrar {
+
+ static void register(ConfigDataLocationResolverContext context, Binder binder,
+ AppConfigurationProperties properties, AppConfigurationProviderProperties appProperties,
+ ReplicaLookUp replicaLookup) {
+
+ AzureGlobalProperties globalProperties = binder
+ .bind(AzureGlobalProperties.PREFIX, Bindable.of(AzureGlobalProperties.class))
+ .orElseGet(AzureGlobalProperties::new);
+ AzureAppConfigurationProperties appConfigurationProperties = binder
+ .bind(AzureAppConfigurationProperties.PREFIX, Bindable.of(AzureAppConfigurationProperties.class))
+ .orElseGet(AzureAppConfigurationProperties::new);
+ // the properties are used to custom the ConfigurationClientBuilder
+ AzureAppConfigurationProperties loadedProperties = AzureGlobalPropertiesUtils.loadProperties(globalProperties,
+ appConfigurationProperties);
+
+ boolean isCredentialConfigured = isCredentialConfigured(loadedProperties);
+
+ AppConfigurationKeyVaultClientFactory keyVaultClientFactory = appConfigurationKeyVaultClientFactory(context,
+ isCredentialConfigured, appProperties.getMaxRetryTime());
+ AppConfigurationReplicaClientsBuilder replicaClientsBuilder = replicaClientBuilder(context, binder,
+ keyVaultClientFactory, loadedProperties, isCredentialConfigured, appProperties.getMaxRetries());
+
+ context.getBootstrapContext().registerIfAbsent(AppConfigurationKeyVaultClientFactory.class,
+ InstanceSupplier.from(() -> keyVaultClientFactory));
+ context.getBootstrapContext().registerIfAbsent(AppConfigurationReplicaClientFactory.class,
+ InstanceSupplier.from(() -> buildClientFactory(replicaClientsBuilder, properties, replicaLookup)));
+ }
+
+ private static AppConfigurationKeyVaultClientFactory appConfigurationKeyVaultClientFactory(
+ ConfigDataLocationResolverContext context, boolean isCredentialConfigured, Integer maxRetryTime)
+ throws IllegalArgumentException {
+
+ SecretClientCustomizer customizer = context.getBootstrapContext().getOrElse(SecretClientCustomizer.class, null);
+ KeyVaultSecretProvider secretProvider = context.getBootstrapContext().getOrElse(KeyVaultSecretProvider.class,
+ null);
+ SecretClientBuilderFactory secretClientFactory = context.getBootstrapContext()
+ .getOrElse(SecretClientBuilderFactory.class, null);
+
+ return new AppConfigurationKeyVaultClientFactory(customizer, secretProvider, secretClientFactory,
+ isCredentialConfigured, maxRetryTime);
+ }
+
+ private static AppConfigurationReplicaClientFactory buildClientFactory(
+ AppConfigurationReplicaClientsBuilder clientBuilder, AppConfigurationProperties properties,
+ ReplicaLookUp replicaLookup) {
+ return new AppConfigurationReplicaClientFactory(clientBuilder, properties.getStores(), replicaLookup);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static AppConfigurationReplicaClientsBuilder replicaClientBuilder(ConfigDataLocationResolverContext context,
+ Binder binder, AppConfigurationKeyVaultClientFactory keyVaultClientFactory,
+ AzureAppConfigurationProperties properties, boolean isCredentialConfigured, Integer maxRetries) {
+
+ InstanceSupplier> customizer = context
+ .getBootstrapContext()
+ .getRegisteredInstanceSupplier(
+ (Class>) (Class>) AzureServiceClientBuilderCustomizer.class);
+ ConfigurationClientBuilderFactory clientFactory = context.getBootstrapContext()
+ .getOrElseSupply(ConfigurationClientBuilderFactory.class, () -> {
+ ConfigurationClientBuilderFactory factory = new ConfigurationClientBuilderFactory(properties);
+ factory.setSpringIdentifier(AzureSpringIdentifier.AZURE_SPRING_APP_CONFIG);
+ if (customizer != null) {
+ factory.addBuilderCustomizer(customizer.get(context.getBootstrapContext()));
+ }
+ return factory;
+ });
+ if (customizer != null) {
+ clientFactory.addBuilderCustomizer(customizer.get(context.getBootstrapContext()));
+ }
+
+ InstanceSupplier configurationClientCustomizer = context
+ .getBootstrapContext()
+ .getRegisteredInstanceSupplier(
+ (Class) (Class>) ConfigurationClientCustomizer.class);
+
+ ConfigurationClientCustomizer clientCustomizer = null;
+ if (configurationClientCustomizer != null) {
+ clientCustomizer = configurationClientCustomizer.get(context.getBootstrapContext());
+ }
+
+ return new AppConfigurationReplicaClientsBuilder(maxRetries, clientFactory, clientCustomizer,
+ isCredentialConfigured, keyVaultClientFactory.isConfigured());
+ }
+
+ private static boolean isCredentialConfigured(AbstractAzureHttpConfigurationProperties properties) {
+ if (properties.getCredential() != null) {
+ TokenCredentialConfigurationProperties tokenProps = properties.getCredential();
+ if (StringUtils.hasText(tokenProps.getClientCertificatePassword())) {
+ return true;
+ } else if (StringUtils.hasText(tokenProps.getClientCertificatePath())) {
+ return true;
+ } else if (StringUtils.hasText(tokenProps.getClientId())) {
+ return true;
+ } else if (StringUtils.hasText(tokenProps.getClientSecret())) {
+ return true;
+ } else if (StringUtils.hasText(tokenProps.getUsername())) {
+ return true;
+ } else if (StringUtils.hasText(tokenProps.getPassword())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AzureAppConfigDataLoader.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AzureAppConfigDataLoader.java
new file mode 100644
index 000000000000..72c1e03c3a3f
--- /dev/null
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AzureAppConfigDataLoader.java
@@ -0,0 +1,199 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.spring.cloud.appconfiguration.config.implementation;
+
+import java.io.IOException;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.springframework.boot.BootstrapRegistry.InstanceSupplier;
+import org.springframework.boot.context.config.ConfigData;
+import org.springframework.boot.context.config.ConfigDataLoader;
+import org.springframework.boot.context.config.ConfigDataLoaderContext;
+import org.springframework.boot.context.config.ConfigDataResourceNotFoundException;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.logging.DeferredLog;
+import org.springframework.boot.logging.DeferredLogFactory;
+import org.springframework.core.env.EnumerablePropertySource;
+import org.springframework.util.StringUtils;
+
+import com.azure.data.appconfiguration.models.ConfigurationSetting;
+import com.azure.spring.cloud.appconfiguration.config.implementation.feature.FeatureFlags;
+import com.azure.spring.cloud.appconfiguration.config.implementation.properties.AppConfigurationKeyValueSelector;
+import com.azure.spring.cloud.appconfiguration.config.implementation.properties.AppConfigurationProviderProperties;
+import com.azure.spring.cloud.appconfiguration.config.implementation.properties.AppConfigurationStoreMonitoring;
+import com.azure.spring.cloud.appconfiguration.config.implementation.properties.FeatureFlagKeyValueSelector;
+
+@EnableConfigurationProperties(AppConfigurationProviderProperties.class)
+public class AzureAppConfigDataLoader implements ConfigDataLoader {
+
+ private static Log logger = new DeferredLog();
+
+ private AzureAppConfigDataResource resource;
+
+ private AppConfigurationReplicaClientFactory replicaClientFactory;
+
+ private AppConfigurationKeyVaultClientFactory keyVaultClientFactory;
+
+ private StateHolder storeState = new StateHolder();
+
+ private FeatureFlagClient featureFlagClient;
+
+ public AzureAppConfigDataLoader(DeferredLogFactory logFactory) {
+ logger = logFactory.getLog(getClass());
+ }
+
+ @Override
+ public ConfigData load(ConfigDataLoaderContext context, AzureAppConfigDataResource resource)
+ throws IOException, ConfigDataResourceNotFoundException {
+ this.resource = resource;
+ storeState.setNextForcedRefresh(resource.getRefreshInterval());
+
+ if (context.getBootstrapContext().isRegistered(FeatureFlagClient.class)) {
+ this.featureFlagClient = context.getBootstrapContext().get(FeatureFlagClient.class);
+ } else {
+ this.featureFlagClient = new FeatureFlagClient();
+ context.getBootstrapContext().registerIfAbsent(FeatureFlagClient.class,
+ InstanceSupplier.from(() -> this.featureFlagClient));
+ }
+
+ List> sourceList = new ArrayList<>();
+
+ if (resource.isConfigStoreEnabled()) {
+ replicaClientFactory = context.getBootstrapContext()
+ .get(AppConfigurationReplicaClientFactory.class);
+ keyVaultClientFactory = context.getBootstrapContext()
+ .get(AppConfigurationKeyVaultClientFactory.class);
+
+ List clients = replicaClientFactory
+ .getAvailableClients(resource.getEndpoint(), true);
+
+ boolean reloadFailed = false;
+
+ // Feature Management needs to be set in the last config store.
+
+ for (AppConfigurationReplicaClient client : clients) {
+ sourceList = new ArrayList<>();
+
+ if (reloadFailed
+ && !AppConfigurationRefreshUtil.refreshStoreCheck(client,
+ replicaClientFactory.findOriginForEndpoint(client.getEndpoint()))) {
+ // This store doesn't have any changes where to refresh store did. Skipping Checking next.
+ continue;
+ }
+
+ // Reverse in order to add Profile specific properties earlier, and last profile comes first
+ try {
+ sourceList.addAll(createSettings(client));
+ List featureFlags = createFeatureFlags(client);
+
+ logger.debug("PropertySource context.");
+ AppConfigurationStoreMonitoring monitoring = resource.getMonitoring();
+
+ storeState.setStateFeatureFlag(resource.getEndpoint(), featureFlags,
+ monitoring.getFeatureFlagRefreshInterval());
+
+ if (monitoring.isEnabled()) {
+ // Setting new ETag values for Watch
+ List watchKeysSettings = monitoring.getTriggers().stream()
+ .map(trigger -> client.getWatchKey(trigger.getKey(), trigger.getLabel(),
+ resource.isRefresh()))
+ .toList();
+
+ storeState.setState(resource.getEndpoint(), watchKeysSettings, monitoring.getRefreshInterval());
+ }
+ storeState.setLoadState(resource.getEndpoint(), true);
+ } catch (AppConfigurationStatusException e) {
+ reloadFailed = true;
+ replicaClientFactory.backoffClientClient(resource.getEndpoint(), client.getEndpoint());
+ } catch (Exception e) {
+ failedToGeneratePropertySource(e);
+
+ // Not a retiable error
+ break;
+ }
+ if (sourceList.size() > 0) {
+ break;
+ }
+ }
+ }
+
+ StateHolder.updateState(storeState);
+ sourceList.add(new AppConfigurationFeatureManagementPropertySource(featureFlagClient));
+ return new ConfigData(sourceList);
+ }
+
+ private void failedToGeneratePropertySource(Exception e) {
+ logger.error("Fail fast is set and there was an error reading configuration from Azure App "
+ + "Configuration store " + resource.getEndpoint() + ".");
+ delayException();
+ throw new RuntimeException("Failed to generate property sources for " + resource.getEndpoint(), e);
+ }
+
+ /**
+ * Creates a new set of AppConfigurationPropertySources, 1 per Label.
+ *
+ * @param client client for connecting to App Configuration
+ * @return a list of AppConfigurationPropertySources
+ * @throws Exception creating a property source failed
+ */
+ private List createSettings(AppConfigurationReplicaClient client)
+ throws Exception {
+ List sourceList = new ArrayList<>();
+ List selects = resource.getSelects();
+ List profiles = resource.getProfiles().getActive();
+
+ for (AppConfigurationKeyValueSelector selectedKeys : selects) {
+ AppConfigurationPropertySource propertySource = null;
+
+ if (StringUtils.hasText(selectedKeys.getSnapshotName())) {
+ propertySource = new AppConfigurationSnapshotPropertySource(
+ selectedKeys.getSnapshotName() + "/" + resource.getEndpoint(), client, keyVaultClientFactory,
+ selectedKeys.getSnapshotName(), featureFlagClient);
+ } else {
+ propertySource = new AppConfigurationApplicationSettingPropertySource(
+ selectedKeys.getKeyFilter() + resource.getEndpoint() + "/", client, keyVaultClientFactory,
+ selectedKeys.getKeyFilter(), selectedKeys.getLabelFilter(profiles));
+ }
+ propertySource.initProperties(resource.getTrimKeyPrefix(), resource.isRefresh());
+ sourceList.add(propertySource);
+ }
+ return sourceList;
+ }
+
+ /**
+ * Creates a new set of AppConfigurationPropertySources, 1 per Label.
+ *
+ * @param client client for connecting to App Configuration
+ * @return a list of AppConfigurationPropertySources
+ * @throws Exception creating a property source failed
+ */
+ private List createFeatureFlags(AppConfigurationReplicaClient client)
+ throws Exception {
+ List featureFlagWatchKeys = new ArrayList<>();
+ List profiles = resource.getProfiles().getActive();
+ for (FeatureFlagKeyValueSelector selectedKeys : resource.getFeatureFlagSelects()) {
+ List storesFeatureFlags = featureFlagClient.loadFeatureFlags(client,
+ selectedKeys.getKeyFilter(), selectedKeys.getLabelFilter(profiles), resource.isRefresh());
+ featureFlagWatchKeys.addAll(storesFeatureFlags);
+ }
+
+ return featureFlagWatchKeys;
+ }
+
+ private void delayException() {
+ Instant currentDate = Instant.now();
+ Instant preKillTIme = resource.getAppProperties().getStartDate()
+ .plusSeconds(resource.getAppProperties().getPrekillTime());
+ if (currentDate.isBefore(preKillTIme)) {
+ long diffInMillies = Math.abs(preKillTIme.toEpochMilli() - currentDate.toEpochMilli());
+ try {
+ Thread.sleep(diffInMillies);
+ } catch (InterruptedException e) {
+ logger.error("Failed to wait before fast fail.");
+ }
+ }
+ }
+}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AzureAppConfigDataLocationResolver.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AzureAppConfigDataLocationResolver.java
new file mode 100644
index 000000000000..77ec7057d854
--- /dev/null
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AzureAppConfigDataLocationResolver.java
@@ -0,0 +1,129 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.spring.cloud.appconfiguration.config.implementation;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.naming.NamingException;
+
+import org.apache.commons.logging.Log;
+import org.springframework.beans.BeanUtils;
+import org.springframework.boot.BootstrapRegistry.InstanceSupplier;
+import org.springframework.boot.context.config.ConfigDataLocation;
+import org.springframework.boot.context.config.ConfigDataLocationNotFoundException;
+import org.springframework.boot.context.config.ConfigDataLocationResolver;
+import org.springframework.boot.context.config.ConfigDataLocationResolverContext;
+import org.springframework.boot.context.config.ConfigDataResourceNotFoundException;
+import org.springframework.boot.context.config.Profiles;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.context.properties.bind.BindHandler;
+import org.springframework.boot.context.properties.bind.Bindable;
+import org.springframework.boot.context.properties.bind.Binder;
+import org.springframework.boot.logging.DeferredLog;
+import org.springframework.util.StringUtils;
+
+import com.azure.spring.cloud.appconfiguration.config.implementation.autofailover.ReplicaLookUp;
+import com.azure.spring.cloud.appconfiguration.config.implementation.properties.AppConfigurationProperties;
+import com.azure.spring.cloud.appconfiguration.config.implementation.properties.AppConfigurationProviderProperties;
+import com.azure.spring.cloud.appconfiguration.config.implementation.properties.ConfigStore;
+
+@EnableConfigurationProperties(AppConfigurationProviderProperties.class)
+public class AzureAppConfigDataLocationResolver
+ implements ConfigDataLocationResolver {
+
+ private static final Log LOGGER = new DeferredLog();
+
+ public static final String PREFIX = "azureAppConfiguration";
+
+ private static final AtomicBoolean START_UP = new AtomicBoolean(true);
+
+ @Override
+ public boolean isResolvable(ConfigDataLocationResolverContext context, ConfigDataLocation location) {
+ if (!location.hasPrefix(PREFIX)) {
+ return false;
+ }
+ Boolean hasEndpoint = StringUtils.hasText(context.getBinder()
+ .bind(AppConfigurationProperties.CONFIG_PREFIX + ".stores[0].endpoint", String.class)
+ .orElse(""));
+ Boolean hasConnectionString = StringUtils.hasText(context.getBinder()
+ .bind(AppConfigurationProperties.CONFIG_PREFIX + ".stores[0].connection-string", String.class)
+ .orElse(""));
+ Boolean hasEndpoints = StringUtils.hasText(context.getBinder()
+ .bind(AppConfigurationProperties.CONFIG_PREFIX + ".stores[0].endpoints", String.class)
+ .orElse(""));
+ Boolean hasConnectionStrings = StringUtils.hasText(context.getBinder()
+ .bind(AppConfigurationProperties.CONFIG_PREFIX + ".stores[0].connection-strings", String.class)
+ .orElse(""));
+
+ return (hasEndpoint || hasConnectionString || hasEndpoints || hasConnectionStrings);
+ }
+
+ @Override
+ public List resolve(ConfigDataLocationResolverContext context,
+ ConfigDataLocation location)
+ throws ConfigDataLocationNotFoundException, ConfigDataResourceNotFoundException {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List resolveProfileSpecific(
+ ConfigDataLocationResolverContext resolverContext, ConfigDataLocation location, Profiles profiles)
+ throws ConfigDataLocationNotFoundException {
+
+ Holder holder = loadProperties(resolverContext);
+ List locations = new ArrayList<>();
+
+ for (ConfigStore store : holder.properties.getStores()) {
+ locations.add(
+ new AzureAppConfigDataResource(store, profiles, holder.appProperties, START_UP.get(),
+ holder.properties.getRefreshInterval()));
+ }
+ START_UP.set(false);
+ return locations;
+ }
+
+ protected Holder loadProperties(ConfigDataLocationResolverContext context) {
+ Binder binder = context.getBinder();
+ BindHandler bindHandler = getBindHandler(context);
+ AppConfigurationProperties properties;
+ AppConfigurationProviderProperties appProperties;
+ Holder holder = new Holder();
+
+ properties = binder.bind(AppConfigurationProperties.CONFIG_PREFIX,
+ Bindable.of(AppConfigurationProperties.class), bindHandler).get();
+
+ appProperties = binder.bind(AppConfigurationProviderProperties.CONFIG_PREFIX,
+ Bindable.of(AppConfigurationProviderProperties.class), bindHandler)
+ .orElseGet(AppConfigurationProviderProperties::new);
+
+ properties.validateAndInit();
+ ReplicaLookUp replicaLookup = null;
+ try {
+ replicaLookup = new ReplicaLookUp(properties);
+ context.getBootstrapContext().registerIfAbsent(ReplicaLookUp.class, InstanceSupplier.of(replicaLookup));
+ } catch (NamingException e) {
+ LOGGER.info("Failed to find DNS Entry for config store while looking for replicas.");
+ }
+
+ AzureAppConfigurationBootstrapRegistrar.register(context, binder, properties, appProperties, replicaLookup);
+
+ holder.properties = properties;
+ holder.appProperties = appProperties;
+
+ return holder;
+ }
+
+ private BindHandler getBindHandler(ConfigDataLocationResolverContext context) {
+ return context.getBootstrapContext().getOrElse(BindHandler.class, null);
+ }
+
+ private class Holder {
+ AppConfigurationProperties properties;
+
+ AppConfigurationProviderProperties appProperties;
+ }
+
+}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AzureAppConfigDataResource.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AzureAppConfigDataResource.java
new file mode 100644
index 000000000000..13f5f1a87ad8
--- /dev/null
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AzureAppConfigDataResource.java
@@ -0,0 +1,152 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.spring.cloud.appconfiguration.config.implementation;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.boot.context.config.ConfigDataResource;
+import org.springframework.boot.context.config.Profiles;
+
+import com.azure.spring.cloud.appconfiguration.config.implementation.properties.AppConfigurationKeyValueSelector;
+import com.azure.spring.cloud.appconfiguration.config.implementation.properties.AppConfigurationProviderProperties;
+import com.azure.spring.cloud.appconfiguration.config.implementation.properties.AppConfigurationStoreMonitoring;
+import com.azure.spring.cloud.appconfiguration.config.implementation.properties.ConfigStore;
+import com.azure.spring.cloud.appconfiguration.config.implementation.properties.FeatureFlagKeyValueSelector;
+
+public class AzureAppConfigDataResource extends ConfigDataResource {
+
+ private final boolean configStoreEnabled;
+
+ private final String endpoint;
+
+ private List trimKeyPrefix;
+
+ private final Profiles profiles;
+
+ private List selects = new ArrayList<>();
+
+ private List featureFlagSelects = new ArrayList<>();
+
+ private final AppConfigurationStoreMonitoring monitoring;
+
+ private final AppConfigurationProviderProperties appProperties;
+
+ private final boolean isRefresh;
+
+ private Duration refreshInterval;
+
+ AzureAppConfigDataResource(ConfigStore configStore, Profiles profiles,
+ AppConfigurationProviderProperties appProperties, boolean isRefresh, Duration refreshInterval) {
+ this.configStoreEnabled = configStore.isEnabled();
+ this.endpoint = configStore.getEndpoint();
+ this.selects = configStore.getSelects();
+ this.featureFlagSelects = configStore.getFeatureFlags().getSelects();
+ this.trimKeyPrefix = configStore.getTrimKeyPrefix();
+ this.monitoring = configStore.getMonitoring();
+ this.profiles = profiles;
+ this.appProperties = appProperties;
+ this.isRefresh = isRefresh;
+ this.refreshInterval = refreshInterval;
+ }
+
+ /**
+ * @return the selects
+ */
+ public List getSelects() {
+ return selects;
+ }
+
+ /**
+ * @param selects the selects to set
+ */
+ public void setSelects(List selects) {
+ this.selects = selects;
+ }
+
+ /**
+ * @return the selects for feature flags
+ */
+ public List getFeatureFlagSelects() {
+ return featureFlagSelects;
+ }
+
+ /**
+ * @param featureFlagSelects the selects to set
+ */
+ public void setFeatureFlagSelects(List featureFlagSelects) {
+ this.featureFlagSelects = featureFlagSelects;
+ }
+
+ /**
+ * @return the configStoreEnabled
+ */
+ public boolean isConfigStoreEnabled() {
+ return configStoreEnabled;
+ }
+
+ /**
+ * @return the endpoint
+ */
+ public String getEndpoint() {
+ return endpoint;
+ }
+
+ /**
+ * @return the monitoring
+ */
+ public AppConfigurationStoreMonitoring getMonitoring() {
+ return monitoring;
+ }
+
+ /**
+ * @return the trimKeyPrefix
+ */
+ public List getTrimKeyPrefix() {
+ return trimKeyPrefix;
+ }
+
+ /**
+ * @param trimKeyPrefix the trimKeyPrefix to set
+ */
+ public void setTrimKeyPrefix(List trimKeyPrefix) {
+ this.trimKeyPrefix = trimKeyPrefix;
+ }
+
+ /**
+ * @return the profiles
+ */
+ public Profiles getProfiles() {
+ return profiles;
+ }
+
+ /**
+ * @return the isRefresh
+ */
+ public boolean isRefresh() {
+ return isRefresh;
+ }
+
+ /**
+ * @return the appProperties
+ */
+ public AppConfigurationProviderProperties getAppProperties() {
+ return appProperties;
+ }
+
+ /**
+ * @return the refreshInterval
+ */
+ public Duration getRefreshInterval() {
+ return refreshInterval;
+ }
+
+ /**
+ * @param refreshInterval the refreshInterval to set
+ */
+ public void setRefreshInterval(Duration refreshInterval) {
+ this.refreshInterval = refreshInterval;
+ }
+
+}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/ConnectionManager.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/ConnectionManager.java
index 16c6d2d05fdc..17124ea72904 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/ConnectionManager.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/ConnectionManager.java
@@ -7,7 +7,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -21,7 +20,7 @@
/**
* Holds a set of connections to an app configuration store with zero to many geo-replications.
*/
-public class ConnectionManager {
+class ConnectionManager {
private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionManager.class);
@@ -143,13 +142,6 @@ List getAvailableClients(Boolean useCurrent) {
return availableClients;
}
- List getAllEndpoints() {
- List endpoints = clients.stream().map(AppConfigurationReplicaClient::getEndpoint)
- .collect(Collectors.toList());
- endpoints.addAll(replicaLookUp.getAutoFailoverEndpoints(configStore.getEndpoint()));
- return endpoints;
- }
-
/**
* Call when the current client failed
* @param endpoint replica endpoint
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/FeatureFlagClient.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/FeatureFlagClient.java
index 956454d616ca..474f0fda49f0 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/FeatureFlagClient.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/FeatureFlagClient.java
@@ -14,6 +14,8 @@
import static com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationConstants.TELEMETRY;
import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -21,7 +23,6 @@
import java.util.List;
import java.util.Map;
-import org.bouncycastle.jcajce.provider.digest.SHA256;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
@@ -43,9 +44,9 @@
* take priority.
*/
@Component
-public class FeatureFlagClient {
+class FeatureFlagClient {
- protected final Map properties = new LinkedHashMap<>();
+ private final Map properties = new LinkedHashMap<>();
private static final ObjectMapper CASE_INSENSITIVE_MAPPER = JsonMapper.builder()
.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true).build();
@@ -62,7 +63,7 @@ public class FeatureFlagClient {
*
*
*/
- public List loadFeatureFlags(AppConfigurationReplicaClient replicaClient, String customKeyFilter,
+ List loadFeatureFlags(AppConfigurationReplicaClient replicaClient, String customKeyFilter,
String[] labelFilter, boolean isRefresh) {
List loadedFeatureFlags = new ArrayList<>();
@@ -84,7 +85,7 @@ public List loadFeatureFlags(AppConfigurationReplicaClient replica
return loadedFeatureFlags;
}
- public List proccessFeatureFlags(FeatureFlags features, String endpoint) {
+ List proccessFeatureFlags(FeatureFlags features, String endpoint) {
List loadedFeatureFlags = new ArrayList<>();
loadedFeatureFlags.add(features);
@@ -151,11 +152,15 @@ protected static Feature createFeature(FeatureFlagConfigurationSetting item, Str
*/
private static String calculateFeatureFlagId(String key, String label) {
final String data = String.format("%s\n%s", key, label.isEmpty() ? null : label);
- final SHA256.Digest digest = new SHA256.Digest();
- final String beforeTrim = Base64URL.encode(digest.digest(data.getBytes(StandardCharsets.UTF_8)))
- .toString().replace('+', '-').replace('/', '_');
- final int index = beforeTrim.indexOf('=');
- return beforeTrim.substring(0, index > -1 ? index : beforeTrim.length());
+ try {
+ MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
+ final String beforeTrim = Base64URL.encode(sha256.digest(data.getBytes(StandardCharsets.UTF_8)))
+ .toString().replace('+', '-').replace('/', '_');
+ final int index = beforeTrim.indexOf('=');
+ return beforeTrim.substring(0, index > -1 ? index : beforeTrim.length());
+ } catch (NoSuchAlgorithmException e) {
+ }
+ return "";
}
/**
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/NormalizeNull.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/NormalizeNull.java
index 8463930ba1c9..3ae7ac5f267b 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/NormalizeNull.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/NormalizeNull.java
@@ -9,7 +9,7 @@
* configurations with any label.
*
*/
-public class NormalizeNull {
+class NormalizeNull {
private static final String EMPTY_LABEL = "\0";
@@ -19,7 +19,7 @@ public class NormalizeNull {
* @param setting ConfigurationSetting
* @return ConfigurationSetting with label corrected from null to \0
*/
- public static ConfigurationSetting normalizeNullLabel(ConfigurationSetting setting) {
+ static ConfigurationSetting normalizeNullLabel(ConfigurationSetting setting) {
return setting.getLabel() == null ? setting.setLabel(EMPTY_LABEL) : setting;
}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/StateHolder.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/StateHolder.java
index 9de8f3d08228..817ee27d1c6c 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/StateHolder.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/StateHolder.java
@@ -132,14 +132,9 @@ Map getLoadState() {
/**
* @param originEndpoint the configuration store connected to.
* @param loaded true if the configuration store was loaded.
- * @param failFast application started after it failed to load from a store.
*/
- void setLoadState(String originEndpoint, Boolean loaded, Boolean failFast) {
- if (loaded || !failFast) {
- loadState.put(originEndpoint, true);
- } else {
- loadState.put(originEndpoint, false);
- }
+ void setLoadState(String originEndpoint, Boolean loaded) {
+ loadState.put(originEndpoint, loaded);
}
/**
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/autofailover/SRVRecord.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/autofailover/SRVRecord.java
index 9646b83527d9..7b7e9c1225f2 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/autofailover/SRVRecord.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/autofailover/SRVRecord.java
@@ -2,7 +2,7 @@
// Licensed under the MIT License.
package com.azure.spring.cloud.appconfiguration.config.implementation.autofailover;
-public class SRVRecord {
+class SRVRecord {
private final int priority;
@@ -14,7 +14,7 @@ public class SRVRecord {
private static final String PROTOCAL = "https://";
- public SRVRecord(String[] record) {
+ SRVRecord(String[] record) {
this.priority = Integer.valueOf(record[0]);
this.weight = Integer.valueOf(record[1]);
this.port = Integer.valueOf(record[2]);
@@ -41,7 +41,7 @@ public String getEndpoint() {
return PROTOCAL + target;
}
- public int compareTo(SRVRecord record) {
+ int compareTo(SRVRecord record) {
if (priority > record.getPriority()) {
return 1;
}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/config/AppConfigurationBootstrapConfiguration.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/config/AppConfigurationBootstrapConfiguration.java
deleted file mode 100644
index 2573d3abf766..000000000000
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/config/AppConfigurationBootstrapConfiguration.java
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-package com.azure.spring.cloud.appconfiguration.config.implementation.config;
-
-import javax.naming.NamingException;
-
-import org.springframework.beans.factory.ObjectProvider;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.boot.context.properties.bind.Binder;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.PropertySource;
-import org.springframework.core.env.Environment;
-import org.springframework.scheduling.annotation.EnableAsync;
-import org.springframework.util.StringUtils;
-
-import com.azure.data.appconfiguration.ConfigurationClientBuilder;
-import com.azure.spring.cloud.appconfiguration.config.ConfigurationClientCustomizer;
-import com.azure.spring.cloud.appconfiguration.config.KeyVaultSecretProvider;
-import com.azure.spring.cloud.appconfiguration.config.SecretClientCustomizer;
-import com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationKeyVaultClientFactory;
-import com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationPropertySourceLocator;
-import com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationReplicaClientFactory;
-import com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationReplicaClientsBuilder;
-import com.azure.spring.cloud.appconfiguration.config.implementation.FeatureFlagClient;
-import com.azure.spring.cloud.appconfiguration.config.implementation.autofailover.ReplicaLookUp;
-import com.azure.spring.cloud.appconfiguration.config.implementation.properties.AppConfigurationProperties;
-import com.azure.spring.cloud.appconfiguration.config.implementation.properties.AppConfigurationProviderProperties;
-import com.azure.spring.cloud.autoconfigure.implementation.appconfiguration.AzureAppConfigurationProperties;
-import com.azure.spring.cloud.autoconfigure.implementation.context.properties.AzureGlobalProperties;
-import com.azure.spring.cloud.autoconfigure.implementation.keyvault.secrets.properties.AzureKeyVaultSecretProperties;
-import com.azure.spring.cloud.autoconfigure.implementation.properties.core.AbstractAzureHttpConfigurationProperties;
-import com.azure.spring.cloud.autoconfigure.implementation.properties.core.authentication.TokenCredentialConfigurationProperties;
-import com.azure.spring.cloud.autoconfigure.implementation.properties.utils.AzureGlobalPropertiesUtils;
-import com.azure.spring.cloud.core.customizer.AzureServiceClientBuilderCustomizer;
-import com.azure.spring.cloud.core.implementation.util.AzurePropertiesUtils;
-import com.azure.spring.cloud.core.implementation.util.AzureSpringIdentifier;
-import com.azure.spring.cloud.service.implementation.appconfiguration.ConfigurationClientBuilderFactory;
-import com.azure.spring.cloud.service.implementation.keyvault.secrets.SecretClientBuilderFactory;
-
-/**
- * Setup ConnectionPool, AppConfigurationPropertySourceLocator, and ClientStore when
- * spring.cloud.azure.appconfiguration.enabled is enabled.
- */
-@Configuration
-@PropertySource("classpath:appConfiguration.properties")
-@EnableConfigurationProperties({ AppConfigurationProperties.class, AppConfigurationProviderProperties.class })
-@ConditionalOnClass(AppConfigurationPropertySourceLocator.class)
-@ConditionalOnProperty(prefix = AppConfigurationProperties.CONFIG_PREFIX, name = "enabled", matchIfMissing = true)
-@EnableAsync
-public class AppConfigurationBootstrapConfiguration {
-
- @Autowired
- private transient ApplicationContext context;
-
- @Bean
- AppConfigurationPropertySourceLocator sourceLocator(AppConfigurationProperties properties,
- AppConfigurationProviderProperties appProperties, AppConfigurationReplicaClientFactory clientFactory,
- AppConfigurationKeyVaultClientFactory keyVaultClientFactory, ReplicaLookUp replicaLookUp,
- FeatureFlagClient featureFlagLoader)
- throws IllegalArgumentException {
-
- return new AppConfigurationPropertySourceLocator(appProperties, clientFactory, keyVaultClientFactory,
- properties.getRefreshInterval(), properties.getStores(), replicaLookUp, featureFlagLoader);
- }
-
- @Bean
- AppConfigurationKeyVaultClientFactory appConfigurationKeyVaultClientFactory(Environment environment,
- AppConfigurationProviderProperties appProperties)
- throws IllegalArgumentException {
- AzureGlobalProperties globalSource = Binder.get(environment).bindOrCreate(AzureGlobalProperties.PREFIX,
- AzureGlobalProperties.class);
- AzureGlobalProperties serviceSource = Binder.get(environment).bindOrCreate(AzureKeyVaultSecretProperties.PREFIX,
- AzureGlobalProperties.class);
-
- AzureKeyVaultSecretProperties globalProperties = AzureGlobalPropertiesUtils.loadProperties(
- globalSource,
- new AzureKeyVaultSecretProperties());
- AzureKeyVaultSecretProperties clientProperties = AzureGlobalPropertiesUtils.loadProperties(serviceSource,
- new AzureKeyVaultSecretProperties());
-
- AzurePropertiesUtils.copyAzureCommonPropertiesIgnoreNull(globalProperties, clientProperties);
-
- SecretClientCustomizer keyVaultClientProvider = context.getBeanProvider(SecretClientCustomizer.class)
- .getIfAvailable();
- KeyVaultSecretProvider keyVaultSecretProvider = context.getBeanProvider(KeyVaultSecretProvider.class)
- .getIfAvailable();
-
- SecretClientBuilderFactory secretClientBuilderFactory = new SecretClientBuilderFactory(clientProperties);
-
- boolean credentialConfigured = isCredentialConfigured(clientProperties);
-
- return new AppConfigurationKeyVaultClientFactory(keyVaultClientProvider, keyVaultSecretProvider,
- secretClientBuilderFactory, credentialConfigured, appProperties.getMaxRetryTime());
- }
-
- /**
- * Factory for working with App Configuration Clients
- *
- * @param clientBuilder Builder for configuration clients
- * @param properties Client configurations for setting up connections to each config store.
- * @return AppConfigurationReplicaClientFactory
- */
- @Bean
- @ConditionalOnMissingBean
- AppConfigurationReplicaClientFactory buildClientFactory(AppConfigurationReplicaClientsBuilder clientBuilder,
- AppConfigurationProperties properties, ReplicaLookUp replicaLookUp) {
- return new AppConfigurationReplicaClientFactory(clientBuilder, properties.getStores(), replicaLookUp);
- }
-
- /**
- * Loader for all feature flags. Enables de-duplicating of feature flags when multiple feature flags with the same
- * name are loaded.
- * @return {@link FeatureFlagClient}
- */
- @Bean
- @ConditionalOnMissingBean
- FeatureFlagClient featureFlagLoader() {
- return new FeatureFlagClient();
- }
-
- /**
- * Builder for clients connecting to App Configuration.
- *
- * @param clientProperties AzureAppConfigurationProperties Spring Cloud Azure global properties.
- * @param appProperties Library configurations for setting up connections to each config store.
- * @param keyVaultClientFactory used for tracing info for if key vault has been configured
- * @param customizers Client Customizers for connecting to Azure App Configuration
- * @return ClientStore
- */
- @Bean
- @ConditionalOnMissingBean
- AppConfigurationReplicaClientsBuilder replicaClientBuilder(Environment environment,
- AppConfigurationProviderProperties appProperties, AppConfigurationKeyVaultClientFactory keyVaultClientFactory,
- ObjectProvider> customizers) {
- AzureGlobalProperties globalSource = Binder.get(environment).bindOrCreate(AzureGlobalProperties.PREFIX,
- AzureGlobalProperties.class);
- AzureGlobalProperties serviceSource = Binder.get(environment).bindOrCreate(
- AzureAppConfigurationProperties.PREFIX,
- AzureGlobalProperties.class);
-
- AzureGlobalProperties globalProperties = AzureGlobalPropertiesUtils.loadProperties(globalSource,
- new AzureGlobalProperties());
- AzureAppConfigurationProperties clientProperties = AzureGlobalPropertiesUtils.loadProperties(serviceSource,
- new AzureAppConfigurationProperties());
-
- AzurePropertiesUtils.copyAzureCommonPropertiesIgnoreNull(globalProperties, clientProperties);
-
- ConfigurationClientBuilderFactory clientFactory = new ConfigurationClientBuilderFactory(clientProperties);
-
- clientFactory.setSpringIdentifier(AzureSpringIdentifier.AZURE_SPRING_APP_CONFIG);
- customizers.orderedStream().forEach(clientFactory::addBuilderCustomizer);
-
- boolean credentialConfigured = isCredentialConfigured(clientProperties);
-
- AppConfigurationReplicaClientsBuilder clientBuilder = new AppConfigurationReplicaClientsBuilder(
- appProperties.getMaxRetries(), clientFactory, credentialConfigured);
-
- clientBuilder
- .setClientProvider(context.getBeanProvider(ConfigurationClientCustomizer.class)
- .getIfAvailable());
-
- clientBuilder.setIsKeyVaultConfigured(keyVaultClientFactory.isConfigured());
-
- return clientBuilder;
- }
-
- @Bean
- ReplicaLookUp replicaLookUp(AppConfigurationProperties properties) throws NamingException {
- return new ReplicaLookUp(properties);
- }
-
- private boolean isCredentialConfigured(AbstractAzureHttpConfigurationProperties properties) {
- if (properties.getCredential() != null) {
- TokenCredentialConfigurationProperties tokenProps = properties.getCredential();
- if (StringUtils.hasText(tokenProps.getClientCertificatePassword())) {
- return true;
- } else if (StringUtils.hasText(tokenProps.getClientCertificatePath())) {
- return true;
- } else if (StringUtils.hasText(tokenProps.getClientId())) {
- return true;
- } else if (StringUtils.hasText(tokenProps.getClientSecret())) {
- return true;
- } else if (StringUtils.hasText(tokenProps.getUsername())) {
- return true;
- } else if (StringUtils.hasText(tokenProps.getPassword())) {
- return true;
- }
- }
-
- return false;
- }
-
-}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/feature/FeatureFlags.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/feature/FeatureFlags.java
index dc725a309000..2a1380a3d907 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/feature/FeatureFlags.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/feature/FeatureFlags.java
@@ -6,7 +6,6 @@
import com.azure.data.appconfiguration.models.ConfigurationSetting;
import com.azure.data.appconfiguration.models.SettingSelector;
-import com.azure.spring.cloud.appconfiguration.config.implementation.properties.ConfigStore;
public class FeatureFlags {
@@ -14,27 +13,11 @@ public class FeatureFlags {
private List featureFlags;
- private ConfigStore configStore;
-
public FeatureFlags(SettingSelector settingSelector, List featureFlags) {
this.settingSelector = settingSelector;
this.featureFlags = featureFlags;
}
- /**
- * @return the configStore
- */
- public ConfigStore getConfigStore() {
- return configStore;
- }
-
- /**
- * @param configStore the configStore to set
- */
- public void setConfigStore(ConfigStore configStore) {
- this.configStore = configStore;
- }
-
/**
* @return the settingSelector
*/
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/feature/entity/Conditions.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/feature/entity/Conditions.java
index d882c0399021..e010edfe7e8f 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/feature/entity/Conditions.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/feature/entity/Conditions.java
@@ -20,7 +20,7 @@ public class Conditions {
@JsonProperty("requirement_type")
private String requirementType = DEFAULT_REQUIREMENT_TYPE;
- public Conditions(List featureFilters, String requirementType) {
+ Conditions(List featureFilters, String requirementType) {
clientFilters = new ArrayList<>();
clientFilters.addAll(featureFilters);
this.requirementType = requirementType;
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/feature/entity/FeatureFilterEvaluationContext.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/feature/entity/FeatureFilterEvaluationContext.java
deleted file mode 100644
index 760284fc57bd..000000000000
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/feature/entity/FeatureFilterEvaluationContext.java
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-package com.azure.spring.cloud.appconfiguration.config.implementation.feature.entity;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-
-/**
- * Context passed into Feature Filters used for evaluation.
- */
-@JsonIgnoreProperties(ignoreUnknown = true)
-public final class FeatureFilterEvaluationContext {
-
- /**
- * Creates an instance of {@link FeatureFilterEvaluationContext}
- */
- public FeatureFilterEvaluationContext() {
- }
-
- private String name;
-
- private Map parameters;
-
- /**
- * Return the name
- * @return the name
- */
- public String getName() {
- return name;
- }
-
- /**
- * Set the name
- * @param name the name to set
- */
- public void setName(String name) {
- this.name = name;
- }
-
- /**
- * Return the parameters
- * @return the parameters
- */
- public Map getParameters() {
- Map params = new HashMap();
- if (parameters != null) {
- params.putAll(parameters);
- }
- return params;
- }
-
- /**
- * Set the parameters
- * @param parameters the parameters to set
- */
- public void setParameters(Map parameters) {
- this.parameters = parameters;
- }
-
-}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/feature/entity/FeatureSet.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/feature/entity/FeatureSet.java
deleted file mode 100644
index 5259f28a3b11..000000000000
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/feature/entity/FeatureSet.java
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-package com.azure.spring.cloud.appconfiguration.config.implementation.feature.entity;
-
-import java.util.HashMap;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-/**
- * Set of Feature Flag Key pairs.
- */
-@JsonIgnoreProperties(ignoreUnknown = true)
-public final class FeatureSet {
-
- @JsonProperty("FeatureManagement")
- private HashMap featureManagement;
-
- /**
- * Returns Map of Feature Flags.
- *
- * @return the featureFlags
- */
- public HashMap getFeatureManagement() {
- return featureManagement;
- }
-
- /**
- * Adds a new Feature Flag.
- *
- * @param key Name of the Feature Flag.
- * @param feature true/false, for on/off feature Flag. {@code Feature} if Feature Filter.
- */
- public void addFeature(String key, Object feature) {
- if (featureManagement == null) {
- featureManagement = new HashMap<>();
- }
- if (feature != null) {
- featureManagement.put(key, feature);
- }
- }
-}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/http/policy/BaseAppConfigurationPolicy.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/http/policy/BaseAppConfigurationPolicy.java
index 0f5db1c2ee38..bd72467aa3f9 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/http/policy/BaseAppConfigurationPolicy.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/http/policy/BaseAppConfigurationPolicy.java
@@ -27,10 +27,10 @@ public final class BaseAppConfigurationPolicy implements HttpPipelinePolicy {
/**
* Format of User Agent
*/
- public static final String USER_AGENT = String.format("%s/%s", StringUtils.replace(PACKAGE_NAME, " ", ""),
+ private static final String USER_AGENT = String.format("%s/%s", StringUtils.replace(PACKAGE_NAME, " ", ""),
BaseAppConfigurationPolicy.class.getPackage().getImplementationVersion());
- final TracingInfo tracingInfo;
+ private final TracingInfo tracingInfo;
/**
* App Configuration Http Pipeline Policy
@@ -40,6 +40,7 @@ public BaseAppConfigurationPolicy(TracingInfo tracingInfo) {
this.tracingInfo = tracingInfo;
}
+
@Override
public Mono process(HttpPipelineCallContext context, HttpPipelineNextPolicy next) {
Boolean watchRequests = (Boolean) context.getData("refresh").orElse(false);
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/http/policy/FeatureFlagTracing.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/http/policy/FeatureFlagTracing.java
index 8a325a4614ce..24b62193cc55 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/http/policy/FeatureFlagTracing.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/http/policy/FeatureFlagTracing.java
@@ -5,7 +5,7 @@
import java.util.Arrays;
import java.util.List;
-public class FeatureFlagTracing {
+class FeatureFlagTracing {
private static final String CUSTOM_FILTER = "CSTM";
@@ -34,18 +34,18 @@ public class FeatureFlagTracing {
private Boolean usesTargetingFilter = false;
- public boolean usesAnyFilter() {
+ boolean usesAnyFilter() {
return usesCustomFilter || usesPercentageFilter || usesTimeWindowFilter || usesTargetingFilter;
}
- public void resetFeatureFilterTelemetry() {
+ void resetFeatureFilterTelemetry() {
usesCustomFilter = false;
usesPercentageFilter = false;
usesTimeWindowFilter = false;
usesTargetingFilter = false;
}
- public void updateFeatureFilterTelemetry(String filterName) {
+ void updateFeatureFilterTelemetry(String filterName) {
if (PERCENTAGE_FILTER_NAMES.stream().anyMatch(name -> name.equalsIgnoreCase(filterName))) {
usesPercentageFilter = true;
} else if (TIME_WINDOW_FILTER_NAMES.stream().anyMatch(name -> name.equalsIgnoreCase(filterName))) {
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/http/policy/TracingInfo.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/http/policy/TracingInfo.java
index e9608eb72db2..5f57b8e9ab78 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/http/policy/TracingInfo.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/http/policy/TracingInfo.java
@@ -2,7 +2,6 @@
// Licensed under the MIT License.
package com.azure.spring.cloud.appconfiguration.config.implementation.http.policy;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationConstants.DEV_ENV_TRACING;
import static com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationConstants.KEY_VAULT_CONFIGURED_TRACING;
import org.springframework.util.StringUtils;
@@ -14,8 +13,6 @@
public class TracingInfo {
- private boolean isDev = false;
-
private boolean isKeyVaultConfigured = false;
private int replicaCount;
@@ -24,17 +21,15 @@ public class TracingInfo {
private final Configuration configuration;
- public TracingInfo(boolean isDev, boolean isKeyVaultConfigured, int replicaCount, Configuration configuration) {
- this.isDev = isDev;
+ public TracingInfo(boolean isKeyVaultConfigured, int replicaCount, Configuration configuration) {
this.isKeyVaultConfigured = isKeyVaultConfigured;
this.replicaCount = replicaCount;
this.featureFlagTracing = new FeatureFlagTracing();
this.configuration = configuration;
}
- public String getValue(boolean watchRequests) {
- String track = configuration
- .get(RequestTracingConstants.REQUEST_TRACING_DISABLED_ENVIRONMENT_VARIABLE.toString());
+ String getValue(boolean watchRequests) {
+ String track = configuration.get(RequestTracingConstants.REQUEST_TRACING_DISABLED_ENVIRONMENT_VARIABLE.toString());
if (track != null && Boolean.valueOf(track)) {
return "";
}
@@ -52,10 +47,6 @@ public String getValue(boolean watchRequests) {
if (!hostType.isEmpty()) {
sb.append(",").append(RequestTracingConstants.HOST_TYPE_KEY).append("=").append(hostType);
}
-
- if (isDev) {
- sb.append(",Env=").append(DEV_ENV_TRACING);
- }
if (isKeyVaultConfigured) {
sb.append(",").append(KEY_VAULT_CONFIGURED_TRACING);
}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/AppConfigurationKeyValueSelector.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/AppConfigurationKeyValueSelector.java
index d6d4baed1efd..3b210621899d 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/AppConfigurationKeyValueSelector.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/AppConfigurationKeyValueSelector.java
@@ -30,7 +30,7 @@ public final class AppConfigurationKeyValueSelector {
/**
* Separator for multiple labels
*/
- public static final String LABEL_SEPARATOR = ",";
+ private static final String LABEL_SEPARATOR = ",";
@NotNull
/**
@@ -129,7 +129,7 @@ public void setSnapshotName(String snapshotName) {
* Validates key-filter and label-filter are valid.
*/
@PostConstruct
- public void validateAndInit() {
+ void validateAndInit() {
Assert.isTrue(!keyFilter.contains("*"), "KeyFilter must not contain asterisk(*)");
if (labelFilter != null) {
Assert.isTrue(!labelFilter.contains("*"), "LabelFilter must not contain asterisk(*)");
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/AppConfigurationStoreMonitoring.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/AppConfigurationStoreMonitoring.java
index 22db1862d354..f90a3a573f12 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/AppConfigurationStoreMonitoring.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/AppConfigurationStoreMonitoring.java
@@ -118,7 +118,7 @@ public void setPushNotification(PushNotification pushNotification) {
* Validates refreshIntervals are at least 1 second, and if enabled triggers are valid.
*/
@PostConstruct
- public void validateAndInit() {
+ void validateAndInit() {
if (enabled) {
Assert.notEmpty(triggers, "Triggers need to be set if refresh is enabled.");
for (AppConfigurationStoreTrigger trigger : triggers) {
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/AppConfigurationStoreTrigger.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/AppConfigurationStoreTrigger.java
index ec69376e1bd7..97499d8b3f23 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/AppConfigurationStoreTrigger.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/AppConfigurationStoreTrigger.java
@@ -58,7 +58,7 @@ public void setLabel(String label) {
* Validates key isn't null
*/
@PostConstruct
- public void validateAndInit() {
+ void validateAndInit() {
Assert.notNull(key, "All Triggers need a key value set.");
}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/ConfigStore.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/ConfigStore.java
index 7444d739770f..0f344b1637a2 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/ConfigStore.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/ConfigStore.java
@@ -53,15 +53,6 @@ public final class ConfigStore {
*/
private List selects = new ArrayList<>();
- /**
- * If true, the application will fail to start if the Config Store cannot be
- * reached. If false, the application will start without the Config Store.
- */
- private boolean failFast = true;
-
- /**
- * Options for retrieving Feature Flags from the Azure Config Service.
- */
private FeatureFlagStore featureFlags = new FeatureFlagStore();
/**
@@ -147,20 +138,6 @@ public void setConnectionStrings(List connectionStrings) {
this.connectionStrings = connectionStrings;
}
- /**
- * @return the failFast
- */
- public boolean isFailFast() {
- return failFast;
- }
-
- /**
- * @param failFast the failFast to set
- */
- public void setFailFast(boolean failFast) {
- this.failFast = failFast;
- }
-
/**
* @return the enabled
*/
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/FeatureFlagKeyValueSelector.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/FeatureFlagKeyValueSelector.java
index b3280178e200..4d1de6b90b11 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/FeatureFlagKeyValueSelector.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/FeatureFlagKeyValueSelector.java
@@ -105,7 +105,7 @@ public FeatureFlagKeyValueSelector setLabelFilter(String labelFilter) {
* Validates key-filter and label-filter are valid.
*/
@PostConstruct
- public void validateAndInit() {
+ void validateAndInit() {
if (labelFilter != null) {
Assert.isTrue(!labelFilter.contains("*"), "LabelFilter must not contain asterisk(*)");
}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/FeatureFlagStore.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/FeatureFlagStore.java
index c7b5e89646f7..18ee7c2f28b3 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/FeatureFlagStore.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/FeatureFlagStore.java
@@ -48,7 +48,7 @@ public void setSelects(List selects) {
}
@PostConstruct
- public void validateAndInit() {
+ void validateAndInit() {
if (enabled && selects.size() == 0) {
selects.add(new FeatureFlagKeyValueSelector());
}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/resources/META-INF/spring.factories b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/resources/META-INF/spring.factories
index 9a76c2325a3c..fb0f411d86c2 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/resources/META-INF/spring.factories
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/resources/META-INF/spring.factories
@@ -1,3 +1,5 @@
-org.springframework.cloud.bootstrap.BootstrapConfiguration=\
-com.azure.spring.cloud.appconfiguration.config.implementation.config.AppConfigurationBootstrapConfiguration
+# ConfigData Location Resolvers
+ org.springframework.boot.context.config.ConfigDataLocationResolver= com.azure.spring.cloud.appconfiguration.config.implementation.AzureAppConfigDataLocationResolver
+ # ConfigData Loaders
+ org.springframework.boot.context.config.ConfigDataLoader= com.azure.spring.cloud.appconfiguration.config.implementation.AzureAppConfigDataLoader
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
index 1b36b907ed1b..0472d30fc7d2 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -1,2 +1 @@
-com.azure.spring.cloud.appconfiguration.config.AppConfigurationAutoConfiguration
-com.azure.spring.cloud.appconfiguration.config.implementation.config.AppConfigurationBootstrapConfiguration
\ No newline at end of file
+com.azure.spring.cloud.appconfiguration.config.AppConfigurationWatchAutoConfiguration
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/resources/appConfiguration.properties b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/resources/appConfiguration.properties
deleted file mode 100644
index 9b90ce63ee85..000000000000
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/resources/appConfiguration.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-spring.cloud.appconfiguration.version=1.0
-spring.cloud.appconfiguration.maxRetries=2
-spring.cloud.appconfiguration.maxRetryTime=60
-spring.cloud.appconfiguration.preKillTime=5
-spring.cloud.appconfiguration.defaultMinBackoff=30
-spring.cloud.appconfiguration.defaultmaxBackoff=600
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationApplicationSettingPropertySourceSnapshotTest.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationApplicationSettingPropertySourceSnapshotTest.java
index bd48c729a109..7ef8af30b518 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationApplicationSettingPropertySourceSnapshotTest.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationApplicationSettingPropertySourceSnapshotTest.java
@@ -128,10 +128,10 @@ public void cleanup() throws Exception {
@Test
public void testPropCanBeInitAndQueried() throws IOException {
when(configurationListMock.iterator()).thenReturn(testItems.iterator()).thenReturn(testItems.iterator());
- when(clientMock.listSettingSnapshot(Mockito.any())).thenReturn(configurationListMock)
+ when(clientMock.listSettingSnapshot(Mockito.any(), Mockito.anyBoolean())).thenReturn(configurationListMock)
.thenReturn(configurationListMock);
- propertySource.initProperties(TRIM);
+ propertySource.initProperties(TRIM, false);
String[] keyNames = propertySource.getPropertyNames();
String[] expectedKeyNames = testItems.stream().map(t -> {
@@ -155,10 +155,10 @@ public void testPropertyNameSlashConvertedToDots() throws IOException {
List settings = new ArrayList<>();
settings.add(slashedProp);
when(configurationListMock.iterator()).thenReturn(settings.iterator()).thenReturn(Collections.emptyIterator());
- when(clientMock.listSettingSnapshot(Mockito.any())).thenReturn(configurationListMock)
+ when(clientMock.listSettingSnapshot(Mockito.any(), Mockito.anyBoolean())).thenReturn(configurationListMock)
.thenReturn(configurationListMock);
- propertySource.initProperties(TRIM);
+ propertySource.initProperties(TRIM, false);
String expectedKeyName = TEST_SLASH_KEY.replace('/', '.');
String[] actualKeyNames = propertySource.getPropertyNames();
@@ -174,9 +174,9 @@ public void initNullValidContentTypeTest() throws IOException {
List items = new ArrayList<>();
items.add(ITEM_NULL);
when(configurationListMock.iterator()).thenReturn(items.iterator()).thenReturn(Collections.emptyIterator());
- when(clientMock.listSettingSnapshot(Mockito.any())).thenReturn(configurationListMock);
+ when(clientMock.listSettingSnapshot(Mockito.any(), Mockito.anyBoolean())).thenReturn(configurationListMock);
- propertySource.initProperties(TRIM);
+ propertySource.initProperties(TRIM, false);
String[] keyNames = propertySource.getPropertyNames();
String[] expectedKeyNames =
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationPropertySourceKeyVaultTest.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationPropertySourceKeyVaultTest.java
index 2833cc92970c..0bc44e5c546c 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationPropertySourceKeyVaultTest.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationPropertySourceKeyVaultTest.java
@@ -2,7 +2,7 @@
// Licensed under the MIT License.
package com.azure.spring.cloud.appconfiguration.config.implementation;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationConstants.KEY_VAULT_CONTENT_TYPE;
+import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.KEY_VAULT_CONTENT_TYPE;
import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_CONN_STRING;
import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_KEY_VAULT_1;
import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_LABEL_VAULT_1;
@@ -146,8 +146,7 @@ public void invalidKeyVaultReferenceParseErrorTest() {
.thenReturn(clientManagerMock);
when(clientManagerMock.getSecret(Mockito.any())).thenThrow(new RuntimeException("Parse Failed"));
- RuntimeException exception = assertThrows(RuntimeException.class,
- () -> propertySource.initProperties(null, false));
+ RuntimeException exception = assertThrows(RuntimeException.class, () -> propertySource.initProperties(null, false));
assertEquals("Parse Failed", exception.getMessage());
}
}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationPropertySourceLocatorTest.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationPropertySourceLocatorTest.java
deleted file mode 100644
index a68ac60e28e6..000000000000
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationPropertySourceLocatorTest.java
+++ /dev/null
@@ -1,568 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-package com.azure.spring.cloud.appconfiguration.config.implementation;
-
-import static com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationConstants.EMPTY_LABEL;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_CONN_STRING;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_CONN_STRING_2;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_STORE_NAME;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_STORE_NAME_2;
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.time.Instant;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.MethodOrderer;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestMethodOrder;
-import org.mockito.Mock;
-import org.mockito.MockedStatic;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.mockito.MockitoSession;
-import org.mockito.quality.Strictness;
-import org.springframework.core.env.CompositePropertySource;
-import org.springframework.core.env.ConfigurableEnvironment;
-import org.springframework.core.env.MutablePropertySources;
-import org.springframework.core.env.PropertySource;
-
-import com.azure.data.appconfiguration.models.FeatureFlagConfigurationSetting;
-import com.azure.spring.cloud.appconfiguration.config.implementation.autofailover.ReplicaLookUp;
-import com.azure.spring.cloud.appconfiguration.config.implementation.feature.entity.Feature;
-import com.azure.spring.cloud.appconfiguration.config.implementation.properties.AppConfigurationKeyValueSelector;
-import com.azure.spring.cloud.appconfiguration.config.implementation.properties.AppConfigurationProperties;
-import com.azure.spring.cloud.appconfiguration.config.implementation.properties.AppConfigurationProviderProperties;
-import com.azure.spring.cloud.appconfiguration.config.implementation.properties.AppConfigurationStoreMonitoring;
-import com.azure.spring.cloud.appconfiguration.config.implementation.properties.AppConfigurationStoreTrigger;
-import com.azure.spring.cloud.appconfiguration.config.implementation.properties.ConfigStore;
-import com.azure.spring.cloud.appconfiguration.config.implementation.properties.FeatureFlagStore;
-
-@TestMethodOrder(MethodOrderer.MethodName.class)
-public class AppConfigurationPropertySourceLocatorTest {
-
- private static final String PROFILE_NAME_1 = "dev";
-
- private static final String PROFILE_NAME_2 = "prod";
-
- private static final String KEY_FILTER = "/foo/";
-
- @Mock
- private ConfigurableEnvironment emptyEnvironment;
-
- @Mock
- private ConfigurableEnvironment devEnvironment;
-
- @Mock
- private ConfigurableEnvironment multiEnvironment;
-
- @Mock
- private AppConfigurationReplicaClientFactory clientFactoryMock;
-
- @Mock
- private AppConfigurationKeyVaultClientFactory keyVaultClientFactory;
-
- @Mock
- private AppConfigurationReplicaClient replicaClientMock;
-
- @Mock
- private FeatureFlagStore featureFlagStoreMock;
-
- @Mock
- private ConfigStore configStoreMockError;
-
- @Mock
- private AppConfigurationProviderProperties appPropertiesMock;
-
- @Mock
- private ReplicaLookUp replicaLookUpMock;
-
- @Mock
- private FeatureFlagClient featureFlagClientMock;
-
- @Mock
- private ConfigStore configStoreMock;
-
- private AppConfigurationPropertySourceLocator locator;
-
- private AppConfigurationProperties properties;
-
- private AppConfigurationProviderProperties appProperties;
-
- private List stores;
-
- private AppConfigurationStoreMonitoring monitoring;
-
- private MutablePropertySources sources = new MutablePropertySources();
-
- private MockitoSession session;
-
- @BeforeEach
- public void setup() {
- session = Mockito.mockitoSession().initMocks(this).strictness(Strictness.STRICT_STUBS).startMocking();
- MockitoAnnotations.openMocks(this);
-
- sources.addFirst(new PropertySource("refreshArgs") {
-
- @Override
- public Object getProperty(String name) {
- return null;
- }
- });
-
- properties = new AppConfigurationProperties();
- properties.setEnabled(true);
- properties.setRefreshInterval(null);
-
- TestUtils.addStore(properties, TEST_STORE_NAME, TEST_CONN_STRING, KEY_FILTER);
-
- monitoring = new AppConfigurationStoreMonitoring();
- monitoring.setEnabled(false);
- AppConfigurationStoreTrigger trigger = new AppConfigurationStoreTrigger();
- trigger.setKey("test");
-
- monitoring.setTriggers(List.of(trigger));
-
- appProperties = new AppConfigurationProviderProperties();
- appProperties.setVersion("1.0");
- appProperties.setMaxRetries(12);
- appProperties.setMaxRetryTime(0);
- appProperties.setDefaultMaxBackoff((long) 600);
- appProperties.setDefaultMinBackoff((long) 30);
-
- properties.getStores().get(0).setFeatureFlags(featureFlagStoreMock);
- properties.getStores().get(0).setMonitoring(monitoring);
- stores = properties.getStores();
- }
-
- @AfterEach
- public void cleanup() throws Exception {
- MockitoAnnotations.openMocks(this).close();
- session.finishMocking();
- AppConfigurationPropertySourceLocator.STARTUP.set(true);
- }
-
- @Test
- public void compositeSourceIsCreated() {
- setupEmptyEnvironment();
- when(featureFlagClientMock.getProperties()).thenReturn(Map.of());
-
- locator = new AppConfigurationPropertySourceLocator(appProperties, clientFactoryMock,
- keyVaultClientFactory, null, stores, replicaLookUpMock, featureFlagClientMock);
-
- try (MockedStatic stateHolderMock = Mockito.mockStatic(StateHolder.class)) {
- stateHolderMock.when(() -> StateHolder.updateState(Mockito.any())).thenReturn(null);
- PropertySource> source = locator.locate(emptyEnvironment);
-
- assertTrue(source instanceof CompositePropertySource);
-
- Collection> sources = ((CompositePropertySource) source).getPropertySources();
-
- String[] expectedSourceNames = new String[] {
- KEY_FILTER + "store1/\0"
- };
- assertEquals(expectedSourceNames.length, sources.size());
- assertArrayEquals((Object[]) expectedSourceNames, sources.stream().map(PropertySource::getName).toArray());
- }
- }
-
- @Test
- public void compositeSourceIsCreatedWithMonitoring() {
- setupEmptyEnvironment();
- when(featureFlagClientMock.getProperties()).thenReturn(Map.of());
-
- String watchKey = "wk1";
- AppConfigurationStoreMonitoring monitoring = new AppConfigurationStoreMonitoring();
- monitoring.setEnabled(true);
-
- AppConfigurationStoreTrigger trigger = new AppConfigurationStoreTrigger();
- trigger.setKey(watchKey);
- trigger.setLabel(EMPTY_LABEL);
- monitoring.setTriggers(List.of(trigger));
-
- properties.getStores().get(0).setMonitoring(monitoring);
-
- when(replicaClientMock.getWatchKey(Mockito.eq(watchKey), Mockito.anyString(), Mockito.anyBoolean()))
- .thenReturn(TestUtils.createItem("", watchKey, "0", EMPTY_LABEL, ""));
-
- locator = new AppConfigurationPropertySourceLocator(appProperties, clientFactoryMock, keyVaultClientFactory,
- null, stores, replicaLookUpMock, featureFlagClientMock);
-
- try (MockedStatic stateHolderMock = Mockito.mockStatic(StateHolder.class)) {
- stateHolderMock.when(() -> StateHolder.updateState(Mockito.any())).thenReturn(null);
- PropertySource> source = locator.locate(emptyEnvironment);
-
- assertTrue(source instanceof CompositePropertySource);
-
- Collection> sources = ((CompositePropertySource) source).getPropertySources();
-
- String[] expectedSourceNames = new String[] {
- KEY_FILTER + "store1/\0"
- };
- assertEquals(expectedSourceNames.length, sources.size());
- assertArrayEquals((Object[]) expectedSourceNames, sources.stream().map(PropertySource::getName).toArray());
- verify(replicaClientMock, times(1)).getWatchKey(Mockito.eq(watchKey), Mockito.anyString(),
- Mockito.anyBoolean());
- }
- }
-
- @Test
- public void compositeSourceIsCreatedWithMonitoringWatchKeyDoesNotExist() {
- // The listed Watch Key doesn't have a value in app config. When one is added will cause a refresh.
- setupEmptyEnvironment();
- when(featureFlagClientMock.getProperties()).thenReturn(Map.of());
-
- String watchKey = "wk1";
- AppConfigurationStoreMonitoring monitoring = new AppConfigurationStoreMonitoring();
- monitoring.setEnabled(true);
-
- AppConfigurationStoreTrigger trigger = new AppConfigurationStoreTrigger();
- trigger.setKey(watchKey);
- trigger.setLabel(EMPTY_LABEL);
- monitoring.setTriggers(List.of(trigger));
-
- properties.getStores().get(0).setMonitoring(monitoring);
-
- when(replicaClientMock.getWatchKey(Mockito.eq(watchKey), Mockito.anyString(), Mockito.anyBoolean()))
- .thenReturn(null);
-
- locator = new AppConfigurationPropertySourceLocator(appProperties, clientFactoryMock, keyVaultClientFactory,
- null, stores, replicaLookUpMock, featureFlagClientMock);
-
- try (MockedStatic stateHolderMock = Mockito.mockStatic(StateHolder.class)) {
- stateHolderMock.when(() -> StateHolder.updateState(Mockito.any())).thenReturn(null);
- PropertySource> source = locator.locate(emptyEnvironment);
-
- assertTrue(source instanceof CompositePropertySource);
-
- Collection> sources = ((CompositePropertySource) source).getPropertySources();
-
- String[] expectedSourceNames = new String[] {
- KEY_FILTER + "store1/\0"
- };
- assertEquals(expectedSourceNames.length, sources.size());
- assertArrayEquals((Object[]) expectedSourceNames, sources.stream().map(PropertySource::getName).toArray());
- verify(replicaClientMock, times(1)).getWatchKey(Mockito.eq(watchKey), Mockito.anyString(),
- Mockito.anyBoolean());
- }
- }
-
- @Test
- public void devSourceIsCreated() {
- when(devEnvironment.getActiveProfiles()).thenReturn(new String[] { PROFILE_NAME_1 });
- when(devEnvironment.getPropertySources()).thenReturn(sources);
- when(clientFactoryMock.getAvailableClients(Mockito.anyString(), Mockito.eq(true))).thenReturn(Arrays.asList(replicaClientMock));
- when(replicaClientMock.listSettings(Mockito.any(), Mockito.anyBoolean())).thenReturn(List.of());
- when(featureFlagClientMock.getProperties()).thenReturn(Map.of());
-
- locator = new AppConfigurationPropertySourceLocator(appProperties, clientFactoryMock, keyVaultClientFactory,
- null, stores, replicaLookUpMock, featureFlagClientMock);
-
- try (MockedStatic stateHolderMock = Mockito.mockStatic(StateHolder.class)) {
- stateHolderMock.when(() -> StateHolder.updateState(Mockito.any())).thenReturn(null);
- PropertySource> source = locator.locate(devEnvironment);
- assertTrue(source instanceof CompositePropertySource);
-
- Collection> sources = ((CompositePropertySource) source).getPropertySources();
-
- String[] expectedSourceNames = new String[] {
- KEY_FILTER + "store1/dev"
- };
- assertEquals(expectedSourceNames.length, sources.size());
- assertArrayEquals((Object[]) expectedSourceNames, sources.stream().map(PropertySource::getName).toArray());
- }
- }
-
- @Test
- public void multiSourceIsCreated() {
- when(multiEnvironment.getActiveProfiles()).thenReturn(new String[] { PROFILE_NAME_1, PROFILE_NAME_2 });
- when(multiEnvironment.getPropertySources()).thenReturn(sources);
- when(clientFactoryMock.getAvailableClients(Mockito.anyString(), Mockito.eq(true))).thenReturn(Arrays.asList(replicaClientMock));
- when(replicaClientMock.listSettings(Mockito.any(), Mockito.anyBoolean())).thenReturn(List.of());
- when(featureFlagClientMock.getProperties()).thenReturn(Map.of());
-
- locator = new AppConfigurationPropertySourceLocator(appProperties, clientFactoryMock, keyVaultClientFactory,
- null, stores, replicaLookUpMock, featureFlagClientMock);
-
- try (MockedStatic stateHolderMock = Mockito.mockStatic(StateHolder.class)) {
- stateHolderMock.when(() -> StateHolder.updateState(Mockito.any())).thenReturn(null);
- PropertySource> source = locator.locate(multiEnvironment);
- assertTrue(source instanceof CompositePropertySource);
-
- Collection> sources = ((CompositePropertySource) source).getPropertySources();
-
- String[] expectedSourceNames = new String[] {
- KEY_FILTER + "store1/prod,dev"
- };
- assertEquals(expectedSourceNames.length, sources.size());
- assertArrayEquals((Object[]) expectedSourceNames, sources.stream().map(PropertySource::getName).toArray());
- }
- }
-
- @Test
- public void storeCreatedWithFeatureFlags() {
- setupEmptyEnvironment();
- when(featureFlagClientMock.getProperties()).thenReturn(Map.of("fake_features", new Feature()));
-
- FeatureFlagStore featureFlagStore = new FeatureFlagStore();
- featureFlagStore.setEnabled(true);
- featureFlagStore.validateAndInit();
-
- FeatureFlagConfigurationSetting featureFlag = new FeatureFlagConfigurationSetting("Alpha", false);
- featureFlag.setValue("");
-
- properties.getStores().get(0).setFeatureFlags(featureFlagStore);
-
- when(replicaClientMock.listSettings(Mockito.any(), Mockito.anyBoolean())).thenReturn(List.of(featureFlag));
-
- locator = new AppConfigurationPropertySourceLocator(appProperties, clientFactoryMock, keyVaultClientFactory,
- null, stores, replicaLookUpMock, featureFlagClientMock);
-
- try (MockedStatic stateHolderMock = Mockito.mockStatic(StateHolder.class)) {
- stateHolderMock.when(() -> StateHolder.updateState(Mockito.any())).thenReturn(null);
- PropertySource> source = locator.locate(emptyEnvironment);
- assertTrue(source instanceof CompositePropertySource);
-
- Collection> sources = ((CompositePropertySource) source).getPropertySources();
- String[] expectedSourceNames = new String[] {
- KEY_FILTER + "store1/\0",
- "feature_management"
- };
- assertEquals(expectedSourceNames.length, sources.size());
- assertArrayEquals((Object[]) expectedSourceNames, sources.stream().map(PropertySource::getName).toArray());
- }
- }
-
- @Test
- public void storeCreatedWithFeatureFlagsWithMonitoring() {
- setupEmptyEnvironment();
- when(featureFlagClientMock.getProperties()).thenReturn(Map.of("fake_features", new Feature()));
-
- AppConfigurationStoreMonitoring monitoring = new AppConfigurationStoreMonitoring();
- monitoring.setEnabled(true);
- FeatureFlagStore featureFlagStore = new FeatureFlagStore();
- featureFlagStore.setEnabled(true);
- featureFlagStore.validateAndInit();
-
- FeatureFlagConfigurationSetting featureFlag = new FeatureFlagConfigurationSetting("Alpha", false);
- featureFlag.setValue("");
-
- properties.getStores().get(0).setFeatureFlags(featureFlagStore);
- properties.getStores().get(0).setMonitoring(monitoring);
-
- when(replicaClientMock.listSettings(Mockito.any(), Mockito.anyBoolean())).thenReturn(List.of(featureFlag));
-
- locator = new AppConfigurationPropertySourceLocator(appProperties, clientFactoryMock, keyVaultClientFactory,
- null, stores, replicaLookUpMock, featureFlagClientMock);
-
- try (MockedStatic stateHolderMock = Mockito.mockStatic(StateHolder.class)) {
- stateHolderMock.when(() -> StateHolder.updateState(Mockito.any())).thenReturn(null);
- PropertySource> source = locator.locate(emptyEnvironment);
- assertTrue(source instanceof CompositePropertySource);
-
- Collection> sources = ((CompositePropertySource) source).getPropertySources();
- String[] expectedSourceNames = new String[] {
- KEY_FILTER + "store1/\0",
- "feature_management"
- };
- assertEquals(expectedSourceNames.length, sources.size());
- assertArrayEquals((Object[]) expectedSourceNames, sources.stream().map(PropertySource::getName).toArray());
- }
- }
-
- @Test
- public void watchedKeyCheck() {
- setupEmptyEnvironment();
- when(featureFlagClientMock.getProperties()).thenReturn(Map.of());
-
- locator = new AppConfigurationPropertySourceLocator(appProperties, clientFactoryMock, keyVaultClientFactory,
- null, stores, replicaLookUpMock, featureFlagClientMock);
-
- try (MockedStatic stateHolderMock = Mockito.mockStatic(StateHolder.class)) {
- stateHolderMock.when(() -> StateHolder.updateState(Mockito.any())).thenReturn(null);
- PropertySource> source = locator.locate(emptyEnvironment);
- assertTrue(source instanceof CompositePropertySource);
-
- Collection> sources = ((CompositePropertySource) source).getPropertySources();
- String[] expectedSourceNames = new String[] {
- KEY_FILTER + "store1/\0"
- };
- assertEquals(expectedSourceNames.length, sources.size());
- assertArrayEquals((Object[]) expectedSourceNames, sources.stream().map(PropertySource::getName).toArray());
- }
- }
-
- @Test
- public void defaultFailFastThrowException() {
- when(emptyEnvironment.getActiveProfiles()).thenReturn(new String[] {});
- when(emptyEnvironment.getPropertySources()).thenReturn(sources);
- when(clientFactoryMock.getAvailableClients(Mockito.anyString(), Mockito.eq(true))).thenReturn(Arrays.asList(replicaClientMock));
- when(configStoreMock.getEndpoint()).thenReturn(TEST_STORE_NAME);
- when(configStoreMock.isEnabled()).thenReturn(true);
- when(configStoreMock.getSelects()).thenReturn(List.of());
- when(configStoreMock.getFeatureFlags()).thenReturn(featureFlagStoreMock);
- when(configStoreMock.isFailFast()).thenReturn(true);
-
- AppConfigurationStoreTrigger trigger = new AppConfigurationStoreTrigger();
- AppConfigurationStoreMonitoring monitor = new AppConfigurationStoreMonitoring();
- monitor.setEnabled(true);
- monitor.setTriggers(List.of(trigger));
-
- when(configStoreMock.getMonitoring()).thenReturn(monitor);
-
- locator = new AppConfigurationPropertySourceLocator(appProperties, clientFactoryMock, keyVaultClientFactory,
- null, List.of(configStoreMock), replicaLookUpMock, featureFlagClientMock);
-
- when(replicaClientMock.getWatchKey(Mockito.any(), Mockito.anyString(), Mockito.anyBoolean())).thenThrow(new RuntimeException());
- RuntimeException e = assertThrows(RuntimeException.class, () -> locator.locate(emptyEnvironment));
- assertEquals("Failed to generate property sources for " + TEST_STORE_NAME, e.getMessage());
- verify(configStoreMock, times(1)).isFailFast();
- }
-
- @Test
- public void refreshThrowException() throws IllegalArgumentException {
- setupEmptyEnvironment();
- when(replicaClientMock.listSettings(any(), Mockito.anyBoolean())).thenThrow(new RuntimeException());
-
- AppConfigurationPropertySourceLocator.STARTUP.set(false);
-
- locator = new AppConfigurationPropertySourceLocator(appProperties, clientFactoryMock, keyVaultClientFactory,
- null, stores, replicaLookUpMock, featureFlagClientMock);
-
- try (MockedStatic stateHolderMock = Mockito.mockStatic(StateHolder.class)) {
- stateHolderMock.when(() -> StateHolder.getLoadState(Mockito.anyString())).thenReturn(true);
- RuntimeException e = assertThrows(RuntimeException.class, () -> locator.locate(emptyEnvironment));
- assertEquals("Failed to generate property sources for store1", e.getMessage());
- }
- }
-
- @Test
- public void notFailFastShouldPass() {
- when(featureFlagClientMock.getProperties()).thenReturn(Map.of());
- when(emptyEnvironment.getActiveProfiles()).thenReturn(new String[] {});
- when(emptyEnvironment.getPropertySources()).thenReturn(sources);
- when(clientFactoryMock.getAvailableClients(Mockito.anyString(), Mockito.eq(true))).thenReturn(Arrays.asList(replicaClientMock));
- when(configStoreMock.getEndpoint()).thenReturn(TEST_STORE_NAME);
- when(configStoreMock.isEnabled()).thenReturn(true);
- when(configStoreMock.getSelects()).thenReturn(List.of());
- when(configStoreMock.getFeatureFlags()).thenReturn(featureFlagStoreMock);
- when(configStoreMock.isFailFast()).thenReturn(false);
-
- locator = new AppConfigurationPropertySourceLocator(appProperties, clientFactoryMock, keyVaultClientFactory,
- null, List.of(configStoreMock), replicaLookUpMock, featureFlagClientMock);
-
- properties.getStores().get(0).setFailFast(false);
-
- try (MockedStatic stateHolderMock = Mockito.mockStatic(StateHolder.class)) {
- stateHolderMock.when(() -> StateHolder.updateState(Mockito.any())).thenReturn(null);
- PropertySource> source = locator.locate(emptyEnvironment);
- assertTrue(source instanceof CompositePropertySource);
-
- // Once a store fails it should stop attempting to load
- verify(configStoreMock, times(3)).isFailFast();
- }
- }
-
- @Test
- public void multiplePropertySourcesExistForMultiStores() {
- setupEmptyEnvironment();
- when(featureFlagClientMock.getProperties()).thenReturn(Map.of());
- TestUtils.addStore(properties, TEST_STORE_NAME_2, TEST_CONN_STRING_2, KEY_FILTER);
-
- locator = new AppConfigurationPropertySourceLocator(appProperties,
- clientFactoryMock, keyVaultClientFactory, null, properties.getStores(), replicaLookUpMock,
- featureFlagClientMock);
-
- try (MockedStatic stateHolderMock = Mockito.mockStatic(StateHolder.class)) {
- stateHolderMock.when(() -> StateHolder.updateState(Mockito.any())).thenReturn(null);
- PropertySource> source = locator.locate(emptyEnvironment);
- assertTrue(source instanceof CompositePropertySource);
-
- Collection> sources = ((CompositePropertySource) source).getPropertySources();
- String[] expectedSourceNames = new String[] { KEY_FILTER + TEST_STORE_NAME_2 + "/\0",
- KEY_FILTER + TEST_STORE_NAME + "/\0" };
- assertEquals(2, sources.size());
- assertArrayEquals((Object[]) expectedSourceNames, sources.stream().map(PropertySource::getName).toArray());
- }
- }
-
- @Test
- public void awaitOnError() {
- when(clientFactoryMock.getAvailableClients(Mockito.anyString(), Mockito.eq(true))).thenReturn(Arrays.asList(replicaClientMock));
- when(replicaClientMock.listSettings(Mockito.any(), Mockito.anyBoolean())).thenReturn(List.of());
- when(appPropertiesMock.getPrekillTime()).thenReturn(5);
-
- ConfigurableEnvironment env = Mockito.mock(ConfigurableEnvironment.class);
- MutablePropertySources sources = new MutablePropertySources();
-
- sources.addFirst(new PropertySource("refreshArgs") {
-
- @Override
- public Object getProperty(String name) {
- return null;
- }
- });
-
- when(env.getPropertySources()).thenReturn(sources);
-
- String[] array = {};
- when(env.getActiveProfiles()).thenReturn(array);
- AppConfigurationKeyValueSelector selectedKeys = new AppConfigurationKeyValueSelector()
- .setKeyFilter("/application/");
- List selects = new ArrayList<>();
- selects.add(selectedKeys);
- when(configStoreMockError.getSelects()).thenReturn(selects);
- when(configStoreMockError.isEnabled()).thenReturn(true);
- when(configStoreMockError.isFailFast()).thenReturn(true);
- when(configStoreMockError.getEndpoint()).thenReturn("");
-
- when(replicaClientMock.listSettings(Mockito.any(), Mockito.anyBoolean())).thenThrow(new NullPointerException(""));
- when(appPropertiesMock.getPrekillTime()).thenReturn(-60);
- when(appPropertiesMock.getStartDate()).thenReturn(Instant.now());
-
- locator = new AppConfigurationPropertySourceLocator(appPropertiesMock, clientFactoryMock, keyVaultClientFactory,
- null, List.of(configStoreMockError), replicaLookUpMock, featureFlagClientMock);
-
- assertThrows(RuntimeException.class, () -> locator.locate(env));
- verify(appPropertiesMock, times(1)).getPrekillTime();
- }
-
- @Test
- public void storeDisabled() {
- when(emptyEnvironment.getActiveProfiles()).thenReturn(new String[] {});
- when(emptyEnvironment.getPropertySources()).thenReturn(sources);
- properties.getStores().get(0).setEnabled(false);
- properties.getStores().get(0).setMonitoring(monitoring);
-
- locator = new AppConfigurationPropertySourceLocator(appProperties, clientFactoryMock, keyVaultClientFactory,
- null, stores, replicaLookUpMock, featureFlagClientMock);
- try (MockedStatic stateHolderMock = Mockito.mockStatic(StateHolder.class)) {
- stateHolderMock.when(() -> StateHolder.updateState(Mockito.any())).thenReturn(null);
- PropertySource> source = locator.locate(emptyEnvironment);
- assertTrue(source instanceof CompositePropertySource);
-
- Collection> sources = ((CompositePropertySource) source).getPropertySources();
-
- assertEquals(0, sources.size());
- }
- }
-
- private void setupEmptyEnvironment() {
- when(emptyEnvironment.getActiveProfiles()).thenReturn(new String[] {});
- when(emptyEnvironment.getPropertySources()).thenReturn(sources);
- when(clientFactoryMock.getAvailableClients(Mockito.anyString(), Mockito.eq(true))).thenReturn(Arrays.asList(replicaClientMock));
- when(replicaClientMock.listSettings(Mockito.any(), Mockito.anyBoolean())).thenReturn(List.of());
- }
-}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationRefreshUtilTest.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationRefreshUtilTest.java
index ba6b62292b8c..161681f4740b 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationRefreshUtilTest.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationRefreshUtilTest.java
@@ -101,13 +101,12 @@ public void cleanup() throws Exception {
public void refreshWithoutTimeWatchKeyConfigStoreNotLoaded(TestInfo testInfo) {
endpoint = testInfo.getDisplayName() + ".azconfig.io";
when(clientMock.getEndpoint()).thenReturn(endpoint);
- when(clientFactoryMock.findOriginForEndpoint(Mockito.eq(endpoint))).thenReturn(endpoint);
try (MockedStatic stateHolderMock = Mockito.mockStatic(StateHolder.class)) {
stateHolderMock.when(() -> StateHolder.getLoadState(endpoint)).thenReturn(false);
- assertFalse(
- AppConfigurationRefreshUtil.checkStoreAfterRefreshFailed(clientMock, clientFactoryMock, featureStore));
+ assertFalse(AppConfigurationRefreshUtil.refreshStoreCheck(clientMock, endpoint));
+ assertFalse(AppConfigurationRefreshUtil.refreshStoreFeatureFlagCheck(true, clientMock));
}
}
@@ -115,20 +114,18 @@ public void refreshWithoutTimeWatchKeyConfigStoreNotLoaded(TestInfo testInfo) {
public void refreshWithoutTimeWatchKeyConfigStoreWatchKeyNotReturned(TestInfo testInfo) {
endpoint = testInfo.getDisplayName() + ".azconfig.io";
when(clientMock.getEndpoint()).thenReturn(endpoint);
- when(clientFactoryMock.findOriginForEndpoint(Mockito.eq(endpoint))).thenReturn(endpoint);
List watchKeys = generateWatchKeys();
State newState = new State(watchKeys, Math.toIntExact(Duration.ofMinutes(10).getSeconds()), endpoint);
// Config Store doesn't return a watch key change.
- when(clientMock.getWatchKey(Mockito.eq(KEY_FILTER), Mockito.eq(EMPTY_LABEL), Mockito.anyBoolean()))
- .thenReturn(watchKeys.get(0));
+ when(clientMock.getWatchKey(Mockito.eq(KEY_FILTER), Mockito.eq(EMPTY_LABEL), Mockito.anyBoolean())).thenReturn(watchKeys.get(0));
try (MockedStatic stateHolderMock = Mockito.mockStatic(StateHolder.class)) {
stateHolderMock.when(() -> StateHolder.getLoadState(endpoint)).thenReturn(true);
stateHolderMock.when(() -> StateHolder.getState(endpoint)).thenReturn(newState);
- assertFalse(
- AppConfigurationRefreshUtil.checkStoreAfterRefreshFailed(clientMock, clientFactoryMock, featureStore));
+ assertFalse(AppConfigurationRefreshUtil.refreshStoreCheck(clientMock, endpoint));
+ assertFalse(AppConfigurationRefreshUtil.refreshStoreFeatureFlagCheck(true, clientMock));
}
}
@@ -136,7 +133,6 @@ public void refreshWithoutTimeWatchKeyConfigStoreWatchKeyNotReturned(TestInfo te
public void refreshWithoutTimeWatchKeyConfigStoreWatchKeyNoChange(TestInfo testInfo) {
endpoint = testInfo.getDisplayName() + ".azconfig.io";
when(clientMock.getEndpoint()).thenReturn(endpoint);
- when(clientFactoryMock.findOriginForEndpoint(Mockito.eq(endpoint))).thenReturn(endpoint);
FeatureFlagState newState = new FeatureFlagState(
List.of(new FeatureFlags(new SettingSelector().setKeyFilter(KEY_FILTER).setLabelFilter(EMPTY_LABEL), null)),
@@ -147,38 +143,36 @@ public void refreshWithoutTimeWatchKeyConfigStoreWatchKeyNoChange(TestInfo testI
try (MockedStatic stateHolderMock = Mockito.mockStatic(StateHolder.class)) {
stateHolderMock.when(() -> StateHolder.getStateFeatureFlag(endpoint)).thenReturn(newState);
- assertFalse(
- AppConfigurationRefreshUtil.checkStoreAfterRefreshFailed(clientMock, clientFactoryMock, featureStore));
+ assertFalse(AppConfigurationRefreshUtil.refreshStoreCheck(clientMock, endpoint));
+ assertFalse(AppConfigurationRefreshUtil.refreshStoreFeatureFlagCheck(true, clientMock));
}
}
- @SuppressWarnings("try")
@Test
public void refreshWithoutTimeFeatureFlagDisabled(TestInfo testInfo) {
endpoint = testInfo.getDisplayName() + ".azconfig.io";
when(clientMock.getEndpoint()).thenReturn(endpoint);
- when(clientFactoryMock.findOriginForEndpoint(Mockito.eq(endpoint))).thenReturn(endpoint);
configStore.getFeatureFlags().setEnabled(false);
try (MockedStatic stateHolderMock = Mockito.mockStatic(StateHolder.class)) {
- assertFalse(
- AppConfigurationRefreshUtil.checkStoreAfterRefreshFailed(clientMock, clientFactoryMock, featureStore));
+ assertFalse(AppConfigurationRefreshUtil.refreshStoreCheck(clientMock, endpoint));
+ assertFalse(AppConfigurationRefreshUtil.refreshStoreFeatureFlagCheck(true, clientMock));
+ stateHolderMock.verify(() -> StateHolder.getLoadState(Mockito.anyString()), times(1));
}
}
- @SuppressWarnings("try")
@Test
public void refreshWithoutTimeFeatureFlagNotLoaded(TestInfo testInfo) {
endpoint = testInfo.getDisplayName() + ".azconfig.io";
when(clientMock.getEndpoint()).thenReturn(endpoint);
- when(clientFactoryMock.findOriginForEndpoint(Mockito.eq(endpoint))).thenReturn(endpoint);
configStore.getFeatureFlags().setEnabled(true);
try (MockedStatic stateHolderMock = Mockito.mockStatic(StateHolder.class)) {
- assertFalse(
- AppConfigurationRefreshUtil.checkStoreAfterRefreshFailed(clientMock, clientFactoryMock, featureStore));
+ assertFalse(AppConfigurationRefreshUtil.refreshStoreCheck(clientMock, endpoint));
+ assertFalse(AppConfigurationRefreshUtil.refreshStoreFeatureFlagCheck(true, clientMock));
+ stateHolderMock.verify(() -> StateHolder.getLoadState(Mockito.anyString()), times(1));
}
}
@@ -186,8 +180,7 @@ public void refreshWithoutTimeFeatureFlagNotLoaded(TestInfo testInfo) {
public void refreshWithoutTimeFeatureFlagNoChange(TestInfo testInfo) {
endpoint = testInfo.getDisplayName() + ".azconfig.io";
when(clientMock.getEndpoint()).thenReturn(endpoint);
- when(clientFactoryMock.findOriginForEndpoint(Mockito.eq(endpoint))).thenReturn(endpoint);
-
+
FeatureFlagState newState = new FeatureFlagState(
List.of(new FeatureFlags(new SettingSelector().setKeyFilter(KEY_FILTER).setLabelFilter(EMPTY_LABEL), null)),
Math.toIntExact(Duration.ofMinutes(10).getSeconds()), endpoint);
@@ -197,8 +190,8 @@ public void refreshWithoutTimeFeatureFlagNoChange(TestInfo testInfo) {
try (MockedStatic stateHolderMock = Mockito.mockStatic(StateHolder.class)) {
stateHolderMock.when(() -> StateHolder.getStateFeatureFlag(endpoint)).thenReturn(newState);
- assertFalse(
- AppConfigurationRefreshUtil.checkStoreAfterRefreshFailed(clientMock, clientFactoryMock, featureStore));
+ assertFalse(AppConfigurationRefreshUtil.refreshStoreCheck(clientMock, endpoint));
+ assertFalse(AppConfigurationRefreshUtil.refreshStoreFeatureFlagCheck(true, clientMock));
}
}
@@ -207,8 +200,7 @@ public void refreshWithoutTimeFeatureFlagNoChange(TestInfo testInfo) {
public void refreshWithoutTimeFeatureFlagEtagChanged(TestInfo testInfo) {
endpoint = testInfo.getDisplayName() + ".azconfig.io";
when(clientMock.getEndpoint()).thenReturn(endpoint);
- when(clientFactoryMock.findOriginForEndpoint(Mockito.eq(endpoint))).thenReturn(endpoint);
-
+
FeatureFlags featureFlags = new FeatureFlags(new SettingSelector(), watchKeysFeatureFlags);
FeatureFlagState newState = new FeatureFlagState(List.of(featureFlags),
Math.toIntExact(Duration.ofMinutes(10).getSeconds()), endpoint);
@@ -218,8 +210,8 @@ public void refreshWithoutTimeFeatureFlagEtagChanged(TestInfo testInfo) {
try (MockedStatic stateHolderMock = Mockito.mockStatic(StateHolder.class)) {
stateHolderMock.when(() -> StateHolder.getStateFeatureFlag(endpoint)).thenReturn(newState);
- assertTrue(
- AppConfigurationRefreshUtil.checkStoreAfterRefreshFailed(clientMock, clientFactoryMock, featureStore));
+ assertFalse(AppConfigurationRefreshUtil.refreshStoreCheck(clientMock, endpoint));
+ assertTrue(AppConfigurationRefreshUtil.refreshStoreFeatureFlagCheck(true, clientMock));
}
}
@@ -241,8 +233,7 @@ public void refreshStoresCheckSettingsTestNotEnabled(TestInfo testInfo) {
(long) 60, replicaLookUpMock);
assertFalse(eventData.getDoRefresh());
verify(clientFactoryMock, times(1)).setCurrentConfigStoreClient(Mockito.eq(endpoint), Mockito.eq(endpoint));
- verify(clientOriginMock, times(0)).getWatchKey(Mockito.anyString(), Mockito.anyString(),
- Mockito.anyBoolean());
+ verify(clientOriginMock, times(0)).getWatchKey(Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean());
}
}
@@ -261,8 +252,7 @@ public void refreshStoresCheckSettingsTestNotLoaded(TestInfo testInfo) {
Duration.ofMinutes(10), (long) 60, replicaLookUpMock);
assertFalse(eventData.getDoRefresh());
verify(clientFactoryMock, times(1)).setCurrentConfigStoreClient(Mockito.eq(endpoint), Mockito.eq(endpoint));
- verify(clientOriginMock, times(0)).getWatchKey(Mockito.anyString(), Mockito.anyString(),
- Mockito.anyBoolean());
+ verify(clientOriginMock, times(0)).getWatchKey(Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean());
}
}
@@ -282,8 +272,7 @@ public void refreshStoresCheckSettingsTestNotRefreshTime(TestInfo testInfo) {
(long) 60, replicaLookUpMock);
assertFalse(eventData.getDoRefresh());
verify(clientFactoryMock, times(1)).setCurrentConfigStoreClient(Mockito.eq(endpoint), Mockito.eq(endpoint));
- verify(clientOriginMock, times(0)).getWatchKey(Mockito.anyString(), Mockito.anyString(),
- Mockito.anyBoolean());
+ verify(clientOriginMock, times(0)).getWatchKey(Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean());
}
}
@@ -305,8 +294,7 @@ public void refreshStoresCheckSettingsTestFailedRequest(TestInfo testInfo) {
(long) 60, replicaLookUpMock);
assertFalse(eventData.getDoRefresh());
verify(clientFactoryMock, times(1)).setCurrentConfigStoreClient(Mockito.eq(endpoint), Mockito.eq(endpoint));
- verify(clientOriginMock, times(1)).getWatchKey(Mockito.anyString(), Mockito.anyString(),
- Mockito.anyBoolean());
+ verify(clientOriginMock, times(1)).getWatchKey(Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean());
assertEquals(newState, StateHolder.getState(endpoint));
}
}
@@ -332,8 +320,7 @@ public void refreshStoresCheckSettingsTestRefreshTimeNoChange(TestInfo testInfo)
assertEquals(newState, StateHolder.getState(endpoint));
assertFalse(eventData.getDoRefresh());
verify(clientFactoryMock, times(1)).setCurrentConfigStoreClient(Mockito.eq(endpoint), Mockito.eq(endpoint));
- verify(clientOriginMock, times(1)).getWatchKey(Mockito.anyString(), Mockito.anyString(),
- Mockito.anyBoolean());
+ verify(clientOriginMock, times(1)).getWatchKey(Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean());
}
}
@@ -349,8 +336,7 @@ public void refreshStoresCheckSettingsTestTriggerRefresh(TestInfo testInfo) {
ConfigurationSetting refreshKey = new ConfigurationSetting().setKey(KEY_FILTER).setLabel(EMPTY_LABEL)
.setETag("new");
- when(clientOriginMock.getWatchKey(Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean()))
- .thenReturn(refreshKey);
+ when(clientOriginMock.getWatchKey(Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean())).thenReturn(refreshKey);
State newState = new State(generateWatchKeys(), Math.toIntExact(Duration.ofMinutes(-1).getSeconds()), endpoint);
@@ -364,8 +350,7 @@ public void refreshStoresCheckSettingsTestTriggerRefresh(TestInfo testInfo) {
(long) 60, replicaLookUpMock);
assertTrue(eventData.getDoRefresh());
verify(clientFactoryMock, times(1)).setCurrentConfigStoreClient(Mockito.eq(endpoint), Mockito.eq(endpoint));
- verify(clientOriginMock, times(1)).getWatchKey(Mockito.anyString(), Mockito.anyString(),
- Mockito.anyBoolean());
+ verify(clientOriginMock, times(1)).getWatchKey(Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean());
verify(currentStateMock, times(1)).updateStateRefresh(Mockito.any(), Mockito.any());
}
}
@@ -388,8 +373,7 @@ public void refreshStoresCheckFeatureFlagTestNotLoaded(TestInfo testInfo) {
(long) 60, replicaLookUpMock);
assertFalse(eventData.getDoRefresh());
verify(clientFactoryMock, times(1)).setCurrentConfigStoreClient(Mockito.eq(endpoint), Mockito.eq(endpoint));
- verify(clientOriginMock, times(0)).getWatchKey(Mockito.anyString(), Mockito.anyString(),
- Mockito.anyBoolean());
+ verify(clientOriginMock, times(0)).getWatchKey(Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean());
}
}
@@ -411,8 +395,7 @@ public void refreshStoresCheckFeatureFlagTestNotRefreshTime(TestInfo testInfo) {
(long) 60, replicaLookUpMock);
assertFalse(eventData.getDoRefresh());
verify(clientFactoryMock, times(1)).setCurrentConfigStoreClient(Mockito.eq(endpoint), Mockito.eq(endpoint));
- verify(clientOriginMock, times(0)).getWatchKey(Mockito.anyString(), Mockito.anyString(),
- Mockito.anyBoolean());
+ verify(clientOriginMock, times(0)).getWatchKey(Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean());
}
}
@@ -440,8 +423,7 @@ public void refreshStoresCheckFeatureFlagTestNoChange(TestInfo testInfo) {
Duration.ofMinutes(10), (long) 60, replicaLookUpMock);
assertFalse(eventData.getDoRefresh());
verify(clientFactoryMock, times(1)).setCurrentConfigStoreClient(Mockito.eq(endpoint), Mockito.eq(endpoint));
- verify(clientOriginMock, times(0)).getWatchKey(Mockito.anyString(), Mockito.anyString(),
- Mockito.anyBoolean());
+ verify(clientOriginMock, times(0)).getWatchKey(Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean());
verify(currentStateMock, times(1)).updateFeatureFlagStateRefresh(Mockito.any(), Mockito.any());
}
@@ -468,8 +450,7 @@ public void refreshStoresCheckFeatureFlagTestTriggerRefresh(TestInfo testInfo) {
Duration.ofMinutes(10), (long) 60, replicaLookUpMock);
assertTrue(eventData.getDoRefresh());
verify(clientFactoryMock, times(1)).setCurrentConfigStoreClient(Mockito.eq(endpoint), Mockito.eq(endpoint));
- verify(clientOriginMock, times(0)).getWatchKey(Mockito.anyString(), Mockito.anyString(),
- Mockito.anyBoolean());
+ verify(clientOriginMock, times(0)).getWatchKey(Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean());
}
}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClientBuilderTest.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClientBuilderTest.java
index 3dda6cd72a43..c35010596f36 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClientBuilderTest.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClientBuilderTest.java
@@ -51,7 +51,7 @@ public class AppConfigurationReplicaClientBuilderTest {
@Mock
private ConfigurationClientBuilderFactory clientFactoryMock;
-
+
@Mock
private Environment envMock;
@@ -68,7 +68,6 @@ public void setup() {
configStore.validateAndInit();
clientBuilder = null;
- when(envMock.getActiveProfiles()).thenReturn(new String[0]);
}
@AfterEach
@@ -79,8 +78,7 @@ public void cleanup() throws Exception {
@Test
public void buildClientFromEndpointTest() {
- clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, false);
- clientBuilder.setEnvironment(envMock);
+ clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, null, false, false);
AppConfigurationReplicaClientsBuilder spy = Mockito.spy(clientBuilder);
when(clientFactoryMock.build()).thenReturn(builderMock);
@@ -102,8 +100,7 @@ public void buildClientFromConnectionStringTest() {
configStore.setConnectionString(TEST_CONN_STRING);
configStore.validateAndInit();
- clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, false);
- clientBuilder.setEnvironment(envMock);
+ clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, null, false, false);
AppConfigurationReplicaClientsBuilder spy = Mockito.spy(clientBuilder);
when(clientFactoryMock.build()).thenReturn(builderMock);
@@ -120,9 +117,7 @@ public void buildClientFromConnectionStringTest() {
@Test
public void modifyClientTest() {
- clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, false);
- clientBuilder.setClientProvider(modifierMock);
- clientBuilder.setEnvironment(envMock);
+ clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, modifierMock, false, false);
AppConfigurationReplicaClientsBuilder spy = Mockito.spy(clientBuilder);
@@ -153,8 +148,7 @@ public void buildClientsFromMultipleEndpointsTest() {
configStore.validateAndInit();
- clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, false);
- clientBuilder.setEnvironment(envMock);
+ clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, null, false, false);
AppConfigurationReplicaClientsBuilder spy = Mockito.spy(clientBuilder);
@@ -180,8 +174,7 @@ public void buildClientsFromMultipleConnectionStringsTest() {
configStore.validateAndInit();
- clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, false);
- clientBuilder.setEnvironment(envMock);
+ clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, null, false, false);
AppConfigurationReplicaClientsBuilder spy = Mockito.spy(clientBuilder);
@@ -205,8 +198,7 @@ public void endpointAndConnectionString() {
configStore.setConnectionString(TEST_CONN_STRING);
configStore.validateAndInit();
- clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, false);
- clientBuilder.setEnvironment(envMock);
+ clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, null, false, false);
String message = assertThrows(IllegalArgumentException.class,
() -> clientBuilder.buildClients(configStore).get(0)).getMessage();
@@ -216,8 +208,7 @@ public void endpointAndConnectionString() {
@Test
public void buildClientTest() {
- clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, false);
- clientBuilder.setEnvironment(envMock);
+ clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, null, false, false);
AppConfigurationReplicaClientsBuilder spy = Mockito.spy(clientBuilder);
when(clientFactoryMock.build()).thenReturn(builderMock);
@@ -236,8 +227,7 @@ public void buildClientTest() {
@Test
public void buildClientConnectionStringTest() {
configStore.setConnectionString(TEST_CONN_STRING);
- clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, false);
- clientBuilder.setEnvironment(envMock);
+ clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, null, false, false);
AppConfigurationReplicaClientsBuilder spy = Mockito.spy(clientBuilder);
when(clientFactoryMock.build()).thenReturn(builderMock);
@@ -255,8 +245,7 @@ public void buildClientConnectionStringTest() {
@Test
public void buildClientConnectionStringsTest() {
configStore.setConnectionStrings(List.of(TEST_CONN_STRING, TEST_CONN_STRING_GEO));
- clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, false);
- clientBuilder.setEnvironment(envMock);
+ clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, null, false, false);
AppConfigurationReplicaClientsBuilder spy = Mockito.spy(clientBuilder);
when(builderMock.addPolicy(Mockito.any())).thenReturn(builderMock);
@@ -274,8 +263,7 @@ public void buildClientConnectionStringsTest() {
@Test
public void buildClientConnectionStringInvalidTest() {
configStore.setConnectionString(TEST_CONN_STRING);
- clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, false);
- clientBuilder.setEnvironment(envMock);
+ clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, null, false, false);
AppConfigurationReplicaClientsBuilder spy = Mockito.spy(clientBuilder);
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
@@ -287,8 +275,7 @@ public void buildClientConnectionStringInvalidTest() {
@Test
public void buildClientConnectionStringInvalid2Test() {
configStore.setConnectionString("Not A Connection String");
- clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, false);
- clientBuilder.setEnvironment(envMock);
+ clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, null, false, false);
AppConfigurationReplicaClientsBuilder spy = Mockito.spy(clientBuilder);
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
@@ -300,8 +287,7 @@ public void buildClientConnectionStringInvalid2Test() {
@Test
public void buildClientConnectionStringInvalid3Test() {
configStore.setConnectionString("Not;A;Connection String");
- clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, false);
- clientBuilder.setEnvironment(envMock);
+ clientBuilder = new AppConfigurationReplicaClientsBuilder(0, clientFactoryMock, null, false, false);
AppConfigurationReplicaClientsBuilder spy = Mockito.spy(clientBuilder);
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClientFactoryTest.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClientFactoryTest.java
index 3be2260be0f4..186a6ee8db94 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClientFactoryTest.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClientFactoryTest.java
@@ -3,8 +3,6 @@
package com.azure.spring.cloud.appconfiguration.config.implementation;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.ArrayList;
import java.util.List;
@@ -79,12 +77,4 @@ public void findOriginTest() {
assertEquals(invalidReplica, clientFactory.findOriginForEndpoint(invalidReplica));
}
- @Test
- public void hasReplicasTest() {
- assertTrue(clientFactory.hasReplicas(originEndpoint));
- assertTrue(clientFactory.hasReplicas(replica1));
- assertFalse(clientFactory.hasReplicas(invalidReplica));
- assertFalse(clientFactory.hasReplicas(noReplicaEndpoint));
- }
-
}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClientTest.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClientTest.java
index 99c71ea169a0..9e328cffd751 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClientTest.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationReplicaClientTest.java
@@ -37,7 +37,6 @@
import com.azure.core.http.rest.PagedResponse;
import com.azure.core.http.rest.PagedResponseBase;
import com.azure.core.http.rest.Response;
-import com.azure.core.util.Configuration;
import com.azure.data.appconfiguration.ConfigurationClient;
import com.azure.data.appconfiguration.models.ConfigurationSetting;
import com.azure.data.appconfiguration.models.ConfigurationSnapshot;
@@ -45,7 +44,6 @@
import com.azure.data.appconfiguration.models.SettingSelector;
import com.azure.data.appconfiguration.models.SnapshotComposition;
import com.azure.identity.CredentialUnavailableException;
-import com.azure.spring.cloud.appconfiguration.config.implementation.http.policy.TracingInfo;
import reactor.core.publisher.Mono;
@@ -67,7 +65,10 @@ public class AppConfigurationReplicaClientTest {
private Supplier>> supplierMock;
@Mock
- private Response mockResponse;
+ private Response configurationSettingResponse;
+
+ @Mock
+ private Response snapshotResponseMock;
private final String endpoint = "clientTest.azconfig.io";
@@ -87,20 +88,17 @@ public void cleanup() throws Exception {
@Test
public void getWatchKeyTest() {
- AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock,
- new TracingInfo(false, false, 0, Configuration.getGlobalConfiguration()));
+ AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock);
ConfigurationSetting watchKey = new ConfigurationSetting().setKey("watch").setLabel("\0");
- when(clientMock.getConfigurationSettingWithResponse(Mockito.any(), Mockito.isNull(), Mockito.anyBoolean(),
- Mockito.any())).thenReturn(mockResponse);
- when(mockResponse.getValue()).thenReturn(watchKey);
+ when(clientMock.getConfigurationSettingWithResponse(Mockito.any(), Mockito.any(), Mockito.anyBoolean(),
+ Mockito.any())).thenReturn(configurationSettingResponse);
+ when(configurationSettingResponse.getValue()).thenReturn(watchKey);
- //assertEquals(watchKey, client.getWatchKey("watch", "\0", false));
+ assertEquals(watchKey, client.getWatchKey("watch", "\0", false));
- when(clientMock.getConfigurationSettingWithResponse(Mockito.any(), Mockito.isNull(), Mockito.anyBoolean(),
- Mockito.any())).thenReturn(mockResponse);
- when(mockResponse.getValue()).thenThrow(exceptionMock);
+ when(configurationSettingResponse.getValue()).thenThrow(exceptionMock);
when(exceptionMock.getResponse()).thenReturn(responseMock);
when(responseMock.getStatusCode()).thenReturn(429);
assertThrows(AppConfigurationStatusException.class, () -> client.getWatchKey("watch", "\0", false));
@@ -114,15 +112,14 @@ public void getWatchKeyTest() {
when(responseMock.getStatusCode()).thenReturn(499);
assertThrows(HttpResponseException.class, () -> client.getWatchKey("watch", "\0", false));
- when(clientMock.getConfigurationSettingWithResponse(Mockito.any(), Mockito.isNull(), Mockito.anyBoolean(),
+ when(clientMock.getConfigurationSettingWithResponse(Mockito.any(), Mockito.any(), Mockito.anyBoolean(),
Mockito.any())).thenThrow(new UncheckedIOException(new UnknownHostException()));
assertThrows(AppConfigurationStatusException.class, () -> client.getWatchKey("watch", "\0", false));
}
@Test
public void listSettingsTest() {
- AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock,
- new TracingInfo(false, false, 0, Configuration.getGlobalConfiguration()));
+ AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock);
ConfigurationSetting configurationSetting = new ConfigurationSetting().setKey("test-key");
List configurations = List.of(configurationSetting);
@@ -154,8 +151,7 @@ public void listSettingsTest() {
@Test
public void listFeatureFlagsTest() {
- AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock,
- new TracingInfo(false, false, 0, Configuration.getGlobalConfiguration()));
+ AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock);
FeatureFlagConfigurationSetting featureFlag = new FeatureFlagConfigurationSetting("Alpha", false);
List configurations = List.of(featureFlag);
@@ -192,8 +188,7 @@ public void listFeatureFlagsTest() {
@Test
public void listSettingsUnknownHostTest() {
- AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock,
- new TracingInfo(false, false, 0, Configuration.getGlobalConfiguration()));
+ AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock);
when(clientMock.listConfigurationSettings(Mockito.any(), Mockito.any()))
.thenThrow(new UncheckedIOException(new UnknownHostException()));
@@ -202,8 +197,7 @@ public void listSettingsUnknownHostTest() {
@Test
public void listSettingsNoCredentialTest() {
- AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock,
- new TracingInfo(false, false, 0, Configuration.getGlobalConfiguration()));
+ AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock);
when(clientMock.listConfigurationSettings(Mockito.any(), Mockito.any()))
.thenThrow(new CredentialUnavailableException("No Credential"));
@@ -213,12 +207,9 @@ public void listSettingsNoCredentialTest() {
@Test
public void getWatchNoCredentialTest() {
- AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock,
- new TracingInfo(false, false, 0, Configuration.getGlobalConfiguration()));
+ AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock);
- when(clientMock.getConfigurationSettingWithResponse(Mockito.any(), Mockito.isNull(), Mockito.anyBoolean(),
- Mockito.any())).thenReturn(mockResponse);
- when(mockResponse.getValue())
+ when(clientMock.getConfigurationSettingWithResponse(Mockito.any(), Mockito.any(), Mockito.anyBoolean(), Mockito.any()))
.thenThrow(new CredentialUnavailableException("No Credential"));
assertThrows(CredentialUnavailableException.class, () -> client.getWatchKey("key", "label", false));
@@ -226,8 +217,7 @@ public void getWatchNoCredentialTest() {
@Test
public void backoffTest() {
- AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock,
- new TracingInfo(false, false, 0, Configuration.getGlobalConfiguration()));
+ AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock);
// Setups in the past and with no errors.
assertTrue(client.getBackoffEndTime().isBefore(Instant.now()));
@@ -255,55 +245,57 @@ public void backoffTest() {
@Test
public void listSettingSnapshotTest() {
- AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock,
- new TracingInfo(false, false, 0, Configuration.getGlobalConfiguration()));
+ AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock);
List configurations = new ArrayList<>();
ConfigurationSnapshot snapshot = new ConfigurationSnapshot(null);
snapshot.setSnapshotComposition(SnapshotComposition.KEY);
- when(clientMock.getSnapshot(Mockito.any())).thenReturn(snapshot);
+ when(clientMock.getSnapshotWithResponse(Mockito.any(), Mockito.any(), Mockito.any()))
+ .thenReturn(snapshotResponseMock);
+ when(snapshotResponseMock.getValue()).thenReturn(snapshot);
when(clientMock.listConfigurationSettingsForSnapshot(Mockito.any())).thenReturn(settingsMock);
- assertEquals(configurations, client.listSettingSnapshot("SnapshotName"));
+ assertEquals(configurations, client.listSettingSnapshot("SnapshotName", false));
when(clientMock.listConfigurationSettingsForSnapshot(Mockito.any())).thenThrow(exceptionMock);
when(exceptionMock.getResponse()).thenReturn(responseMock);
when(responseMock.getStatusCode()).thenReturn(429);
- assertThrows(AppConfigurationStatusException.class, () -> client.listSettingSnapshot("SnapshotName"));
+ assertThrows(AppConfigurationStatusException.class, () -> client.listSettingSnapshot("SnapshotName", false));
when(responseMock.getStatusCode()).thenReturn(408);
- assertThrows(AppConfigurationStatusException.class, () -> client.listSettingSnapshot("SnapshotName"));
+ assertThrows(AppConfigurationStatusException.class, () -> client.listSettingSnapshot("SnapshotName", false));
when(responseMock.getStatusCode()).thenReturn(500);
- assertThrows(AppConfigurationStatusException.class, () -> client.listSettingSnapshot("SnapshotName"));
+ assertThrows(AppConfigurationStatusException.class, () -> client.listSettingSnapshot("SnapshotName", false));
when(responseMock.getStatusCode()).thenReturn(499);
- assertThrows(HttpResponseException.class, () -> client.listSettingSnapshot("SnapshotName"));
+ assertThrows(HttpResponseException.class, () -> client.listSettingSnapshot("SnapshotName", false));
- when(clientMock.getSnapshot(Mockito.any())).thenThrow(new UncheckedIOException(new UnknownHostException()));
- assertThrows(AppConfigurationStatusException.class, () -> client.listSettingSnapshot("SnapshotName"));
+ when(clientMock.getSnapshotWithResponse(Mockito.any(), Mockito.any(), Mockito.any()))
+ .thenThrow(new UncheckedIOException(new UnknownHostException()));
+ assertThrows(AppConfigurationStatusException.class, () -> client.listSettingSnapshot("SnapshotName", false));
}
@Test
public void listSettingSnapshotInvalidCompositionTypeTest() {
- AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock,
- new TracingInfo(false, false, 0, Configuration.getGlobalConfiguration()));
+ AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock);
ConfigurationSnapshot snapshot = new ConfigurationSnapshot(null);
snapshot.setSnapshotComposition(SnapshotComposition.KEY_LABEL);
- when(clientMock.getSnapshot(Mockito.any())).thenReturn(snapshot);
+ when(clientMock.getSnapshotWithResponse(Mockito.any(), Mockito.any(), Mockito.any()))
+ .thenReturn(snapshotResponseMock);
+ when(snapshotResponseMock.getValue()).thenReturn(snapshot);
IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
- () -> client.listSettingSnapshot("SnapshotName"));
+ () -> client.listSettingSnapshot("SnapshotName", false));
assertEquals("Snapshot SnapshotName needs to be of type Key.", e.getMessage());
}
@Test
public void updateSyncTokenTest() {
- AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock,
- new TracingInfo(false, false, 0, Configuration.getGlobalConfiguration()));
+ AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock);
String fakeToken = "fake_sync_token";
client.updateSyncToken(fakeToken);
@@ -316,8 +308,7 @@ public void updateSyncTokenTest() {
@Test
public void checkWatchKeysTest() {
- AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock,
- new TracingInfo(false, false, 0, Configuration.getGlobalConfiguration()));
+ AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock);
FeatureFlagConfigurationSetting featureFlag = new FeatureFlagConfigurationSetting("Alpha", false);
List configurations = List.of(featureFlag);
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/ConnectionManagerTest.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/ConnectionManagerTest.java
index ff6a30fed45b..bdaa51cecaf7 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/ConnectionManagerTest.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/ConnectionManagerTest.java
@@ -4,7 +4,6 @@
import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_ENDPOINT;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -118,8 +117,6 @@ public void backoffTest() {
expectedEndpoints.add(replicaEndpoint);
assertEquals(2, connectionManager.getAvailableClients().size());
- assertEquals(2, connectionManager.getAllEndpoints().size());
- assertTrue(connectionManager.getAllEndpoints().containsAll(expectedEndpoints));
assertEquals(AppConfigurationStoreHealth.UP, connectionManager.getHealth());
connectionManager.backoffClient(originEndpoint);
@@ -129,15 +126,11 @@ public void backoffTest() {
when(replicaClient1.getBackoffEndTime()).thenReturn(Instant.now().plusSeconds(1000));
assertEquals(1, connectionManager.getAvailableClients().size());
- assertEquals(2, connectionManager.getAllEndpoints().size());
- assertTrue(connectionManager.getAllEndpoints().containsAll(expectedEndpoints));
assertEquals(AppConfigurationStoreHealth.UP, connectionManager.getHealth());
connectionManager.backoffClient(originEndpoint);
assertEquals(1, connectionManager.getAvailableClients().size());
- assertEquals(2, connectionManager.getAllEndpoints().size());
- assertTrue(connectionManager.getAllEndpoints().containsAll(expectedEndpoints));
assertEquals(AppConfigurationStoreHealth.UP, connectionManager.getHealth());
connectionManager.backoffClient(replicaEndpoint);
@@ -146,8 +139,6 @@ public void backoffTest() {
when(replicaClient2.getBackoffEndTime()).thenReturn(Instant.now().plusSeconds(1000));
assertEquals(0, connectionManager.getAvailableClients().size());
- assertEquals(2, connectionManager.getAllEndpoints().size());
- assertTrue(connectionManager.getAllEndpoints().containsAll(expectedEndpoints));
assertEquals(AppConfigurationStoreHealth.DOWN, connectionManager.getHealth());
}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/FeatureFlagClientTest.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/FeatureFlagClientTest.java
index f473388bd8c3..07c2e5a56fa2 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/FeatureFlagClientTest.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/FeatureFlagClientTest.java
@@ -2,18 +2,18 @@
// Licensed under the MIT License.
package com.azure.spring.cloud.appconfiguration.config.implementation;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationConstants.DEFAULT_ROLLOUT_PERCENTAGE;
import static com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationConstants.E_TAG;
import static com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationConstants.FEATURE_FLAG_CONTENT_TYPE;
import static com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationConstants.FEATURE_FLAG_ID;
import static com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationConstants.FEATURE_FLAG_REFERENCE;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationConstants.GROUPS;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationConstants.USERS;
+import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.DEFAULT_ROLLOUT_PERCENTAGE;
import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.FEATURE_LABEL;
+import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.FEATURE_VALUE_ALL;
import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.FEATURE_VALUE_TELEMETRY;
+import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.GROUPS;
import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_ENDPOINT;
import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_E_TAG;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.FEATURE_VALUE_ALL;
+import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.USERS;
import static com.azure.spring.cloud.appconfiguration.config.implementation.TestUtils.createItemFeatureFlag;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -78,8 +78,7 @@ public void loadFeatureFlagsTestNoFeatureFlags() {
FeatureFlags featureFlags = new FeatureFlags(null, settings);
when(clientMock.listFeatureFlags(Mockito.any(), Mockito.anyBoolean())).thenReturn(featureFlags);
- List featureFlagsList = featureFlagClient.loadFeatureFlags(clientMock, null, emptyLabelList,
- false);
+ List featureFlagsList = featureFlagClient.loadFeatureFlags(clientMock, null, emptyLabelList, false);
assertEquals(1, featureFlagsList.size());
assertEquals(featureFlags, featureFlagsList.get(0));
assertEquals("FakeKey", featureFlagsList.get(0).getFeatureFlags().get(0).getKey());
@@ -93,8 +92,7 @@ public void loadFeatureFlagsTestFeatureFlags() {
FeatureFlags featureFlags = new FeatureFlags(null, settings);
when(clientMock.listFeatureFlags(Mockito.any(), Mockito.anyBoolean())).thenReturn(featureFlags);
- List featureFlagsList = featureFlagClient.loadFeatureFlags(clientMock, null, emptyLabelList,
- false);
+ List featureFlagsList = featureFlagClient.loadFeatureFlags(clientMock, null, emptyLabelList, false);
assertEquals(1, featureFlagsList.size());
assertEquals(featureFlags, featureFlagsList.get(0));
assertEquals(".appconfig.featureflag/Alpha", featureFlagsList.get(0).getFeatureFlags().get(0).getKey());
@@ -109,8 +107,7 @@ public void loadFeatureFlagsTestMultipleLoads() {
FeatureFlags featureFlags = new FeatureFlags(null, settings);
when(clientMock.listFeatureFlags(Mockito.any(), Mockito.anyBoolean())).thenReturn(featureFlags);
- List featureFlagsList = featureFlagClient.loadFeatureFlags(clientMock, null, emptyLabelList,
- false);
+ List featureFlagsList = featureFlagClient.loadFeatureFlags(clientMock, null, emptyLabelList, false);
assertEquals(1, featureFlagsList.size());
assertEquals(featureFlags, featureFlagsList.get(0));
assertEquals(".appconfig.featureflag/Alpha", featureFlagsList.get(0).getFeatureFlags().get(0).getKey());
@@ -168,8 +165,7 @@ public void loadFeatureFlagsTestTargetingFilter() {
FeatureFlags featureFlags = new FeatureFlags(null, settings);
when(clientMock.listFeatureFlags(Mockito.any(), Mockito.anyBoolean())).thenReturn(featureFlags);
- List featureFlagsList = featureFlagClient.loadFeatureFlags(clientMock, null, emptyLabelList,
- false);
+ List featureFlagsList = featureFlagClient.loadFeatureFlags(clientMock, null, emptyLabelList, false);
assertEquals(1, featureFlagsList.size());
assertEquals(featureFlags, featureFlagsList.get(0));
assertEquals(".appconfig.featureflag/TargetingTest", featureFlagsList.get(0).getFeatureFlags().get(0).getKey());
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/StateHolderTest.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/StateHolderTest.java
index 184a33374bb7..3b10d736f8ec 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/StateHolderTest.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/StateHolderTest.java
@@ -180,7 +180,7 @@ private void updateNextRefreshBackoffCalcTest(TestInfo testInfo) {
private void loadStateTest(TestInfo testInfo) {
String endpoint = testInfo.getDisplayName() + "updateRefreshTimeBackoffCalc" + ".azconfig.io";
StateHolder testStateHolder = new StateHolder();
- testStateHolder.setLoadState(endpoint, true, false);
+ testStateHolder.setLoadState(endpoint, true);
StateHolder.updateState(testStateHolder);
assertEquals(testStateHolder.getLoadState().get(endpoint), StateHolder.getLoadState(endpoint));
assertEquals(testStateHolder, StateHolder.getCurrentState());
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/TestConstants.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/TestConstants.java
index 63903d1ef5ec..48e379747e3b 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/TestConstants.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/TestConstants.java
@@ -6,6 +6,22 @@
* Test constants which can be shared across different test classes
*/
public final class TestConstants {
+
+ /**
+ * Http Header Correlation Context
+ */
+ public static final String CORRELATION_CONTEXT = "Correlation-Context";
+
+ /**
+ * App Configurations Key Vault Reference Content Type
+ */
+ public static final String KEY_VAULT_CONTENT_TYPE = "application/vnd.microsoft.appconfig.keyvaultref+json;charset=utf-8";
+
+ public static final String USERS = "users";
+
+ public static final String GROUPS = "groups";
+
+ public static final String DEFAULT_ROLLOUT_PERCENTAGE = "defaultRolloutPercentage";
// Store specific configuration
public static final String TEST_STORE_NAME = "store1";
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/config/AppConfigurationBootstrapConfigurationTest.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/config/AppConfigurationBootstrapConfigurationTest.java
deleted file mode 100644
index 93202173f069..000000000000
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/config/AppConfigurationBootstrapConfigurationTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-package com.azure.spring.cloud.appconfiguration.config.implementation.config;
-
-import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.CONN_STRING_PROP;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.FAIL_FAST_PROP;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.STORE_ENDPOINT_PROP;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_CONN_STRING;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_STORE_NAME;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.TestUtils.propPair;
-import static org.assertj.core.api.Assertions.assertThat;
-
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.test.context.runner.ApplicationContextRunner;
-
-import com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationPropertySourceLocator;
-import com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationReplicaClientFactory;
-import com.azure.spring.cloud.autoconfigure.implementation.context.AzureGlobalPropertiesAutoConfiguration;
-
-public class AppConfigurationBootstrapConfigurationTest {
-
- private static final ApplicationContextRunner CONTEXT_RUNNER = new ApplicationContextRunner()
- .withConfiguration(AutoConfigurations.of(AppConfigurationBootstrapConfiguration.class,
- AzureGlobalPropertiesAutoConfiguration.class))
- .withPropertyValues(propPair("spring.cloud.azure.appconfiguration.enabled", "true"));
-
- @Test
- public void iniConnectionStringSystemAssigned() {
- CONTEXT_RUNNER
- .withPropertyValues(propPair(STORE_ENDPOINT_PROP, TEST_STORE_NAME), propPair(FAIL_FAST_PROP, "false"))
- .run(context -> assertThat(context).hasSingleBean(AppConfigurationPropertySourceLocator.class));
- }
-
- @Test
- public void iniConnectionStringUserAssigned() {
- CONTEXT_RUNNER
- .withPropertyValues(propPair(STORE_ENDPOINT_PROP, TEST_STORE_NAME), propPair(FAIL_FAST_PROP, "false"),
- propPair("spring.cloud.azure.appconfiguration.managed-identity.client-id", "client-id"))
- .run(context -> assertThat(context).hasSingleBean(AppConfigurationPropertySourceLocator.class));
- }
-
- @Test
- public void propertySourceLocatorBeanCreated() {
- CONTEXT_RUNNER
- .withPropertyValues(propPair(CONN_STRING_PROP, TEST_CONN_STRING), propPair(FAIL_FAST_PROP, "false"))
- .run(context -> assertThat(context).hasSingleBean(AppConfigurationPropertySourceLocator.class));
- }
-
- @Test
- public void clientsBeanCreated() {
- CONTEXT_RUNNER
- .withPropertyValues(propPair(CONN_STRING_PROP, TEST_CONN_STRING))
- .run(context -> assertThat(context).hasSingleBean(AppConfigurationReplicaClientFactory.class));
- }
-}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/http/policy/BaseAppConfigurationPolicyTest.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/http/policy/BaseAppConfigurationPolicyTest.java
index c08c29975ffa..d3bfdea27cef 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/http/policy/BaseAppConfigurationPolicyTest.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/http/policy/BaseAppConfigurationPolicyTest.java
@@ -2,10 +2,7 @@
// Licensed under the MIT License.
package com.azure.spring.cloud.appconfiguration.config.implementation.http.policy;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationConstants.CORRELATION_CONTEXT;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationConstants.DEV_ENV_TRACING;
import static com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationConstants.KEY_VAULT_CONFIGURED_TRACING;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationConstants.USER_AGENT_TYPE;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;
@@ -24,11 +21,13 @@
import org.mockito.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;
+import com.azure.core.http.HttpHeaderName;
import com.azure.core.http.HttpMethod;
import com.azure.core.http.HttpPipelineCallContext;
import com.azure.core.http.HttpPipelineNextPolicy;
import com.azure.core.http.HttpRequest;
import com.azure.core.util.Configuration;
+import com.azure.spring.cloud.appconfiguration.config.implementation.RequestTracingConstants;
// This test class needs to be isolated and ran sequential as it uses BaseAppConfigurationPolicy.setWatchRequests
// which mutates a global static and can result in race condition failures.
@@ -55,27 +54,28 @@ public void cleanup() throws Exception {
MockitoAnnotations.openMocks(this).close();
}
- @SuppressWarnings("deprecation")
@Test
public void startupThenWatchUpdateTest() throws MalformedURLException {
URL url = new URL("https://www.test.url/kv");
HttpRequest request = new HttpRequest(HttpMethod.GET, url);
- request.setHeader(USER_AGENT_TYPE, "PreExistingUserAgent");
+ request.setHeader(HttpHeaderName.USER_AGENT, "PreExistingUserAgent");
BaseAppConfigurationPolicy policy = new BaseAppConfigurationPolicy(
- new TracingInfo(false, false, 0, Configuration.getGlobalConfiguration()));
+ new TracingInfo(false, 0, Configuration.getGlobalConfiguration()));
when(contextMock.getHttpRequest()).thenReturn(request);
policy.process(contextMock, nextMock);
- String userAgent = contextMock.getHttpRequest().getHeaders().get(USER_AGENT_TYPE).getValue();
+ String userAgent = contextMock.getHttpRequest().getHeaders().get(HttpHeaderName.USER_AGENT).getValue();
assertEquals("null/null " + PRE_USER_AGENT, userAgent);
assertEquals("RequestType=Startup",
- contextMock.getHttpRequest().getHeaders().get(CORRELATION_CONTEXT).getValue());
+ contextMock.getHttpRequest().getHeaders()
+ .get(HttpHeaderName.fromString(RequestTracingConstants.CORRELATION_CONTEXT_HEADER.toString()))
+ .getValue());
request = new HttpRequest(HttpMethod.GET, url);
- request.setHeader(USER_AGENT_TYPE, "PreExistingUserAgent");
+ request.setHeader(HttpHeaderName.USER_AGENT, "PreExistingUserAgent");
when(contextMock.getHttpRequest()).thenReturn(request);
when(contextMock.getData("refresh")).thenReturn(Optional.of(true));
@@ -85,10 +85,12 @@ public void startupThenWatchUpdateTest() throws MalformedURLException {
assertEquals("null/null " + PRE_USER_AGENT, userAgent);
assertEquals("RequestType=Watch",
- contextMock.getHttpRequest().getHeaders().get(CORRELATION_CONTEXT).getValue());
+ contextMock.getHttpRequest().getHeaders()
+ .get(HttpHeaderName.fromString(RequestTracingConstants.CORRELATION_CONTEXT_HEADER.toString()))
+ .getValue());
request = new HttpRequest(HttpMethod.GET, url);
- request.setHeader(USER_AGENT_TYPE, "PreExistingUserAgent");
+ request.setHeader(HttpHeaderName.USER_AGENT, "PreExistingUserAgent");
when(contextMock.getHttpRequest()).thenReturn(request);
@@ -96,55 +98,26 @@ public void startupThenWatchUpdateTest() throws MalformedURLException {
assertEquals("null/null " + PRE_USER_AGENT, userAgent);
assertEquals("RequestType=Watch",
- contextMock.getHttpRequest().getHeaders().get(CORRELATION_CONTEXT).getValue());
+ contextMock.getHttpRequest().getHeaders()
+ .get(HttpHeaderName.fromString(RequestTracingConstants.CORRELATION_CONTEXT_HEADER.toString()))
+ .getValue());
}
- @SuppressWarnings("deprecation")
- @Test
- public void devIsConfigured() throws MalformedURLException {
- BaseAppConfigurationPolicy policy = new BaseAppConfigurationPolicy(
- new TracingInfo(true, false, 0, Configuration.getGlobalConfiguration()));
-
- URL url = new URL("https://www.test.url/kv");
- HttpRequest request = new HttpRequest(HttpMethod.GET, url);
- request.setHeader(USER_AGENT_TYPE, "PreExistingUserAgent");
- when(contextMock.getHttpRequest()).thenReturn(request);
-
- policy.process(contextMock, nextMock);
- assertEquals("RequestType=Startup,Env=" + DEV_ENV_TRACING,
- contextMock.getHttpRequest().getHeaders().get(CORRELATION_CONTEXT).getValue());
- }
-
- @SuppressWarnings("deprecation")
@Test
public void keyVaultIsConfigured() throws MalformedURLException {
BaseAppConfigurationPolicy policy = new BaseAppConfigurationPolicy(
- new TracingInfo(false, true, 0, Configuration.getGlobalConfiguration()));
+ new TracingInfo(true, 0, Configuration.getGlobalConfiguration()));
URL url = new URL("https://www.test.url/kv");
HttpRequest request = new HttpRequest(HttpMethod.GET, url);
- request.setHeader(USER_AGENT_TYPE, "PreExistingUserAgent");
+ request.setHeader(HttpHeaderName.USER_AGENT, "PreExistingUserAgent");
when(contextMock.getHttpRequest()).thenReturn(request);
policy.process(contextMock, nextMock);
assertEquals("RequestType=Startup," + KEY_VAULT_CONFIGURED_TRACING,
- contextMock.getHttpRequest().getHeaders().get(CORRELATION_CONTEXT).getValue());
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void devAndKeyVaultAreConfigured() throws MalformedURLException {
- BaseAppConfigurationPolicy policy = new BaseAppConfigurationPolicy(
- new TracingInfo(true, true, 0, Configuration.getGlobalConfiguration()));
-
- URL url = new URL("https://www.test.url/kv");
- HttpRequest request = new HttpRequest(HttpMethod.GET, url);
- request.setHeader(USER_AGENT_TYPE, "PreExistingUserAgent");
- when(contextMock.getHttpRequest()).thenReturn(request);
-
- policy.process(contextMock, nextMock);
- assertEquals("RequestType=Startup,Env=" + DEV_ENV_TRACING + "," + KEY_VAULT_CONFIGURED_TRACING,
- contextMock.getHttpRequest().getHeaders().get(CORRELATION_CONTEXT).getValue());
+ contextMock.getHttpRequest().getHeaders()
+ .get(HttpHeaderName.fromString(RequestTracingConstants.CORRELATION_CONTEXT_HEADER.toString()))
+ .getValue());
}
}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/http/policy/TracingInfoTest.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/http/policy/TracingInfoTest.java
index 67c3aba02153..2bdcdd238590 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/http/policy/TracingInfoTest.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/http/policy/TracingInfoTest.java
@@ -23,20 +23,17 @@ public class TracingInfoTest {
public void getValueTest() {
Configuration configuration = getConfiguration("false");
- TracingInfo tracingInfo = new TracingInfo(false, false, 0, configuration);
+ TracingInfo tracingInfo = new TracingInfo(false, 0, configuration);
assertEquals("RequestType=Startup", tracingInfo.getValue(false));
assertEquals("RequestType=Watch", tracingInfo.getValue(true));
- tracingInfo = new TracingInfo(true, false, 0, configuration);
- assertEquals("RequestType=Startup,Env=Dev", tracingInfo.getValue(false));
-
- tracingInfo = new TracingInfo(false, true, 0, configuration);
+ tracingInfo = new TracingInfo(true, 0, configuration);
assertEquals("RequestType=Startup,UsesKeyVault", tracingInfo.getValue(false));
- tracingInfo = new TracingInfo(false, false, 1, configuration);
+ tracingInfo = new TracingInfo(false, 1, configuration);
assertEquals("RequestType=Startup,ReplicaCount=1", tracingInfo.getValue(false));
- tracingInfo = new TracingInfo(false, false, 0, configuration);
+ tracingInfo = new TracingInfo(false, 0, configuration);
tracingInfo.getFeatureFlagTracing().updateFeatureFilterTelemetry("Random");
assertEquals("RequestType=Startup,Filter=CSTM", tracingInfo.getValue(false));
@@ -44,19 +41,19 @@ public void getValueTest() {
@Test
public void disableTracingTest() {
- TracingInfo tracingInfo = new TracingInfo(false, false, 0, getConfiguration(null));
+ TracingInfo tracingInfo = new TracingInfo(false, 0, getConfiguration(null));
assertNotEquals("", tracingInfo.getValue(false));
- tracingInfo = new TracingInfo(false, false, 0, getConfiguration(""));
+ tracingInfo = new TracingInfo(false, 0, getConfiguration(""));
assertNotEquals("", tracingInfo.getValue(false));
- tracingInfo = new TracingInfo(false, false, 0, getConfiguration("true"));
+ tracingInfo = new TracingInfo(false, 0, getConfiguration("true"));
assertEquals("", tracingInfo.getValue(false));
- tracingInfo = new TracingInfo(false, false, 0, getConfiguration("false"));
+ tracingInfo = new TracingInfo(false, 0, getConfiguration("false"));
assertNotEquals("", tracingInfo.getValue(false));
- tracingInfo = new TracingInfo(false, false, 0, getConfiguration("random string"));
+ tracingInfo = new TracingInfo(false, 0, getConfiguration("random string"));
assertNotEquals("", tracingInfo.getValue(false));
}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/AppConfigurationPropertiesTest.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/AppConfigurationPropertiesTest.java
index e8d839e22faa..6641e1ee7108 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/AppConfigurationPropertiesTest.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/properties/AppConfigurationPropertiesTest.java
@@ -2,35 +2,18 @@
// Licensed under the MIT License.
package com.azure.spring.cloud.appconfiguration.config.implementation.properties;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationReplicaClientsBuilder.ENDPOINT_ERR_MSG;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.CONN_STRING_PROP;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.CONN_STRING_PROP_NEW;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.FAIL_FAST_PROP;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.KEY_PROP;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.LABEL_PROP;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.REFRESH_INTERVAL_PROP;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.STORE_ENDPOINT_PROP;
import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_CONN_STRING;
import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_ENDPOINT;
import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_ENDPOINT_GEO;
-import static com.azure.spring.cloud.appconfiguration.config.implementation.TestUtils.propPair;
-import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
-import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.mockito.MockitoAnnotations;
-import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.test.context.runner.ApplicationContextRunner;
-
-import com.azure.spring.cloud.appconfiguration.config.implementation.config.AppConfigurationBootstrapConfiguration;
-import com.azure.spring.cloud.autoconfigure.implementation.context.AzureGlobalPropertiesAutoConfiguration;
public class AppConfigurationPropertiesTest {
@@ -43,29 +26,21 @@ public class AppConfigurationPropertiesTest {
private static final String VALID_KEY = "/application/";
private static final String ILLEGAL_LABELS = "*,my-label";
+
+ private AppConfigurationProperties properties;
- @InjectMocks
- private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
- .withConfiguration(AutoConfigurations.of(AppConfigurationBootstrapConfiguration.class,
- AzureGlobalPropertiesAutoConfiguration.class))
- .withPropertyValues("spring.cloud.azure.appconfiguration.endpoint=https://test-appconfig.azconfig.io");
@BeforeEach
public void setup() {
- MockitoAnnotations.openMocks(this);
- }
-
- @AfterEach
- public void cleanup() throws Exception {
- MockitoAnnotations.openMocks(this).close();
+ properties = new AppConfigurationProperties();
+ properties.setStores(List.of(new ConfigStore()));
}
@Test
public void validInputShouldCreatePropertiesBean() {
- this.contextRunner
- .withPropertyValues(propPair(CONN_STRING_PROP, TEST_CONN_STRING))
- .withPropertyValues(propPair(FAIL_FAST_PROP, "false"))
- .run(context -> assertThat(context).hasSingleBean(AppConfigurationProperties.class));
+ ConfigStore store = properties.getStores().get(0);
+ store.setConnectionString(TEST_CONN_STRING);
+ store.validateAndInit();
}
@Test
@@ -84,55 +59,54 @@ public void secretMustExistInConnectionString() {
}
private void testConnStringFields(String connString) {
- this.contextRunner
- .withPropertyValues(propPair(CONN_STRING_PROP, connString))
- .run(context -> assertThat(context).getFailure().hasStackTraceContaining(ENDPOINT_ERR_MSG));
+ ConfigStore store = properties.getStores().get(0);
+ store.setConnectionString(connString);
+ IllegalStateException e = assertThrows(IllegalStateException.class, () -> properties.validateAndInit());
+ assertEquals("Connection string does not follow format Endpoint=([^;]+);Id=([^;]+);Secret=([^;]+).", e.getMessage());
}
@Test
public void asteriskShouldNotBeIncludedInTheLabels() {
- this.contextRunner
- .withPropertyValues(
- propPair(CONN_STRING_PROP, TEST_CONN_STRING),
- propPair(KEY_PROP, VALID_KEY),
- propPair(LABEL_PROP, ILLEGAL_LABELS))
- .run(context -> assertThat(context)
- .getFailure()
- .hasStackTraceContaining("LabelFilter must not contain asterisk(*)"));
+ ConfigStore store = properties.getStores().get(0);
+ store.setConnectionString(TEST_CONN_STRING);
+ AppConfigurationKeyValueSelector select = new AppConfigurationKeyValueSelector();
+ select.setKeyFilter(VALID_KEY);
+ select.setLabelFilter(ILLEGAL_LABELS);
+ store.setSelects(List.of(select));
+ IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> properties.validateAndInit());
+ assertEquals("LabelFilter must not contain asterisk(*)", e.getMessage());
}
@Test
public void storeNameCanBeInitIfConnectionStringConfigured() {
- this.contextRunner
- .withPropertyValues(
- propPair(CONN_STRING_PROP, TEST_CONN_STRING),
- propPair(STORE_ENDPOINT_PROP, ""))
- .withPropertyValues(propPair(FAIL_FAST_PROP, "false"))
- .run(context -> {
- AppConfigurationProperties properties = context.getBean(AppConfigurationProperties.class);
- assertThat(properties.getStores()).isNotNull();
- assertThat(properties.getStores().size()).isEqualTo(1);
- assertThat(properties.getStores().get(0).getEndpoint()).isEqualTo("https://fake.test.config.io");
- });
+ ConfigStore store = properties.getStores().get(0);
+ store.setConnectionString(TEST_CONN_STRING);
+ store.setEndpoint("");
+ store.validateAndInit();
+ assertEquals(1, properties.getStores().size());
+ assertEquals("https://fake.test.config.io", properties.getStores().get(0).getEndpoint());
}
@Test
public void duplicateConnectionStringIsNotAllowed() {
- this.contextRunner
- .withPropertyValues(
- propPair(CONN_STRING_PROP, TEST_CONN_STRING),
- propPair(CONN_STRING_PROP_NEW, TEST_CONN_STRING))
- .run(context -> assertThat(context)
- .getFailure()
- .hasStackTraceContaining("Duplicate store name exists"));
+ properties = new AppConfigurationProperties();
+ properties.setStores(List.of(new ConfigStore(), new ConfigStore()));
+
+ ConfigStore store = properties.getStores().get(0);
+ store.setConnectionString(TEST_CONN_STRING);
+ ConfigStore newStore = properties.getStores().get(1);
+ newStore.setConnectionString(TEST_CONN_STRING);
+
+ java.lang.IllegalArgumentException e = assertThrows(java.lang.IllegalArgumentException.class, () -> properties.validateAndInit());
+ assertEquals("Duplicate store name exists.", e.getMessage());
}
@Test
public void minValidWatchTime() {
- this.contextRunner
- .withPropertyValues(propPair(CONN_STRING_PROP, TEST_CONN_STRING))
- .withPropertyValues(propPair(REFRESH_INTERVAL_PROP, "1s"))
- .run(context -> assertThat(context).hasSingleBean(AppConfigurationProperties.class));
+ ConfigStore store = properties.getStores().get(0);
+ store.setConnectionString(TEST_CONN_STRING);
+ properties.setRefreshInterval(Duration.ofSeconds(1));
+ properties.validateAndInit();
}
@Test
diff --git a/sdk/spring/spring-cloud-azure-feature-management/src/test/java/com/azure/spring/cloud/feature/management/ValidationsTest.java b/sdk/spring/spring-cloud-azure-feature-management/src/test/java/com/azure/spring/cloud/feature/management/ValidationsTest.java
deleted file mode 100644
index 35d43967f85e..000000000000
--- a/sdk/spring/spring-cloud-azure-feature-management/src/test/java/com/azure/spring/cloud/feature/management/ValidationsTest.java
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-package com.azure.spring.cloud.feature.management;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.mockito.Mockito.when;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.nio.file.Files;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.stream.Stream;
-
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.Arguments;
-import org.junit.jupiter.params.provider.MethodSource;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.context.ApplicationContext;
-import org.springframework.test.context.junit.jupiter.SpringExtension;
-
-import com.azure.spring.cloud.feature.management.filters.TargetingFilter;
-import com.azure.spring.cloud.feature.management.filters.TargetingFilterTestContextAccessor;
-import com.azure.spring.cloud.feature.management.filters.TimeWindowFilter;
-import com.azure.spring.cloud.feature.management.implementation.FeatureManagementConfigProperties;
-import com.azure.spring.cloud.feature.management.implementation.FeatureManagementProperties;
-import com.azure.spring.cloud.feature.management.validationstests.models.ValidationTestCase;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.MapperFeature;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.json.JsonMapper;
-import com.fasterxml.jackson.databind.type.CollectionType;
-import com.fasterxml.jackson.databind.type.TypeFactory;
-
-@ExtendWith(SpringExtension.class)
-public class ValidationsTest {
- @Mock
- private ApplicationContext context;
-
- @Mock
- private FeatureManagementConfigProperties configProperties;
-
- private static final Logger LOGGER = LoggerFactory.getLogger(ValidationsTest.class);
-
- private static final ObjectMapper OBJECT_MAPPER = JsonMapper.builder()
- .configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true).build();
-
- private static final String TEST_CASE_FOLDER_PATH = "validations-tests";
-
- private final String inputsUser = "user";
-
- private final String inputsGroups = "groups";
-
- private static final String SAMPLE_FILE_NAME_FILTER = "sample";
-
- private static final String TESTS_FILE_NAME_FILTER = "tests";
-
- @BeforeEach
- public void setup() {
- MockitoAnnotations.openMocks(this);
- when(configProperties.isFailFast()).thenReturn(true);
- when(context.getBean(Mockito.contains("TimeWindow"))).thenReturn(new TimeWindowFilter());
- }
-
- @AfterEach
- public void cleanup() throws Exception {
- MockitoAnnotations.openMocks(this).close();
- }
-
- private boolean hasException(ValidationTestCase testCase) {
- final String exceptionStr = testCase.getIsEnabled().getException();
- return exceptionStr != null && !exceptionStr.isEmpty();
- }
-
- private boolean hasInput(ValidationTestCase testCase) {
- final LinkedHashMap inputsMap = testCase.getInputs();
- return inputsMap != null && !inputsMap.isEmpty();
- }
-
- private static File[] getFileList(String fileNameFilter) {
- final URL folderUrl = Thread.currentThread().getContextClassLoader().getResource(TEST_CASE_FOLDER_PATH);
- assert folderUrl != null;
-
- final File folderFile = new File(folderUrl.getFile());
- final File[] filteredFiles = folderFile
- .listFiles(pathname -> pathname.getName().toLowerCase().contains(fileNameFilter));
- assert filteredFiles != null;
-
- Arrays.sort(filteredFiles, Comparator.comparing(File::getName));
- return filteredFiles;
- }
-
- private List readTestcasesFromFile(File testFile) throws IOException {
- final String jsonString = Files.readString(testFile.toPath());
- final CollectionType typeReference = TypeFactory.defaultInstance().constructCollectionType(List.class,
- ValidationTestCase.class);
- return OBJECT_MAPPER.readValue(jsonString, typeReference);
- }
-
- @SuppressWarnings("unchecked")
- private static LinkedHashMap readConfigurationFromFile(File sampleFile) throws IOException {
- final String jsonString = Files.readString(sampleFile.toPath());
- final LinkedHashMap configurations = OBJECT_MAPPER.readValue(jsonString, new TypeReference<>() {
- });
- final Object featureManagementSection = configurations.get("feature_management");
- if (featureManagementSection.getClass().isAssignableFrom(LinkedHashMap.class)) {
- return (LinkedHashMap) featureManagementSection;
- }
- throw new IllegalArgumentException("feature_management part is not a map");
- }
-
- static Stream testProvider() throws IOException {
- List arguments = new ArrayList<>();
- File[] files = getFileList(TESTS_FILE_NAME_FILTER);
-
- final File[] sampleFiles = getFileList(SAMPLE_FILE_NAME_FILTER);
- List properties = new ArrayList<>();
- for (File sampleFile : sampleFiles) {
- final FeatureManagementProperties managementProperties = new FeatureManagementProperties();
- managementProperties.putAll(readConfigurationFromFile(sampleFile));
- properties.add(managementProperties);
- }
-
- for (int i = 0; i < files.length; i++) {
- if (files[i].getName().contains(("TargetingFilter"))) {
- continue; // TODO(mametcal). Not run the test case until we release the little endian fix
- }
- arguments.add(Arguments.of(files[i].getName(), files[i], properties.get(i)));
- }
-
- return arguments.stream();
- }
-
- @ParameterizedTest(name = "{0}")
- @MethodSource("testProvider")
- void validationTest(String name, File testsFile, FeatureManagementProperties managementProperties)
- throws IOException {
- LOGGER.debug("Running test case from file: " + name);
- final FeatureManager featureManager = new FeatureManager(context, managementProperties, configProperties);
- List testCases = readTestcasesFromFile(testsFile);
- for (ValidationTestCase testCase : testCases) {
- LOGGER.debug("Test case : " + testCase.getDescription());
- if (hasException(testCase)) { // TODO(mametcal). Currently we didn't throw the exception when parameter is
- // invalid
- assertNull(managementProperties.getOnOff().get(testCase.getFeatureFlagName()));
- continue;
- }
- if (hasInput(testCase)) { // Set inputs
- final Object userObj = testCase.getInputs().get(inputsUser);
- final Object groupsObj = testCase.getInputs().get(inputsGroups);
- final String user = userObj != null ? userObj.toString() : null;
- @SuppressWarnings("unchecked")
- final List groups = groupsObj != null ? (List) groupsObj : null;
- when(context.getBean(Mockito.contains("Targeting")))
- .thenReturn(new TargetingFilter(new TargetingFilterTestContextAccessor(user, groups)));
- }
-
- final Boolean result = featureManager.isEnabled(testCase.getFeatureFlagName());
- assertEquals(result.toString(), testCase.getIsEnabled().getResult());
- }
- }
-}