From 284ae3804e6a50a3740a93ea8a58b8df974f337a Mon Sep 17 00:00:00 2001
From: Matt Metcalf
Date: Mon, 11 Sep 2023 14:14:14 -0700
Subject: [PATCH 1/7] Snapshots
---
.../pom.xml | 2 +-
...ationApplicationSettingPropertySource.java | 131 ++++++++-----
...rationFeatureManagementPropertySource.java | 69 ++++---
...AppConfigurationKeyVaultClientFactory.java | 7 +-
.../AppConfigurationPropertySource.java | 33 ++--
...AppConfigurationPropertySourceLocator.java | 36 ++--
.../AppConfigurationReplicaClient.java | 49 +++--
...ppConfigurationSnapshotPropertySource.java | 64 ++++++
...ppConfigurationBootstrapConfiguration.java | 55 +++---
.../AppConfigurationKeyValueSelector.java | 27 ++-
.../properties/ConfigStore.java | 21 +-
.../AppConfigurationSecretClientManager.java | 11 +-
...nApplicationSettingPropertySourceTest.java | 8 +-
...onFeatureManagementPropertySourceTest.java | 18 +-
...nfigurationPropertySourceKeyVaultTest.java | 6 +-
.../AppConfigurationReplicaClientTest.java | 80 ++++++++
...nfigurationSnapshotPropertySourceTest.java | 184 ++++++++++++++++++
.../stores/KeyVaultClientTest.java | 18 +-
.../README.md | 71 +++++++
19 files changed, 698 insertions(+), 192 deletions(-)
create mode 100644 sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationSnapshotPropertySource.java
create mode 100644 sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationSnapshotPropertySourceTest.java
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/pom.xml b/sdk/spring/spring-cloud-azure-appconfiguration-config/pom.xml
index 9611699b4e1dd..6bb15a9b732e0 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/pom.xml
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/pom.xml
@@ -48,7 +48,7 @@
com.azure
azure-data-appconfiguration
- 1.4.8
+ 1.5.0-beta.1
com.azure
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 96a9f5fd5d801..87cc8bddc0733 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
@@ -2,9 +2,12 @@
// Licensed under the MIT License.
package com.azure.spring.cloud.appconfiguration.config.implementation;
+import static com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationConstants.FEATURE_FLAG_CONTENT_TYPE;
+
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -17,6 +20,7 @@
import org.springframework.util.StringUtils;
import com.azure.data.appconfiguration.models.ConfigurationSetting;
+import com.azure.data.appconfiguration.models.FeatureFlagConfigurationSetting;
import com.azure.data.appconfiguration.models.SecretReferenceConfigurationSetting;
import com.azure.data.appconfiguration.models.SettingSelector;
import com.azure.security.keyvault.secrets.models.KeyVaultSecret;
@@ -26,27 +30,28 @@
* Azure App Configuration PropertySource unique per Store Label(Profile) combo.
*
*
- * i.e. If connecting to 2 stores and have 2 labels set 4
- * AppConfigurationPropertySources need to be created.
+ * i.e. If connecting to 2 stores and have 2 labels set 4 AppConfigurationPropertySources need to be created.
*
*/
-final class AppConfigurationApplicationSettingPropertySource extends AppConfigurationPropertySource {
+class AppConfigurationApplicationSettingPropertySource extends AppConfigurationPropertySource {
private static final Logger LOGGER = LoggerFactory
- .getLogger(AppConfigurationApplicationSettingPropertySource.class);
+ .getLogger(AppConfigurationApplicationSettingPropertySource.class);
private final AppConfigurationKeyVaultClientFactory keyVaultClientFactory;
- private final int maxRetryTime;
+ private final String keyFilter;
+
+ private final String[] labelFilters;
- AppConfigurationApplicationSettingPropertySource(String originEndpoint, AppConfigurationReplicaClient replicaClient,
- AppConfigurationKeyVaultClientFactory keyVaultClientFactory, String keyFilter, String[] labelFilter,
- int maxRetryTime) {
+ AppConfigurationApplicationSettingPropertySource(String name, AppConfigurationReplicaClient replicaClient,
+ AppConfigurationKeyVaultClientFactory keyVaultClientFactory, String keyFilter, String[] labelFilters) {
// The context alone does not uniquely define a PropertySource, append storeName
// and label to uniquely define a PropertySource
- super(originEndpoint, replicaClient, keyFilter, labelFilter);
+ super(name + getLabelName(labelFilters), replicaClient);
this.keyVaultClientFactory = keyVaultClientFactory;
- this.maxRetryTime = maxRetryTime;
+ this.keyFilter = keyFilter;
+ this.labelFilters = labelFilters;
}
/**
@@ -54,74 +59,102 @@ final class AppConfigurationApplicationSettingPropertySource extends AppConfigur
* Gets settings from Azure/Cache to set as configurations. Updates the cache.
*
*
+ * @param keyPrefixTrimValues prefixs to trim from key values
* @throws JsonProcessingException thrown if fails to parse Json content type
*/
- public void initProperties() throws JsonProcessingException {
- List labels = Arrays.asList(labelFilter);
+ public void initProperties(List keyPrefixTrimValues) throws JsonProcessingException {
+
+ List labels = Arrays.asList(labelFilters);
+ // Reverse labels so they have the right priority order.
Collections.reverse(labels);
for (String label : labels) {
- SettingSelector settingSelector = new SettingSelector().setKeyFilter(keyFilter + "*")
- .setLabelFilter(label);
+ SettingSelector settingSelector = new SettingSelector().setKeyFilter(keyFilter + "*").setLabelFilter(label);
// * for wildcard match
- List settings = replicaClient.listSettings(settingSelector);
-
- for (ConfigurationSetting setting : settings) {
- String key = setting.getKey().trim().substring(keyFilter.length())
- .replace('/', '.');
- if (setting instanceof SecretReferenceConfigurationSetting) {
- String entry = getKeyVaultEntry((SecretReferenceConfigurationSetting) setting);
-
- // Null in the case of failFast is false, will just skip entry.
- if (entry != null) {
- properties.put(key, entry);
- }
- } else if (StringUtils.hasText(setting.getContentType())
- && JsonConfigurationParser.isJsonContentType(setting.getContentType())) {
- Map jsonSettings = JsonConfigurationParser.parseJsonSetting(setting);
- for (Entry jsonSetting : jsonSettings.entrySet()) {
- key = jsonSetting.getKey().trim().substring(keyFilter.length());
- properties.put(key, jsonSetting.getValue());
- }
- } else {
- properties.put(key, setting.getValue());
- }
- }
+ processConfigurationSettings(replicaClient.listSettings(settingSelector), settingSelector.getKeyFilter(),
+ keyPrefixTrimValues);
}
}
+ protected void processConfigurationSettings(List settings, String keyFilter,
+ List keyPrefixTrimValues)
+ throws JsonProcessingException {
+ for (ConfigurationSetting setting : settings) {
+ if (keyPrefixTrimValues == null && StringUtils.hasText(keyFilter)) {
+ keyPrefixTrimValues = new ArrayList<>();
+ keyPrefixTrimValues.add(keyFilter.substring(0, keyFilter.length() - 1));
+ }
+ String key = trimKey(setting.getKey(), keyPrefixTrimValues);
+
+ if (setting instanceof SecretReferenceConfigurationSetting) {
+ handleKeyVaultReference(key, (SecretReferenceConfigurationSetting) setting);
+ } else if (setting instanceof FeatureFlagConfigurationSetting
+ && FEATURE_FLAG_CONTENT_TYPE.equals(setting.getContentType())) {
+ handleFeatureFlag(key, (FeatureFlagConfigurationSetting) setting, keyPrefixTrimValues);
+ } else if (StringUtils.hasText(setting.getContentType())
+ && JsonConfigurationParser.isJsonContentType(setting.getContentType())) {
+ handleJson(setting, keyPrefixTrimValues);
+ } else {
+ properties.put(key, setting.getValue());
+ }
+ }
+ }
+
/**
- * Given a Setting's Key Vault Reference stored in the Settings value, it will
- * get its entry in Key Vault.
+ * Given a Setting's Key Vault Reference stored in the Settings value, it will get its entry in Key Vault.
*
- * @param secretReference {"uri":
- * "<your-vault-url>/secret/<secret>/<version>"}
+ * @param key Application Setting name
+ * @param secretReference {"uri": "<your-vault-url>/secret/<secret>/<version>"}
* @return Key Vault Secret Value
*/
- private String getKeyVaultEntry(SecretReferenceConfigurationSetting secretReference) {
- String secretValue = null;
+ protected void handleKeyVaultReference(String key, SecretReferenceConfigurationSetting secretReference) {
try {
- URI uri = null;
KeyVaultSecret secret = null;
// Parsing Key Vault Reference for URI
try {
- uri = new URI(secretReference.getSecretId());
- secret = keyVaultClientFactory.getClient("https://" + uri.getHost()).getSecret(uri, maxRetryTime);
+ URI uri = new URI(secretReference.getSecretId());
+ secret = keyVaultClientFactory.getClient("https://" + uri.getHost()).getSecret(uri);
} catch (URISyntaxException e) {
LOGGER.error("Error Processing Key Vault Entry URI.");
ReflectionUtils.rethrowRuntimeException(e);
}
-
+
if (secret == null) {
throw new IOException("No Key Vault Secret found for Reference.");
}
- secretValue = secret.getValue();
+ properties.put(key, secret.getValue());
} catch (RuntimeException | IOException e) {
LOGGER.error("Error Retrieving Key Vault Entry");
ReflectionUtils.rethrowRuntimeException(e);
}
- return secretValue;
+ }
+
+ void handleFeatureFlag(String key, FeatureFlagConfigurationSetting setting, List trimStrings)
+ throws JsonProcessingException {
+ handleJson(setting, trimStrings);
+ }
+
+ void handleJson(ConfigurationSetting setting, List keyPrefixTrimValues)
+ throws JsonProcessingException {
+ Map jsonSettings = JsonConfigurationParser.parseJsonSetting(setting);
+ for (Entry jsonSetting : jsonSettings.entrySet()) {
+ String key = trimKey(jsonSetting.getKey(), keyPrefixTrimValues);
+ properties.put(key, jsonSetting.getValue());
+ }
+ }
+
+
+ protected String trimKey(String key, List trimStrings) {
+ key = key.trim();
+ if (trimStrings != null) {
+ for (String trim : trimStrings) {
+ if (key.startsWith(trim)) {
+ return key.replaceFirst("^" + trim, "").replace('/', '.');
+ }
+ }
+ }
+ return key.replace("/", ".");
}
}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationFeatureManagementPropertySource.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationFeatureManagementPropertySource.java
index c1fcd5315d6c9..f310c604ef3b1 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationFeatureManagementPropertySource.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationFeatureManagementPropertySource.java
@@ -19,7 +19,6 @@
import static java.util.Collections.emptyList;
import static java.util.stream.Collectors.toMap;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -48,24 +47,20 @@
* i.e. If connecting to 2 stores and have 2 labels set 4 AppConfigurationPropertySources need to be created.
*
*/
-final class AppConfigurationFeatureManagementPropertySource extends AppConfigurationPropertySource {
+class AppConfigurationFeatureManagementPropertySource extends AppConfigurationPropertySource {
private static final ObjectMapper CASE_INSENSITIVE_MAPPER = JsonMapper.builder()
.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true).build();
- private final List featureConfigurationSettings;
+ private final String keyFilter;
+
+ private final String[] labelFilter;
AppConfigurationFeatureManagementPropertySource(String originEndpoint, AppConfigurationReplicaClient replicaClient,
String keyFilter, String[] labelFilter) {
- super("FM_" + originEndpoint, replicaClient, keyFilter, labelFilter);
- featureConfigurationSettings = new ArrayList<>();
- }
-
- private static List convertToListOrEmptyList(Map parameters, String key) {
- List listObjects = CASE_INSENSITIVE_MAPPER.convertValue(parameters.get(key),
- new TypeReference>() {
- });
- return listObjects == null ? emptyList() : listObjects;
+ super("FM_" + originEndpoint + "/" + getLabelName(labelFilter), replicaClient);
+ this.keyFilter = keyFilter;
+ this.labelFilter = labelFilter;
}
/**
@@ -80,7 +75,8 @@ private static List convertToListOrEmptyList(Map paramet
*
*
*/
- public void initProperties() {
+ @Override
+ public void initProperties(List trim) {
SettingSelector settingSelector = new SettingSelector();
String keyFilter = SELECT_ALL_FEATURE_FLAGS;
@@ -98,30 +94,33 @@ public void initProperties() {
settingSelector.setLabelFilter(label);
List features = replicaClient.listSettings(settingSelector);
- TracingInfo tracing = replicaClient.getTracingInfo();
// Reading In Features
for (ConfigurationSetting setting : features) {
if (setting instanceof FeatureFlagConfigurationSetting
&& FEATURE_FLAG_CONTENT_TYPE.equals(setting.getContentType())) {
- featureConfigurationSettings.add(setting);
- FeatureFlagConfigurationSetting featureFlag = (FeatureFlagConfigurationSetting) setting;
-
- String configName = FEATURE_MANAGEMENT_KEY
- + setting.getKey().trim().substring(FEATURE_FLAG_PREFIX.length());
-
- updateTelemetry(featureFlag, tracing);
-
- properties.put(configName, createFeature(featureFlag));
+ processFeatureFlag(null, (FeatureFlagConfigurationSetting) setting, null);
}
}
}
}
-
+
List getFeatureFlagSettings() {
return featureConfigurationSettings;
}
+ protected void processFeatureFlag(String key, FeatureFlagConfigurationSetting setting, List trimStrings) {
+ TracingInfo tracing = replicaClient.getTracingInfo();
+ featureConfigurationSettings.add(setting);
+ FeatureFlagConfigurationSetting featureFlag = setting;
+
+ String configName = FEATURE_MANAGEMENT_KEY + setting.getKey().trim().substring(FEATURE_FLAG_PREFIX.length());
+
+ updateTelemetry(featureFlag, tracing);
+
+ properties.put(configName, createFeature(featureFlag));
+ }
+
/**
* Creates a {@code Feature} from a {@code KeyValueItem}
*
@@ -129,7 +128,7 @@ List getFeatureFlagSettings() {
* @return Feature created from KeyValueItem
*/
@SuppressWarnings("unchecked")
- private Object createFeature(FeatureFlagConfigurationSetting item) {
+ protected static Object createFeature(FeatureFlagConfigurationSetting item) {
String key = getFeatureSimpleName(item);
String requirementType = DEFAULT_REQUIREMENT_TYPE;
try {
@@ -182,31 +181,37 @@ private Object createFeature(FeatureFlagConfigurationSetting item) {
}
return feature;
-
}
-
+
/**
* Looks at each filter used in a Feature Flag to check what types it is using.
*
* @param featureFlag FeatureFlagConfigurationSetting
* @param tracing The TracingInfo for this store.
*/
- private void updateTelemetry(FeatureFlagConfigurationSetting featureFlag, TracingInfo tracing) {
+ protected static void updateTelemetry(FeatureFlagConfigurationSetting featureFlag, TracingInfo tracing) {
for (FeatureFlagFilter filter : featureFlag.getClientFilters()) {
tracing.getFeatureFlagTracing().updateFeatureFilterTelemetry(filter.getName());
}
}
- private String getFeatureSimpleName(ConfigurationSetting setting) {
+ private static String getFeatureSimpleName(ConfigurationSetting setting) {
return setting.getKey().trim().substring(FEATURE_FLAG_PREFIX.length());
}
-
- private Map mapValuesByIndex(List users) {
+
+ @SuppressWarnings("null")
+ private static Map mapValuesByIndex(List users) {
return IntStream.range(0, users.size()).boxed().collect(toMap(String::valueOf, users::get));
}
- private void switchKeyValues(Map parameters, String oldKey, String newKey, Object value) {
+ private static void switchKeyValues(Map parameters, String oldKey, String newKey, Object value) {
parameters.put(newKey, value);
parameters.remove(oldKey);
}
+
+ private static List convertToListOrEmptyList(Map parameters, String key) {
+ List listObjects =
+ CASE_INSENSITIVE_MAPPER.convertValue(parameters.get(key), new TypeReference>() {});
+ return listObjects == null ? emptyList() : listObjects;
+ }
}
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 c1ebcbd34394e..2cc9fbffe363a 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
@@ -23,16 +23,19 @@ public class AppConfigurationKeyVaultClientFactory {
private final boolean credentialsConfigured;
private final boolean isConfigured;
+
+ private final int timeout;
public AppConfigurationKeyVaultClientFactory(SecretClientCustomizer keyVaultClientProvider,
KeyVaultSecretProvider keyVaultSecretProvider, SecretClientBuilderFactory secretClientFactory,
- boolean credentialsConfigured) {
+ boolean credentialsConfigured, int timeout) {
this.keyVaultClientProvider = keyVaultClientProvider;
this.keyVaultSecretProvider = keyVaultSecretProvider;
this.secretClientFactory = secretClientFactory;
keyVaultClients = new HashMap<>();
this.credentialsConfigured = credentialsConfigured;
isConfigured = keyVaultClientProvider != null || credentialsConfigured;
+ this.timeout = timeout;
}
public AppConfigurationSecretClientManager getClient(String host) {
@@ -40,7 +43,7 @@ public AppConfigurationSecretClientManager getClient(String host) {
// one
if (!keyVaultClients.containsKey(host)) {
AppConfigurationSecretClientManager client = new AppConfigurationSecretClientManager(host,
- keyVaultClientProvider, keyVaultSecretProvider, secretClientFactory, credentialsConfigured);
+ keyVaultClientProvider, keyVaultSecretProvider, secretClientFactory, credentialsConfigured, timeout);
keyVaultClients.put(host, client);
}
return keyVaultClients.get(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 f883f304aac82..ca1a4caad94fe 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,40 +2,39 @@
// 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;
import java.util.Set;
import org.springframework.core.env.EnumerablePropertySource;
import com.azure.data.appconfiguration.ConfigurationClient;
+import com.azure.data.appconfiguration.models.ConfigurationSetting;
+import com.fasterxml.jackson.core.JsonProcessingException;
/**
* Azure App Configuration PropertySource unique per Store Label(Profile) combo.
*
*
- * i.e. If connecting to 2 stores and have 2 labels set 4 AppConfigurationPropertySources need to be created.
+ * i.e. If connecting to 2 stores and have 2 labels set 4 AppConfigurationPropertySources need to be
+ * created.
*
*/
abstract class AppConfigurationPropertySource extends EnumerablePropertySource {
- protected final String keyFilter;
-
- protected final String[] labelFilter;
-
protected final Map properties = new LinkedHashMap<>();
+ protected final List featureConfigurationSettings = new ArrayList<>();
+
protected final AppConfigurationReplicaClient replicaClient;
- AppConfigurationPropertySource(String originEndpoint, AppConfigurationReplicaClient replicaClient, String keyFilter,
- String[] labelFilter) {
+ AppConfigurationPropertySource(String name, AppConfigurationReplicaClient replicaClient) {
// The context alone does not uniquely define a PropertySource, append storeName
// and label to uniquely define a PropertySource
- super(
- keyFilter + originEndpoint + "/" + getLabelName(labelFilter));
+ super(name);
this.replicaClient = replicaClient;
- this.keyFilter = keyFilter;
- this.labelFilter = labelFilter;
}
@Override
@@ -49,12 +48,12 @@ public Object getProperty(String name) {
return properties.get(name);
}
- private static String getLabelName(String[] labelFilter) {
- StringBuilder labelName = new StringBuilder();
- for (String label : labelFilter) {
-
- labelName.append((labelName.length() == 0) ? label : "," + label);
+ protected static String getLabelName(String[] labelFilters) {
+ if (labelFilters == null) {
+ return "";
}
- return labelName.toString();
+ return String.join(",", labelFilters);
}
+
+ protected abstract void initProperties(List trim) throws JsonProcessingException;
}
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
index 870cc48fa3221..f17487acce07e 100644
--- 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
@@ -19,6 +19,7 @@
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.properties.AppConfigurationKeyValueSelector;
@@ -114,9 +115,8 @@ public PropertySource> locate(Environment environment) {
for (AppConfigurationReplicaClient client : clients) {
sourceList = new ArrayList<>();
- if (!STARTUP.get() && reloadFailed
- && !AppConfigurationRefreshUtil.checkStoreAfterRefreshFailed(client, clientFactory,
- configStore.getFeatureFlags(), profiles)) {
+ if (!STARTUP.get() && reloadFailed && !AppConfigurationRefreshUtil
+ .checkStoreAfterRefreshFailed(client, clientFactory, configStore.getFeatureFlags(), profiles)) {
// This store doesn't have any changes where to refresh store did. Skipping Checking next.
continue;
}
@@ -196,9 +196,7 @@ private List getWatchKeys(AppConfigurationReplicaClient cl
if (watchKey != null) {
watchKeysSettings.add(watchKey);
} else {
- watchKeysSettings
- .add(new ConfigurationSetting().setKey(trigger.getKey())
- .setLabel(trigger.getLabel()));
+ watchKeysSettings.add(new ConfigurationSetting().setKey(trigger.getKey()).setLabel(trigger.getLabel()));
}
}
return watchKeysSettings;
@@ -210,7 +208,8 @@ private List getFeatureFlagWatchKeys(ConfigStore configSto
if (configStore.getFeatureFlags().getEnabled()) {
for (AppConfigurationPropertySource propertySource : sources) {
if (propertySource instanceof AppConfigurationFeatureManagementPropertySource) {
- watchKeysFeatures.addAll(((AppConfigurationFeatureManagementPropertySource) propertySource).getFeatureFlagSettings());
+ watchKeysFeatures.addAll(
+ ((AppConfigurationFeatureManagementPropertySource) propertySource).getFeatureFlagSettings());
}
}
}
@@ -260,20 +259,29 @@ private List create(AppConfigurationReplicaClien
if (store.getFeatureFlags().getEnabled()) {
for (FeatureFlagKeyValueSelector selectedKeys : store.getFeatureFlags().getSelects()) {
AppConfigurationFeatureManagementPropertySource propertySource = new AppConfigurationFeatureManagementPropertySource(
- store.getEndpoint(), client, selectedKeys.getKeyFilter(),
- selectedKeys.getLabelFilter(profiles));
+ store.getEndpoint(), client,
+ selectedKeys.getKeyFilter(), selectedKeys.getLabelFilter(profiles));
- propertySource.initProperties();
+ propertySource.initProperties(null);
sourceList.add(propertySource);
}
}
for (AppConfigurationKeyValueSelector selectedKeys : selects) {
- AppConfigurationApplicationSettingPropertySource propertySource = new AppConfigurationApplicationSettingPropertySource(
- store.getEndpoint(), client, keyVaultClientFactory, selectedKeys.getKeyFilter(),
- selectedKeys.getLabelFilter(profiles), appProperties.getMaxRetryTime());
- propertySource.initProperties();
+ AppConfigurationPropertySource propertySource = null;
+
+ if (StringUtils.hasText(selectedKeys.getSnapshotName())) {
+ propertySource = new AppConfigurationSnapshotPropertySource(
+ selectedKeys.getSnapshotName() + "/" + store.getEndpoint(), client, keyVaultClientFactory,
+ selectedKeys.getSnapshotName());
+ } else {
+ propertySource = new AppConfigurationApplicationSettingPropertySource(
+ selectedKeys.getKeyFilter() + store.getEndpoint() + "/", client, keyVaultClientFactory,
+ selectedKeys.getKeyFilter(), selectedKeys.getLabelFilter(profiles));
+ }
+ propertySource.initProperties(store.getTrimKeyPrefix());
sourceList.add(propertySource);
+
}
return sourceList;
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 c6532283f58a7..ae3c84abbcc8e 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
@@ -2,6 +2,7 @@
// Licensed under the MIT License.
package com.azure.spring.cloud.appconfiguration.config.implementation;
+import java.io.UncheckedIOException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
@@ -11,7 +12,9 @@
import com.azure.core.exception.HttpResponseException;
import com.azure.core.http.rest.PagedIterable;
import com.azure.data.appconfiguration.ConfigurationClient;
+import com.azure.data.appconfiguration.models.CompositionType;
import com.azure.data.appconfiguration.models.ConfigurationSetting;
+import com.azure.data.appconfiguration.models.ConfigurationSettingSnapshot;
import com.azure.data.appconfiguration.models.SettingSelector;
import com.azure.spring.cloud.appconfiguration.config.implementation.http.policy.TracingInfo;
@@ -97,16 +100,8 @@ ConfigurationSetting getWatchKey(String key, String label)
}
}
throw e;
- } catch (Exception e) { // TODO (mametcal) This should be an UnknownHostException, but currently it isn't
- // catchable.
- if (e.getMessage().startsWith("java.net.UnknownHostException")
- || e.getMessage().startsWith("java.net.WebSocketHandshakeException")
- || e.getMessage().startsWith("java.net.SocketException")
- || e.getMessage().startsWith("java.io.IOException") || e.getMessage()
- .startsWith("io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused")) {
- throw new AppConfigurationStatusException(e.getMessage(), null, null);
- }
- throw e;
+ } catch (UncheckedIOException e) {
+ throw new AppConfigurationStatusException(e.getMessage(), null, null);
}
}
@@ -133,16 +128,34 @@ List listSettings(SettingSelector settingSelector)
}
}
throw e;
- } catch (Exception e) { // TODO (mametcal) This should be an UnknownHostException, but currently it isn't
- // catchable.
- if (e.getMessage().startsWith("java.net.UnknownHostException")
- || e.getMessage().startsWith("java.net.WebSocketHandshakeException")
- || e.getMessage().startsWith("java.net.SocketException")
- || e.getMessage().startsWith("java.io.IOException") || e.getMessage()
- .startsWith("io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused")) {
- throw new AppConfigurationStatusException(e.getMessage(), null, null);
+ } catch (UncheckedIOException e) {
+ throw new AppConfigurationStatusException(e.getMessage(), null, null);
+ }
+ }
+
+ List listSettingSnapshot(String snapshotName) {
+ List configurationSettings = new ArrayList<>();
+ try {
+ ConfigurationSettingSnapshot snapshot = client.getSnapshot(snapshotName);
+ if (!CompositionType.KEY.equals(snapshot.getCompositionType())) {
+ throw new IllegalArgumentException("Snapshot " + snapshotName + " needs to be of type Key.");
+ }
+
+ PagedIterable settings = client.listConfigurationSettingsForSnapshot(snapshotName);
+ this.failedAttempts = 0;
+ settings.forEach(setting -> configurationSettings.add(NormalizeNull.normalizeNullLabel(setting)));
+ return configurationSettings;
+ } catch (HttpResponseException e) {
+ if (e.getResponse() != null) {
+ int statusCode = e.getResponse().getStatusCode();
+
+ if (statusCode == 429 || statusCode == 408 || statusCode >= 500) {
+ throw new AppConfigurationStatusException(e.getMessage(), e.getResponse(), e.getValue());
+ }
}
throw e;
+ } catch (UncheckedIOException e) {
+ throw new AppConfigurationStatusException(e.getMessage(), null, null);
}
}
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
new file mode 100644
index 0000000000000..e0d6eae181b2f
--- /dev/null
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationSnapshotPropertySource.java
@@ -0,0 +1,64 @@
+// 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.FEATURE_FLAG_PREFIX;
+import static com.azure.spring.cloud.appconfiguration.config.implementation.AppConfigurationConstants.FEATURE_MANAGEMENT_KEY;
+
+import java.util.List;
+
+import com.azure.data.appconfiguration.models.FeatureFlagConfigurationSetting;
+import com.azure.spring.cloud.appconfiguration.config.implementation.http.policy.TracingInfo;
+import com.fasterxml.jackson.core.JsonProcessingException;
+
+/**
+ * Azure App Configuration PropertySource unique per Store Label(Profile) combo.
+ *
+ *
+ * i.e. If connecting to 2 stores and have 2 labels set 4 AppConfigurationPropertySources need to be created.
+ *
+ */
+final class AppConfigurationSnapshotPropertySource extends AppConfigurationApplicationSettingPropertySource {
+
+ private final String snapshotName;
+
+ AppConfigurationSnapshotPropertySource(String name, AppConfigurationReplicaClient replicaClient,
+ AppConfigurationKeyVaultClientFactory keyVaultClientFactory, String snapshotName) {
+ // The context alone does not uniquely define a PropertySource, append storeName
+ // and label to uniquely define a PropertySource
+ // super(snapshotName + originEndpoint + "/", replicaClient, maxRetryTime);
+ super(name, replicaClient, keyVaultClientFactory, null, null);
+ this.snapshotName = snapshotName;
+ }
+
+ /**
+ *
+ * Gets settings from Azure/Cache to set as configurations. Updates the cache.
+ *
+ *
+ * @param trim prefix to trim
+ * @throws JsonProcessingException thrown if fails to parse Json content type
+ */
+ public void initProperties(List trim) throws JsonProcessingException {
+ processConfigurationSettings(replicaClient.listSettingSnapshot(snapshotName), null, trim);
+ }
+
+ @Override
+ void handleFeatureFlag(String key, FeatureFlagConfigurationSetting setting, List trimStrings)
+ throws JsonProcessingException {
+ // Feature Flags are only part of this if they come from a snapshot
+ processFeatureFlag(key, setting, trimStrings);
+ }
+
+ protected void processFeatureFlag(String key, FeatureFlagConfigurationSetting setting, List trimStrings) {
+ TracingInfo tracing = replicaClient.getTracingInfo();
+ featureConfigurationSettings.add(setting);
+ FeatureFlagConfigurationSetting featureFlag = setting;
+
+ String configName = FEATURE_MANAGEMENT_KEY + setting.getKey().trim().substring(FEATURE_FLAG_PREFIX.length());
+
+ AppConfigurationFeatureManagementPropertySource.updateTelemetry(featureFlag, tracing);
+
+ properties.put(configName, AppConfigurationFeatureManagementPropertySource.createFeature(featureFlag));
+ }
+}
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
index 826ee47a3bb84..b503d3080e7d3 100644
--- 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
@@ -44,7 +44,7 @@
*/
@Configuration
@PropertySource("classpath:appConfiguration.properties")
-@EnableConfigurationProperties({AppConfigurationProperties.class, AppConfigurationProviderProperties.class})
+@EnableConfigurationProperties({ AppConfigurationProperties.class, AppConfigurationProviderProperties.class })
@ConditionalOnClass(AppConfigurationPropertySourceLocator.class)
@ConditionalOnProperty(prefix = AppConfigurationProperties.CONFIG_PREFIX, name = "enabled", matchIfMissing = true)
public class AppConfigurationBootstrapConfiguration {
@@ -55,38 +55,40 @@ public class AppConfigurationBootstrapConfiguration {
@Bean
AppConfigurationPropertySourceLocator sourceLocator(AppConfigurationProperties properties,
AppConfigurationProviderProperties appProperties, AppConfigurationReplicaClientFactory clientFactory,
- AppConfigurationKeyVaultClientFactory keyVaultClientFactory) throws IllegalArgumentException {
+ AppConfigurationKeyVaultClientFactory keyVaultClientFactory)
+ throws IllegalArgumentException {
return new AppConfigurationPropertySourceLocator(appProperties, clientFactory, keyVaultClientFactory,
properties.getRefreshInterval(), properties.getStores());
}
@Bean
- AppConfigurationKeyVaultClientFactory appConfigurationKeyVaultClientFactory(Environment environment)
+ 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);
+ 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());
+ 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();
+ 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);
+ secretClientBuilderFactory, credentialConfigured, appProperties.getMaxRetryTime());
}
/**
@@ -117,15 +119,16 @@ AppConfigurationReplicaClientFactory buildClientFactory(AppConfigurationReplicaC
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 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());
+ AzureGlobalProperties globalProperties = AzureGlobalPropertiesUtils.loadProperties(globalSource,
+ new AzureGlobalProperties());
+ AzureAppConfigurationProperties clientProperties = AzureGlobalPropertiesUtils.loadProperties(serviceSource,
+ new AzureAppConfigurationProperties());
AzurePropertiesUtils.copyAzureCommonPropertiesIgnoreNull(globalProperties, clientProperties);
@@ -139,7 +142,9 @@ AppConfigurationReplicaClientsBuilder replicaClientBuilder(Environment environme
AppConfigurationReplicaClientsBuilder clientBuilder = new AppConfigurationReplicaClientsBuilder(
appProperties.getMaxRetries(), clientFactory, credentialConfigured);
- clientBuilder.setClientProvider(context.getBeanProvider(ConfigurationClientCustomizer.class).getIfAvailable());
+ clientBuilder
+ .setClientProvider(context.getBeanProvider(ConfigurationClientCustomizer.class)
+ .getIfAvailable());
clientBuilder.setIsKeyVaultConfigured(keyVaultClientFactory.isConfigured());
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 2192121008d77..b8b9f1ad86847 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
@@ -24,7 +24,7 @@ public final class AppConfigurationKeyValueSelector {
* Label for requesting all configurations with (No Label)
*/
private static final String[] EMPTY_LABEL_ARRAY = { EMPTY_LABEL };
-
+
private static final String APPLICATION_SETTING_DEFAULT_KEY_FILTER = "/application/";
/**
@@ -37,6 +37,7 @@ public final class AppConfigurationKeyValueSelector {
private String labelFilter;
+ private String snapshotName = "";
/**
* @return the keyFilter
*/
@@ -61,14 +62,14 @@ public String[] getLabelFilter(List profiles) {
if (labelFilter == null && profiles.size() > 0) {
Collections.reverse(profiles);
return profiles.toArray(new String[profiles.size()]);
+ } else if (StringUtils.hasText(snapshotName)) {
+ return new String[0];
} else if (!StringUtils.hasText(labelFilter)) {
return EMPTY_LABEL_ARRAY;
}
// The use of trim makes label= dev,prod and label= dev, prod equal.
- List labels = Arrays.stream(labelFilter.split(LABEL_SEPARATOR))
- .map(this::mapLabel)
- .distinct()
+ List labels = Arrays.stream(labelFilter.split(LABEL_SEPARATOR)).map(this::mapLabel).distinct()
.collect(Collectors.toList());
if (labelFilter.endsWith(",")) {
@@ -89,6 +90,20 @@ public AppConfigurationKeyValueSelector setLabelFilter(String labelFilter) {
return this;
}
+ /**
+ * @return the snapshot
+ */
+ public String getSnapshotName() {
+ return snapshotName;
+ }
+
+ /**
+ * @param snapshot the snapshot to set
+ */
+ public void setSnapshotName(String snapshotName) {
+ this.snapshotName = snapshotName;
+ }
+
/**
* Validates key-filter and label-filter are valid.
*/
@@ -98,6 +113,10 @@ public void validateAndInit() {
if (labelFilter != null) {
Assert.isTrue(!labelFilter.contains("*"), "LabelFilter must not contain asterisk(*)");
}
+ Assert.isTrue(!(StringUtils.hasText(keyFilter) && StringUtils.hasText(snapshotName)),
+ "Snapshots can't use key filters");
+ Assert.isTrue(!(StringUtils.hasText(labelFilter) && StringUtils.hasText(snapshotName)),
+ "Snapshots can't use label filters");
}
private String mapLabel(String label) {
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 0e50436064307..17ac625ba1558 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
@@ -40,6 +40,8 @@ public final class ConfigStore {
private AppConfigurationStoreMonitoring monitoring = new AppConfigurationStoreMonitoring();
+ private List trimKeyPrefix;
+
/**
* @return the endpoint
*/
@@ -173,6 +175,21 @@ public boolean containsEndpoint(String endpoint) {
return endpoints.stream().anyMatch(storeEndpoint -> storeEndpoint.startsWith(endpoint));
}
+ /**
+ * @return the trimKeyPrefix
+ */
+ public List getTrimKeyPrefix() {
+ return trimKeyPrefix;
+ }
+
+ /**
+ * @param trimKeyPrefix the values to be trimmed from key names before being set to
+ * `@ConfigurationProperties`
+ */
+ public void setTrimKeyPrefix(List trimKeyPrefix) {
+ this.trimKeyPrefix = trimKeyPrefix;
+ }
+
/**
* @throws IllegalStateException Connection String URL endpoint is invalid
*/
@@ -190,9 +207,9 @@ public void validateAndInit() {
String endpoint = (AppConfigurationReplicaClientsBuilder.getEndpointFromConnectionString(connectionString));
try {
// new URI is used to validate the endpoint as a valid URI
- new URI(endpoint).toURL();
+ new URI(endpoint);
this.endpoint = endpoint;
- } catch (MalformedURLException | URISyntaxException | IllegalArgumentException e) {
+ } catch (URISyntaxException e) {
throw new IllegalStateException("Endpoint in connection string is not a valid URI.", e);
}
} else if (connectionStrings.size() > 0) {
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/stores/AppConfigurationSecretClientManager.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/stores/AppConfigurationSecretClientManager.java
index 606d997d1fcd8..2c086d3c5dab3 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/stores/AppConfigurationSecretClientManager.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/stores/AppConfigurationSecretClientManager.java
@@ -29,8 +29,10 @@ public final class AppConfigurationSecretClientManager {
private final KeyVaultSecretProvider keyVaultSecretProvider;
private final SecretClientBuilderFactory secretClientFactory;
-
+
private final boolean credentialConfigured;
+
+ private final int timeout;
/**
* Creates a Client for connecting to Key Vault
@@ -39,14 +41,17 @@ public final class AppConfigurationSecretClientManager {
* @param keyVaultSecretProvider optional provider for providing Secrets instead of connecting to Key Vault
* @param secretClientFactory Factory for building clients to Key Vault
* @param credentialConfigured Is a credential configured with Global Configurations or Service Configurations
+ * @param timeout How long the connection to key vault is kept open without a response.
*/
public AppConfigurationSecretClientManager(String endpoint, SecretClientCustomizer keyVaultClientProvider,
- KeyVaultSecretProvider keyVaultSecretProvider, SecretClientBuilderFactory secretClientFactory, boolean credentialConfigured) {
+ KeyVaultSecretProvider keyVaultSecretProvider, SecretClientBuilderFactory secretClientFactory,
+ boolean credentialConfigured, int timeout) {
this.endpoint = endpoint;
this.keyVaultClientProvider = keyVaultClientProvider;
this.keyVaultSecretProvider = keyVaultSecretProvider;
this.secretClientFactory = secretClientFactory;
this.credentialConfigured = credentialConfigured;
+ this.timeout = timeout;
}
AppConfigurationSecretClientManager build() {
@@ -74,7 +79,7 @@ AppConfigurationSecretClientManager build() {
* @param timeout How long it waits for a response from Key Vault
* @return Secret values that matches the secretIdentifier
*/
- public KeyVaultSecret getSecret(URI secretIdentifier, int timeout) {
+ public KeyVaultSecret getSecret(URI secretIdentifier) {
if (secretClient == null) {
build();
}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationApplicationSettingPropertySourceTest.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationApplicationSettingPropertySourceTest.java
index b59a2c0ff7e04..975d694443e2e 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationApplicationSettingPropertySourceTest.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationApplicationSettingPropertySourceTest.java
@@ -91,7 +91,7 @@ public void init() {
String[] labelFilter = { "\0" };
propertySource = new AppConfigurationApplicationSettingPropertySource(TEST_STORE_NAME, clientMock,
- keyVaultClientFactoryMock, KEY_FILTER, labelFilter, 60);
+ keyVaultClientFactoryMock, KEY_FILTER, labelFilter);
}
@AfterEach
@@ -105,7 +105,7 @@ public void testPropCanBeInitAndQueried() throws IOException {
when(clientMock.listSettings(Mockito.any())).thenReturn(configurationListMock)
.thenReturn(configurationListMock);
- propertySource.initProperties();
+ propertySource.initProperties(null);
String[] keyNames = propertySource.getPropertyNames();
String[] expectedKeyNames = testItems.stream()
@@ -129,7 +129,7 @@ public void testPropertyNameSlashConvertedToDots() throws IOException {
when(clientMock.listSettings(Mockito.any())).thenReturn(configurationListMock)
.thenReturn(configurationListMock);
- propertySource.initProperties();
+ propertySource.initProperties(null);
String expectedKeyName = TEST_SLASH_KEY.replace('/', '.');
String[] actualKeyNames = propertySource.getPropertyNames();
@@ -148,7 +148,7 @@ public void initNullValidContentTypeTest() throws IOException {
.thenReturn(Collections.emptyIterator());
when(clientMock.listSettings(Mockito.any())).thenReturn(configurationListMock);
- propertySource.initProperties();
+ propertySource.initProperties(null);
String[] keyNames = propertySource.getPropertyNames();
String[] expectedKeyNames = items.stream()
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationFeatureManagementPropertySourceTest.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationFeatureManagementPropertySourceTest.java
index 8ae9ed99071ad..755e5a8c0725b 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationFeatureManagementPropertySourceTest.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationFeatureManagementPropertySourceTest.java
@@ -121,7 +121,7 @@ public void init() {
public void cleanup() throws Exception {
MockitoAnnotations.openMocks(this).close();
}
-
+
@Test
public void overrideTest() {
String[] labels = {"test"};
@@ -133,7 +133,7 @@ public void overrideTest() {
when(clientMock.getTracingInfo()).thenReturn(new TracingInfo(false, false, 0, Configuration.getGlobalConfiguration()));
featureFlagStore.setEnabled(true);
- propertySourceOverride.initProperties();
+ propertySourceOverride.initProperties(null);
Map filters = new HashMap<>();
FeatureFlagFilter ffec = new FeatureFlagFilter("TestFilter");
@@ -142,7 +142,7 @@ public void overrideTest() {
gamma.setKey("Gamma");
filters = new HashMap<>();
ffec = new FeatureFlagFilter("TestFilter");
- LinkedHashMap parameters = new LinkedHashMap<>();
+ Map parameters = new LinkedHashMap<>();
parameters.put("key", "value");
ffec.setParameters(parameters);
filters.put(0, ffec);
@@ -151,7 +151,7 @@ public void overrideTest() {
assertEquals(gamma.getKey(),
((Feature) propertySourceOverride.getProperty(FEATURE_MANAGEMENT_KEY + "Gamma")).getKey());
}
-
+
@Test
public void testFeatureFlagCanBeInitedAndQueried() {
when(featureListMock.iterator()).thenReturn(FEATURE_ITEMS.iterator());
@@ -160,9 +160,9 @@ public void testFeatureFlagCanBeInitedAndQueried() {
when(clientMock.getTracingInfo()).thenReturn(new TracingInfo(false, false, 0, Configuration.getGlobalConfiguration()));
featureFlagStore.setEnabled(true);
- propertySource.initProperties();
+ propertySource.initProperties(null);
- Map filters = new HashMap<>();
+ HashMap filters = new HashMap<>();
FeatureFlagFilter ffec = new FeatureFlagFilter("TestFilter");
filters.put(0, ffec);
Feature gamma = new Feature();
@@ -185,7 +185,7 @@ public void testFeatureFlagThrowError() {
when(clientMock.listSettings(Mockito.any())).thenReturn(featureListMock);
when(clientMock.getTracingInfo()).thenReturn(new TracingInfo(false, false, 0, Configuration.getGlobalConfiguration()));
try {
- propertySource.initProperties();
+ propertySource.initProperties(null);
} catch (Exception e) {
assertEquals("Found Feature Flag /foo/test_key_1 with invalid Content Type of ", e.getMessage());
}
@@ -200,7 +200,7 @@ public void initNullInvalidContentTypeFeatureFlagTest() {
when(clientMock.listSettings(Mockito.any()))
.thenReturn(featureListMock).thenReturn(featureListMock);
- propertySource.initProperties();
+ propertySource.initProperties(null);
String[] keyNames = propertySource.getPropertyNames();
String[] expectedKeyNames = {};
@@ -216,7 +216,7 @@ public void testFeatureFlagTargeting() {
when(clientMock.getTracingInfo()).thenReturn(new TracingInfo(false, false, 0, Configuration.getGlobalConfiguration()));
featureFlagStore.setEnabled(true);
- propertySource.initProperties();
+ propertySource.initProperties(null);
FeatureSet featureSetExpected = new FeatureSet();
Feature feature = new Feature();
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 e7ec5fb3e3380..f37d941a78505 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
@@ -97,7 +97,7 @@ public void init() {
String[] labelFilter = { "\0" };
propertySource = new AppConfigurationApplicationSettingPropertySource(TEST_STORE_NAME, replicaClientMock,
- keyVaultClientFactory, KEY_FILTER, labelFilter, 60);
+ keyVaultClientFactory, KEY_FILTER, labelFilter);
TEST_ITEMS.add(ITEM_1);
TEST_ITEMS.add(ITEM_2);
@@ -121,10 +121,10 @@ public void testKeyVaultTest() {
KeyVaultSecret secret = new KeyVaultSecret("mySecret", "mySecretValue");
when(keyVaultClientFactory.getClient(Mockito.eq("https://test.key.vault.com"))).thenReturn(clientManagerMock);
- when(clientManagerMock.getSecret(Mockito.any(URI.class), Mockito.anyInt())).thenReturn(secret);
+ when(clientManagerMock.getSecret(Mockito.any(URI.class))).thenReturn(secret);
try {
- propertySource.initProperties();
+ propertySource.initProperties(null);
} catch (IOException e) {
fail("Failed Reading in Feature Flags");
}
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 247c2db84a7f8..f554ab41f7bb5 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
@@ -5,8 +5,13 @@
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.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import java.io.UncheckedIOException;
+import java.net.UnknownHostException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
@@ -22,7 +27,9 @@
import com.azure.core.http.rest.PagedIterable;
import com.azure.core.util.Configuration;
import com.azure.data.appconfiguration.ConfigurationClient;
+import com.azure.data.appconfiguration.models.CompositionType;
import com.azure.data.appconfiguration.models.ConfigurationSetting;
+import com.azure.data.appconfiguration.models.ConfigurationSettingSnapshot;
import com.azure.data.appconfiguration.models.SettingSelector;
import com.azure.identity.CredentialUnavailableException;
import com.azure.spring.cloud.appconfiguration.config.implementation.http.policy.TracingInfo;
@@ -73,6 +80,9 @@ public void getWatchKeyTest() {
when(responseMock.getStatusCode()).thenReturn(499);
assertThrows(HttpResponseException.class, () -> client.getWatchKey("watch", "\0"));
+
+ when(clientMock.getConfigurationSetting(Mockito.any(), Mockito.any())).thenThrow(new UncheckedIOException(new UnknownHostException()));
+ assertThrows(AppConfigurationStatusException.class, () -> client.getWatchKey("watch", "\0"));
}
@Test
@@ -102,6 +112,15 @@ public void listSettingsTest() {
assertThrows(HttpResponseException.class, () -> client.listSettings(new SettingSelector()));
}
+ @Test
+ public void listSettingsUnknownHostTest() {
+ AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock,
+ new TracingInfo(false, false, 0, Configuration.getGlobalConfiguration()));
+
+ when(clientMock.listConfigurationSettings(Mockito.any())).thenThrow(new UncheckedIOException(new UnknownHostException()));
+ assertThrows(AppConfigurationStatusException.class, () -> client.listSettings(new SettingSelector()));
+ }
+
@Test
public void listSettingsNoCredentialTest() {
AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock,
@@ -158,4 +177,65 @@ public void backoffTest() {
assertEquals(0, client.getFailedAttempts());
}
+ @Test
+ public void listSettingSnapshotTest() {
+ AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock,
+ new TracingInfo(false, false, 0, Configuration.getGlobalConfiguration()));
+
+ List configurations = new ArrayList<>();
+ ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(null);
+ snapshot.setCompositionType(CompositionType.KEY);
+
+ when(clientMock.getSnapshot(Mockito.any())).thenReturn(snapshot);
+ when(clientMock.listConfigurationSettingsForSnapshot(Mockito.any())).thenReturn(settingsMock);
+ when(settingsMock.iterator()).thenReturn(configurations.iterator());
+
+ assertEquals(configurations, client.listSettingSnapshot("SnapshotName"));
+
+ when(clientMock.listConfigurationSettingsForSnapshot(Mockito.any())).thenThrow(exceptionMock);
+ when(exceptionMock.getResponse()).thenReturn(responseMock);
+ when(responseMock.getStatusCode()).thenReturn(429);
+ assertThrows(AppConfigurationStatusException.class, () -> client.listSettingSnapshot("SnapshotName"));
+
+ when(responseMock.getStatusCode()).thenReturn(408);
+ assertThrows(AppConfigurationStatusException.class, () -> client.listSettingSnapshot("SnapshotName"));
+
+ when(responseMock.getStatusCode()).thenReturn(500);
+ assertThrows(AppConfigurationStatusException.class, () -> client.listSettingSnapshot("SnapshotName"));
+
+ when(responseMock.getStatusCode()).thenReturn(499);
+ assertThrows(HttpResponseException.class, () -> client.listSettingSnapshot("SnapshotName"));
+
+ when(clientMock.getSnapshot(Mockito.any())).thenThrow(new UncheckedIOException(new UnknownHostException()));
+ assertThrows(AppConfigurationStatusException.class, () -> client.listSettingSnapshot("SnapshotName"));
+ }
+
+ @Test
+ public void listSettingSnapshotInvalidCompositionTypeTest() {
+ AppConfigurationReplicaClient client = new AppConfigurationReplicaClient(endpoint, clientMock,
+ new TracingInfo(false, false, 0, Configuration.getGlobalConfiguration()));
+
+ ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(null);
+ snapshot.setCompositionType(CompositionType.KEY_LABEL);
+
+ when(clientMock.getSnapshot(Mockito.any())).thenReturn(snapshot);
+
+ IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> client.listSettingSnapshot("SnapshotName"));
+ 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()));
+ String fakeToken = "fake_sync_token";
+
+ client.updateSyncToken(fakeToken);
+ verify(clientMock, times(1)).updateSyncToken(Mockito.eq(fakeToken));
+ reset(clientMock);
+
+ client.updateSyncToken(null);
+ verify(clientMock, times(0)).updateSyncToken(Mockito.eq(fakeToken));
+ }
+
}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationSnapshotPropertySourceTest.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationSnapshotPropertySourceTest.java
new file mode 100644
index 0000000000000..5c810b11b8c0a
--- /dev/null
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationSnapshotPropertySourceTest.java
@@ -0,0 +1,184 @@
+// 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.FEATURE_FLAG_CONTENT_TYPE;
+import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.FEATURE_LABEL;
+import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.FEATURE_VALUE;
+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_1;
+import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_KEY_2;
+import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_KEY_3;
+import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_LABEL_1;
+import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_LABEL_2;
+import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_LABEL_3;
+import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_SLASH_KEY;
+import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_SLASH_VALUE;
+import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_STORE_NAME;
+import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_VALUE_1;
+import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_VALUE_2;
+import static com.azure.spring.cloud.appconfiguration.config.implementation.TestConstants.TEST_VALUE_3;
+import static com.azure.spring.cloud.appconfiguration.config.implementation.TestUtils.createItem;
+import static com.azure.spring.cloud.appconfiguration.config.implementation.TestUtils.createItemFeatureFlag;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import com.azure.core.util.Configuration;
+import com.azure.data.appconfiguration.models.ConfigurationSetting;
+import com.azure.data.appconfiguration.models.FeatureFlagConfigurationSetting;
+import com.azure.spring.cloud.appconfiguration.config.implementation.http.policy.TracingInfo;
+import com.azure.spring.cloud.appconfiguration.config.implementation.properties.AppConfigurationProperties;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.PropertyNamingStrategies;
+
+public class AppConfigurationSnapshotPropertySourceTest {
+
+ private static final String EMPTY_CONTENT_TYPE = "";
+
+ private static final AppConfigurationProperties TEST_PROPS = new AppConfigurationProperties();
+
+ private static final String KEY_FILTER = "/foo/";
+
+ private static final List TRIM = new ArrayList<>();
+
+ private static final String SNAPSHOT_NAME = "snapshot_test";
+
+ private static final ConfigurationSetting ITEM_1 =
+ createItem(KEY_FILTER, TEST_KEY_1, TEST_VALUE_1, TEST_LABEL_1, EMPTY_CONTENT_TYPE);
+
+ private static final ConfigurationSetting ITEM_2 =
+ createItem(KEY_FILTER, TEST_KEY_2, TEST_VALUE_2, TEST_LABEL_2, EMPTY_CONTENT_TYPE);
+
+ private static final ConfigurationSetting ITEM_3 =
+ createItem(KEY_FILTER, TEST_KEY_3, TEST_VALUE_3, TEST_LABEL_3, EMPTY_CONTENT_TYPE);
+
+ private static final ConfigurationSetting ITEM_4 =
+ createItem("/bar/", "test_key_4", "test_value_4", "test_label_4", EMPTY_CONTENT_TYPE);
+
+ private static final FeatureFlagConfigurationSetting FEATURE_ITEM = createItemFeatureFlag(".appconfig.featureflag/",
+ "Alpha", FEATURE_VALUE, FEATURE_LABEL, FEATURE_FLAG_CONTENT_TYPE);
+
+ private static final ConfigurationSetting ITEM_NULL =
+ createItem(KEY_FILTER, TEST_KEY_3, TEST_VALUE_3, TEST_LABEL_3, null);
+
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+
+ private List testItems = new ArrayList<>();
+
+ private AppConfigurationSnapshotPropertySource propertySource;
+
+ @Mock
+ private AppConfigurationReplicaClient clientMock;
+
+ @Mock
+ private AppConfigurationKeyVaultClientFactory keyVaultClientFactoryMock;
+
+ @Mock
+ private List configurationListMock;
+
+ @BeforeAll
+ public static void setup() {
+ TestUtils.addStore(TEST_PROPS, TEST_STORE_NAME, TEST_CONN_STRING, KEY_FILTER);
+ }
+
+ @BeforeEach
+ public void init() {
+ MAPPER.setPropertyNamingStrategy(PropertyNamingStrategies.KEBAB_CASE);
+
+ MockitoAnnotations.openMocks(this);
+
+ testItems = new ArrayList<>();
+ testItems.add(ITEM_1);
+ testItems.add(ITEM_2);
+ testItems.add(ITEM_3);
+ testItems.add(ITEM_4);
+ testItems.add(FEATURE_ITEM);
+
+ TRIM.add(KEY_FILTER);
+
+ propertySource = new AppConfigurationSnapshotPropertySource(TEST_STORE_NAME, clientMock,
+ keyVaultClientFactoryMock, SNAPSHOT_NAME);
+ }
+
+ @AfterEach
+ public void cleanup() throws Exception {
+ MockitoAnnotations.openMocks(this).close();
+ }
+
+ @Test
+ public void testPropCanBeInitAndQueried() throws IOException {
+ when(configurationListMock.iterator()).thenReturn(testItems.iterator());
+ when(clientMock.listSettingSnapshot(Mockito.any())).thenReturn(configurationListMock)
+ .thenReturn(configurationListMock);
+ when(clientMock.getTracingInfo())
+ .thenReturn(new TracingInfo(false, false, 0, Configuration.getGlobalConfiguration()));
+
+ propertySource.initProperties(TRIM);
+
+ String[] keyNames = propertySource.getPropertyNames();
+ String[] expectedKeyNames = testItems.stream().map(t -> {
+ if (t.getKey().startsWith(".appconfig.featureflag/")) {
+ return t.getKey().replace(".appconfig.featureflag/", "feature-management.");
+ }
+ return t.getKey().replaceFirst("^" + KEY_FILTER, "").replace("/", ".");
+
+ }).toArray(String[]::new);
+
+ assertThat(keyNames).containsExactlyInAnyOrder(expectedKeyNames);
+
+ assertThat(propertySource.getProperty(TEST_KEY_1)).isEqualTo(TEST_VALUE_1);
+ assertThat(propertySource.getProperty(TEST_KEY_2)).isEqualTo(TEST_VALUE_2);
+ assertThat(propertySource.getProperty(TEST_KEY_3)).isEqualTo(TEST_VALUE_3);
+ assertThat(propertySource.getProperty(".bar.test_key_4")).isEqualTo("test_value_4");
+ }
+
+ @Test
+ public void testPropertyNameSlashConvertedToDots() throws IOException {
+ ConfigurationSetting slashedProp =
+ createItem(KEY_FILTER, TEST_SLASH_KEY, TEST_SLASH_VALUE, null, EMPTY_CONTENT_TYPE);
+ List settings = new ArrayList<>();
+ settings.add(slashedProp);
+ when(configurationListMock.iterator()).thenReturn(settings.iterator()).thenReturn(Collections.emptyIterator());
+ when(clientMock.listSettingSnapshot(Mockito.any())).thenReturn(configurationListMock)
+ .thenReturn(configurationListMock);
+
+ propertySource.initProperties(TRIM);
+
+ String expectedKeyName = TEST_SLASH_KEY.replace('/', '.');
+ String[] actualKeyNames = propertySource.getPropertyNames();
+
+ assertThat(actualKeyNames.length).isEqualTo(1);
+ assertThat(actualKeyNames[0]).isEqualTo(expectedKeyName);
+ assertThat(propertySource.getProperty(TEST_SLASH_KEY)).isNull();
+ assertThat(propertySource.getProperty(expectedKeyName)).isEqualTo(TEST_SLASH_VALUE);
+ }
+
+ @Test
+ 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);
+
+ propertySource.initProperties(TRIM);
+
+ String[] keyNames = propertySource.getPropertyNames();
+ String[] expectedKeyNames =
+ items.stream().map(t -> t.getKey().substring(KEY_FILTER.length())).toArray(String[]::new);
+
+ assertThat(keyNames).containsExactlyInAnyOrder(expectedKeyNames);
+ }
+}
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/stores/KeyVaultClientTest.java b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/stores/KeyVaultClientTest.java
index 05fd95dc3e2b4..98f2c3ec9bc82 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/stores/KeyVaultClientTest.java
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/stores/KeyVaultClientTest.java
@@ -59,7 +59,7 @@ public void configProviderAuth() throws URISyntaxException {
String keyVaultUri = "https://keyvault.vault.azure.net";
clientStore = new AppConfigurationSecretClientManager(keyVaultUri, null, null, secretClientBuilderFactoryMock,
- false);
+ false, 60);
AppConfigurationSecretClientManager test = Mockito.spy(clientStore);
when(secretClientBuilderFactoryMock.build()).thenReturn(builderMock);
@@ -73,8 +73,8 @@ public void configProviderAuth() throws URISyntaxException {
.thenReturn(monoSecret);
when(monoSecret.block(Mockito.any())).thenReturn(new KeyVaultSecret("", ""));
- assertNotNull(test.getSecret(new URI(keyVaultUri), 10));
- assertEquals(test.getSecret(new URI(keyVaultUri), 10).getName(), "");
+ assertNotNull(test.getSecret(new URI(keyVaultUri)));
+ assertEquals(test.getSecret(new URI(keyVaultUri)).getName(), "");
}
@Test
@@ -82,7 +82,7 @@ public void systemAssignedCredentials() throws URISyntaxException {
String keyVaultUri = "https://keyvault.vault.azure.net/secrets/mySecret";
clientStore = new AppConfigurationSecretClientManager(keyVaultUri, null, null, secretClientBuilderFactoryMock,
- false);
+ false, 60);
AppConfigurationSecretClientManager test = Mockito.spy(clientStore);
when(secretClientBuilderFactoryMock.build()).thenReturn(builderMock);
@@ -96,8 +96,8 @@ public void systemAssignedCredentials() throws URISyntaxException {
.thenReturn(monoSecret);
when(monoSecret.block(Mockito.any())).thenReturn(new KeyVaultSecret("", ""));
- assertNotNull(test.getSecret(new URI(keyVaultUri), 10));
- assertEquals(test.getSecret(new URI(keyVaultUri), 10).getName(), "");
+ assertNotNull(test.getSecret(new URI(keyVaultUri)));
+ assertEquals(test.getSecret(new URI(keyVaultUri)).getName(), "");
}
@Test
@@ -105,15 +105,15 @@ public void secretResolverTest() throws URISyntaxException {
String keyVaultUri = "https://keyvault.vault.azure.net/secrets/mySecret";
clientStore = new AppConfigurationSecretClientManager(keyVaultUri, null, new TestSecretResolver(),
- secretClientBuilderFactoryMock, false);
+ secretClientBuilderFactoryMock, false, 60);
AppConfigurationSecretClientManager test = Mockito.spy(clientStore);
when(secretClientBuilderFactoryMock.build()).thenReturn(builderMock);
when(builderMock.vaultUrl(Mockito.any())).thenReturn(builderMock);
- assertEquals("Test-Value", test.getSecret(new URI(keyVaultUri + "/testSecret"), 10).getValue());
- assertEquals("Default-Secret", test.getSecret(new URI(keyVaultUri + "/testSecret2"), 10).getValue());
+ assertEquals("Test-Value", test.getSecret(new URI(keyVaultUri + "/testSecret")).getValue());
+ assertEquals("Default-Secret", test.getSecret(new URI(keyVaultUri + "/testSecret2")).getValue());
}
class TestSecretResolver implements KeyVaultSecretProvider {
diff --git a/sdk/spring/spring-cloud-azure-starter-appconfiguration-config/README.md b/sdk/spring/spring-cloud-azure-starter-appconfiguration-config/README.md
index fa4116a968cdb..5cc8dd9f84437 100644
--- a/sdk/spring/spring-cloud-azure-starter-appconfiguration-config/README.md
+++ b/sdk/spring/spring-cloud-azure-starter-appconfiguration-config/README.md
@@ -62,6 +62,8 @@ spring.cloud.azure.appconfiguration.stores[0].enabled | Whether the store will b
spring.cloud.azure.appconfiguration.stores[0].fail-fast | Whether to throw a `RuntimeException` or not when failing to read from App Configuration during application start-up. If an exception does occur during startup when set to false the store is skipped. | No | true
spring.cloud.azure.appconfiguration.stores[0].selects[0].key-filter | The key pattern used to indicate which configuration(s) will be loaded. | No | /application/*
spring.cloud.azure.appconfiguration.stores[0].selects[0].label-filter | The label used to indicate which configuration(s) will be loaded. | No | `${spring.profiles.active}` or if null `\0`
+spring.cloud.azure.appconfiguration.stores[0].selects[0].snapshot-name | The snapshot name used to indicate which configuration(s) will be loaded. | No | null
+ spring.cloud.azure.appconfiguration.stores[0].trimKeyPrefix[0] | The prefix that will be trimmed from the key when the configuration is loaded. | No | null, unless using key-filter, then it is the key-filter
Configuration Store Authentication
@@ -168,6 +170,75 @@ spring:
label-filter: ',${spring.profiles.active}'
```
+#### Snapshots
+
+ App Configuration snapshots allow you to freeze a moment in time of your configuration store. Snapshots are immutable. Snapshots are stored in the same configuration store as the rest of your configuration data. Snapshots are identified by a unique snapshot name. The snapshot name is a string that can contain any combination of alphanumeric characters, hyphens, and underscores. The snapshot name is case sensitive and must be unique within the configuration store.
+
+ To load configuration from a snapshot, use the following configuration:
+
+ ```yaml
+ spring:
+ cloud:
+ azure:
+ appconfiguration:
+ stores:
+ -
+ connection-string:
+ selects:
+ -
+ snapshot-name:
+ trimKeyPrefix:
+ - /application/
+ ```
+
+ NOTE: Snapshots have to be of the composition type KEY in order to be loaded, this is to stop configuration name conflicts inside of a snapshot.
+
+ NOTE 2: If keys start with a prefix such as `/application/` a trim value is needed otherwise `/` will be converted to `.` and your key will not be mapped to `@ConfigurationProperties`
+
+ When using snapshots, key-filters and label filters aren't used. The snapshot is loaded as is. You can load multiple snapshots by adding multiple selects, even adding key and label filters to other selects.
+
+ ```yaml
+ spring:
+ cloud:
+ azure:
+ appconfiguration:
+ stores:
+ -
+ connection-string:
+ selects:
+ -
+ snapshot-name:
+ -
+ key-filter:
+ label-filter:
+ ```
+
+ In this case, the snapshot is loaded first then keys from the filter are loaded. If there are duplicate keys, the last key loaded has the highest priority.
+
+ If previously you used these keys in your application outside of a snapshot than they will most likely contain a prefix like `/application/`, when using a key filter the prefix was automatically removed, but it isn't with a snapshot, which means you have to trim your key names.
+
+ ```yaml
+ spring:
+ cloud:
+ azure:
+ appconfiguration:
+ stores:
+ -
+ connection-string:
+ selects:
+ -
+ snapshot-name:
+ trim:
+ - /application/
+ ```
+
+ This will trim the prefix from all keys in the snapshot, and will also trim any other keys selected if they begin with the prefix. This has also been added to the key filter, so you can use it there as well, though it overrides the key-filter name trim.
+
+
+ NOTE: If you are only using snapshots, you don't have to monitor the configuration store, as snapshots are immutable. But if you are using snapshots and other configuration data, you can still monitor the configuration store.
+
+ NOTE: If your snapshot includes feature flags they will automatically be loaded even if feature flags are disabled. If feature flags are enabled, the feature flags will be loaded, any feature flags loaded this way take priority of feature flags loaded from snapshots.
+
#### Configuration Refresh
Configuration Refresh feature allows the application to load the latest property value from configuration store automatically, without restarting the application.
From 70893b948c9914b66b0d5afc4385fab563daee0f Mon Sep 17 00:00:00 2001
From: Matt Metcalf
Date: Tue, 12 Sep 2023 14:38:31 -0700
Subject: [PATCH 2/7] Updating witch change log and undoing a few changes in
main library for build
---
eng/versioning/version_client.txt | 1 +
.../azure-data-appconfiguration/assets.json | 2 +-
.../azure-data-appconfiguration/pom.xml | 4 +-
.../ConfigurationAsyncClientTest.java | 9 +-
.../ConfigurationClientTest.java | 206 +++++++++++++++---
.../ConfigurationClientTestBase.java | 27 ++-
.../CHANGELOG.md | 11 +-
.../CHANGELOG.md | 11 +-
.../CHANGELOG.md | 11 +-
.../CHANGELOG.md | 11 +-
.../CHANGELOG.md | 11 +-
.../README.md | 4 +-
12 files changed, 234 insertions(+), 74 deletions(-)
diff --git a/eng/versioning/version_client.txt b/eng/versioning/version_client.txt
index 9159c8a6afede..535c40a8b9378 100644
--- a/eng/versioning/version_client.txt
+++ b/eng/versioning/version_client.txt
@@ -445,5 +445,6 @@ unreleased_com.azure:azure-core-test;1.20.0-beta.1
beta_com.azure:azure-communication-common;1.3.0-beta.1
beta_com.azure:azure-core-http-netty;1.14.0-beta.1
beta_com.azure:azure-core;1.42.0-beta.1
+beta_com.azure:azure-data-appconfiguration;1.5.0-beta.1
diff --git a/sdk/appconfiguration/azure-data-appconfiguration/assets.json b/sdk/appconfiguration/azure-data-appconfiguration/assets.json
index fc8544394a3eb..3a2147ea900b2 100644
--- a/sdk/appconfiguration/azure-data-appconfiguration/assets.json
+++ b/sdk/appconfiguration/azure-data-appconfiguration/assets.json
@@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "java",
"TagPrefix": "java/appconfiguration/azure-data-appconfiguration",
- "Tag": "java/appconfiguration/azure-data-appconfiguration_e4b3d8b190"
+ "Tag": "java/appconfiguration/azure-data-appconfiguration_d6483d4636"
}
diff --git a/sdk/appconfiguration/azure-data-appconfiguration/pom.xml b/sdk/appconfiguration/azure-data-appconfiguration/pom.xml
index 3e788256af75b..7e2b74d6d6c39 100644
--- a/sdk/appconfiguration/azure-data-appconfiguration/pom.xml
+++ b/sdk/appconfiguration/azure-data-appconfiguration/pom.xml
@@ -104,7 +104,7 @@
io.projectreactor
reactor-test
- 3.5.8
+ 3.4.31
test
@@ -127,7 +127,7 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.11.0
+ 3.10.1
default-testCompile
diff --git a/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationAsyncClientTest.java b/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationAsyncClientTest.java
index 9730cd5bde5f5..42bab30b6dc21 100644
--- a/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationAsyncClientTest.java
+++ b/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationAsyncClientTest.java
@@ -1216,6 +1216,7 @@ public void listRevisionsWithPaginationAndRepeatIterator(HttpClient httpClient,
* Verifies that, given a ton of existing settings, we can list the ConfigurationSettings using pagination
* (ie. where 'nextLink' has a URL pointing to the next page of results.
*/
+ @Disabled("Error code 403 TOO_MANY_REQUESTS https://github.com/Azure/azure-sdk-for-java/issues/36602")
@ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
@MethodSource("com.azure.data.appconfiguration.TestHelper#getTestParameters")
public void listConfigurationSettingsWithPagination(HttpClient httpClient, ConfigurationServiceVersion serviceVersion) {
@@ -1609,7 +1610,6 @@ public void listSnapshots(HttpClient httpClient, ConfigurationServiceVersion ser
.verifyComplete();
});
-
for (ConfigurationSettingSnapshot snapshot : actualSnapshots) {
// List only the snapshot with a specific name
StepVerifier.create(client.listSnapshots(
@@ -1631,8 +1631,8 @@ public void listSettingFromSnapshot(HttpClient httpClient, ConfigurationServiceV
// Create a snapshot
createSnapshotRunner((name, filters) -> {
- // Prepare 50 settings before creating a snapshot
- final int numberExpected = 50;
+ // Prepare 5 settings before creating a snapshot
+ final int numberExpected = 5;
List settings = new ArrayList<>(numberExpected);
for (int value = 0; value < numberExpected; value++) {
settings.add(new ConfigurationSetting().setKey(name + "-" + value));
@@ -1655,8 +1655,7 @@ public void listSettingFromSnapshot(HttpClient httpClient, ConfigurationServiceV
ConfigurationSettingSnapshot snapshotResult = poller.getFinalResult();
assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
- MINIMUM_RETENTION_PERIOD, Long.valueOf(15000), Long.valueOf(50), null, snapshotResult);
-
+ MINIMUM_RETENTION_PERIOD, Long.valueOf(15000), Long.valueOf(numberExpected), null, snapshotResult);
StepVerifier.create(client.listConfigurationSettingsForSnapshot(name))
.expectNextCount(numberExpected)
diff --git a/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTest.java b/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTest.java
index 5b85f7256ba18..c55d3c3598d3d 100644
--- a/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTest.java
+++ b/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTest.java
@@ -21,6 +21,7 @@
import com.azure.data.appconfiguration.models.SecretReferenceConfigurationSetting;
import com.azure.data.appconfiguration.models.SettingFields;
import com.azure.data.appconfiguration.models.SettingSelector;
+import com.azure.data.appconfiguration.models.SnapshotSelector;
import com.azure.data.appconfiguration.models.SnapshotStatus;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
@@ -935,6 +936,7 @@ public void listRevisionsWithPaginationAndRepeatIterator(HttpClient httpClient,
* Verifies that, given a ton of existing settings, we can list the ConfigurationSettings using pagination
* (ie. where 'nextLink' has a URL pointing to the next page of results.)
*/
+ @Disabled("Error code 403 TOO_MANY_REQUESTS https://github.com/Azure/azure-sdk-for-java/issues/36602")
@ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
@MethodSource("com.azure.data.appconfiguration.TestHelper#getTestParameters")
public void listConfigurationSettingsWithPagination(HttpClient httpClient, ConfigurationServiceVersion serviceVersion) {
@@ -1005,11 +1007,8 @@ public void createSnapshot(HttpClient httpClient, ConfigurationServiceVersion se
client.addConfigurationSettingWithResponse(expected, Context.NONE).getValue()));
createSnapshotRunner((name, filters) -> {
- // Retention period can be setup when creating a snapshot and cannot edit.
- Duration retentionPeriod = Duration.ofMinutes(60);
-
ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
- .setRetentionPeriod(retentionPeriod);
+ .setRetentionPeriod(MINIMUM_RETENTION_PERIOD);
SyncPoller poller =
client.beginCreateSnapshot(name, snapshot, Context.NONE);
poller.setPollInterval(Duration.ofSeconds(10));
@@ -1018,7 +1017,7 @@ public void createSnapshot(HttpClient httpClient, ConfigurationServiceVersion se
assertEqualsConfigurationSettingSnapshot(name,
SnapshotStatus.READY, filters, CompositionType.KEY,
- retentionPeriod, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
+ MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
// Archived the snapshot, it will be deleted automatically when retention period expires.
assertEquals(SnapshotStatus.ARCHIVED, client.archiveSnapshot(name).getStatus());
@@ -1034,11 +1033,8 @@ public void getSnapshot(HttpClient httpClient, ConfigurationServiceVersion servi
client.addConfigurationSettingWithResponse(expected, Context.NONE).getValue()));
createSnapshotRunner((name, filters) -> {
- // Retention period can be setup when creating a snapshot and cannot edit.
- Duration retentionPeriod = Duration.ofMinutes(60);
-
ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
- .setRetentionPeriod(retentionPeriod);
+ .setRetentionPeriod(MINIMUM_RETENTION_PERIOD);
SyncPoller poller =
client.beginCreateSnapshot(name, snapshot, Context.NONE);
poller.setPollInterval(Duration.ofSeconds(10));
@@ -1046,13 +1042,13 @@ public void getSnapshot(HttpClient httpClient, ConfigurationServiceVersion servi
ConfigurationSettingSnapshot snapshotResult = poller.getFinalResult();
assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
- retentionPeriod, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
+ MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
// Retrieve a snapshot after creation
Response getSnapshot = client.getSnapshotWithResponse(name, Context.NONE);
assertConfigurationSettingSnapshotWithResponse(200, name,
SnapshotStatus.READY, filters, CompositionType.KEY,
- retentionPeriod, Long.valueOf(1000), Long.valueOf(0), null, getSnapshot);
+ MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, getSnapshot);
// Archived the snapshot, it will be deleted automatically when retention period expires.
ConfigurationSettingSnapshot archivedSnapshot = client.archiveSnapshot(name);
@@ -1069,18 +1065,20 @@ public void getSnapshotConvenience(HttpClient httpClient, ConfigurationServiceVe
client.addConfigurationSettingWithResponse(expected, Context.NONE).getValue()));
createSnapshotRunner((name, filters) -> {
+ ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
+ .setRetentionPeriod(MINIMUM_RETENTION_PERIOD);
SyncPoller poller =
- client.beginCreateSnapshot(name, new ConfigurationSettingSnapshot(filters), Context.NONE);
+ client.beginCreateSnapshot(name, snapshot, Context.NONE);
poller.setPollInterval(Duration.ofSeconds(10));
poller.waitForCompletion();
ConfigurationSettingSnapshot snapshotResult = poller.getFinalResult();
assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
- DEFAULT_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
+ MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
// Retrieve a snapshot after creation
assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
- DEFAULT_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null,
+ MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null,
client.getSnapshot(name));
// Archived the snapshot, it will be deleted automatically when retention period expires.
@@ -1091,7 +1089,37 @@ public void getSnapshotConvenience(HttpClient httpClient, ConfigurationServiceVe
@ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
@MethodSource("com.azure.data.appconfiguration.TestHelper#getTestParameters")
- public void recoverSnapshot(HttpClient httpClient, ConfigurationServiceVersion serviceVersion) {
+ public void archiveSnapshot(HttpClient httpClient, ConfigurationServiceVersion serviceVersion) {
+ client = getConfigurationClient(httpClient, serviceVersion);
+ // Prepare a setting before creating a snapshot
+ addConfigurationSettingRunner((expected) -> assertConfigurationEquals(expected,
+ client.addConfigurationSettingWithResponse(expected, Context.NONE).getValue()));
+
+ createSnapshotRunner((name, filters) -> {
+ // Retention period can be setup when creating a snapshot and cannot edit.
+ ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
+ .setRetentionPeriod(MINIMUM_RETENTION_PERIOD);
+ SyncPoller poller =
+ client.beginCreateSnapshot(name, snapshot, Context.NONE);
+ poller.setPollInterval(Duration.ofSeconds(10));
+ poller.waitForCompletion();
+ ConfigurationSettingSnapshot snapshotResult = poller.getFinalResult();
+
+ assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
+ MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
+
+ // Archived the snapshot, it will be deleted automatically when retention period expires.
+ Response response = client.archiveSnapshotWithResponse(snapshotResult,
+ false, Context.NONE);
+ assertConfigurationSettingSnapshotWithResponse(200, name,
+ SnapshotStatus.ARCHIVED, filters, CompositionType.KEY,
+ MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, response);
+ });
+ }
+
+ @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
+ @MethodSource("com.azure.data.appconfiguration.TestHelper#getTestParameters")
+ public void archiveSnapshotConvenience(HttpClient httpClient, ConfigurationServiceVersion serviceVersion) {
client = getConfigurationClient(httpClient, serviceVersion);
// Prepare a setting before creating a snapshot
addConfigurationSettingRunner((expected) -> assertConfigurationEquals(expected,
@@ -1099,10 +1127,35 @@ public void recoverSnapshot(HttpClient httpClient, ConfigurationServiceVersion s
createSnapshotRunner((name, filters) -> {
// Retention period can be setup when creating a snapshot and cannot edit.
- Duration retentionPeriod = Duration.ofMinutes(60);
+ ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
+ .setRetentionPeriod(MINIMUM_RETENTION_PERIOD);
+ SyncPoller poller =
+ client.beginCreateSnapshot(name, snapshot, Context.NONE);
+ poller.setPollInterval(Duration.ofSeconds(10));
+ poller.waitForCompletion();
+ ConfigurationSettingSnapshot snapshotResult = poller.getFinalResult();
+
+ assertEqualsConfigurationSettingSnapshot(name,
+ SnapshotStatus.READY, filters, CompositionType.KEY,
+ MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
+
+ // Archived the snapshot, it will be deleted automatically when retention period expires.
+ ConfigurationSettingSnapshot archivedSnapshot = client.archiveSnapshot(name);
+ assertEquals(SnapshotStatus.ARCHIVED, archivedSnapshot.getStatus());
+ });
+ }
+
+ @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
+ @MethodSource("com.azure.data.appconfiguration.TestHelper#getTestParameters")
+ public void recoverSnapshot(HttpClient httpClient, ConfigurationServiceVersion serviceVersion) {
+ client = getConfigurationClient(httpClient, serviceVersion);
+ // Prepare a setting before creating a snapshot
+ addConfigurationSettingRunner((expected) -> assertConfigurationEquals(expected,
+ client.addConfigurationSettingWithResponse(expected, Context.NONE).getValue()));
+ createSnapshotRunner((name, filters) -> {
ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
- .setRetentionPeriod(retentionPeriod);
+ .setRetentionPeriod(MINIMUM_RETENTION_PERIOD);
SyncPoller poller =
client.beginCreateSnapshot(name, snapshot, Context.NONE);
poller.setPollInterval(Duration.ofSeconds(10));
@@ -1110,12 +1163,12 @@ public void recoverSnapshot(HttpClient httpClient, ConfigurationServiceVersion s
ConfigurationSettingSnapshot snapshotResult = poller.getFinalResult();
assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
- retentionPeriod, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
+ MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
// Archived the snapshot
assertEqualsConfigurationSettingSnapshot(name,
SnapshotStatus.ARCHIVED, filters, CompositionType.KEY,
- retentionPeriod, Long.valueOf(1000), Long.valueOf(0), null,
+ MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null,
client.archiveSnapshot(name));
// Recover the snapshot, it will be deleted automatically when retention period expires.
@@ -1123,7 +1176,7 @@ public void recoverSnapshot(HttpClient httpClient, ConfigurationServiceVersion s
client.recoverSnapshotWithResponse(snapshotResult, false, Context.NONE);
assertConfigurationSettingSnapshotWithResponse(200, name,
SnapshotStatus.READY, filters, CompositionType.KEY,
- retentionPeriod, Long.valueOf(1000), Long.valueOf(0), null,
+ MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null,
configurationSettingSnapshotResponse);
// Archived the snapshot, it will be deleted automatically when retention period expires.
@@ -1140,11 +1193,8 @@ public void recoverSnapshotConvenience(HttpClient httpClient, ConfigurationServi
client.addConfigurationSettingWithResponse(expected, Context.NONE).getValue()));
createSnapshotRunner((name, filters) -> {
- // Retention period can be setup when creating a snapshot and cannot edit.
- Duration retentionPeriod = Duration.ofMinutes(60);
-
ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
- .setRetentionPeriod(retentionPeriod);
+ .setRetentionPeriod(MINIMUM_RETENTION_PERIOD);
SyncPoller poller =
client.beginCreateSnapshot(name, snapshot, Context.NONE);
poller.setPollInterval(Duration.ofSeconds(10));
@@ -1152,14 +1202,118 @@ public void recoverSnapshotConvenience(HttpClient httpClient, ConfigurationServi
ConfigurationSettingSnapshot snapshotResult = poller.getFinalResult();
assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
- retentionPeriod, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
+ MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
// Archived the snapshot
assertEquals(SnapshotStatus.ARCHIVED, client.archiveSnapshot(name).getStatus());
// Recover the snapshot, it will be deleted automatically when retention period expires.
assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
- retentionPeriod, Long.valueOf(1000), Long.valueOf(0), null, client.recoverSnapshot(name));
+ MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null,
+ client.recoverSnapshot(name));
+
+ // Archived the snapshot, it will be deleted automatically when retention period expires.
+ assertEquals(SnapshotStatus.ARCHIVED, client.archiveSnapshot(name).getStatus());
+ });
+ }
+
+ @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
+ @MethodSource("com.azure.data.appconfiguration.TestHelper#getTestParameters")
+ public void listSnapshots(HttpClient httpClient, ConfigurationServiceVersion serviceVersion) {
+ client = getConfigurationClient(httpClient, serviceVersion);
+
+ List allExistingSnapshots = new ArrayList<>();
+ client.listSnapshots(new SnapshotSelector().setSnapshotStatus(SnapshotStatus.READY))
+ .stream()
+ .map(snapshot -> allExistingSnapshots.add(snapshot));
+
+ // Clean all ready snapshots
+ for (ConfigurationSettingSnapshot existSnapshot : allExistingSnapshots) {
+ client.archiveSnapshot(existSnapshot.getName());
+ }
+
+ // Prepare a setting before creating a snapshot
+ addConfigurationSettingRunner((expected) -> assertConfigurationEquals(expected,
+ client.addConfigurationSettingWithResponse(expected, Context.NONE).getValue()));
+
+ List actualSnapshots = new ArrayList<>();
+
+ // Create first snapshot
+ createSnapshotRunner((name, filters) -> {
+ ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
+ .setRetentionPeriod(MINIMUM_RETENTION_PERIOD);
+ SyncPoller poller =
+ client.beginCreateSnapshot(name, snapshot, Context.NONE);
+ poller.setPollInterval(Duration.ofSeconds(10));
+ poller.waitForCompletion();
+ ConfigurationSettingSnapshot snapshotResult = poller.getFinalResult();
+
+ assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
+ MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
+
+ // Archived the snapshot, it will be deleted automatically when retention period expires.
+ assertEquals(SnapshotStatus.ARCHIVED, client.archiveSnapshot(name).getStatus());
+ });
+
+ // Create second snapshot
+ createSnapshotRunner((name, filters) -> {
+ ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
+ .setRetentionPeriod(MINIMUM_RETENTION_PERIOD);
+ SyncPoller poller =
+ client.beginCreateSnapshot(name, snapshot, Context.NONE);
+ poller.setPollInterval(Duration.ofSeconds(10));
+ poller.waitForCompletion();
+ ConfigurationSettingSnapshot snapshotResult = poller.getFinalResult();
+
+ assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
+ MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
+
+ // Archived the snapshot, it will be deleted automatically when retention period expires.
+ assertEquals(SnapshotStatus.ARCHIVED, client.archiveSnapshot(name).getStatus());
+ });
+
+
+ for (ConfigurationSettingSnapshot snapshot : actualSnapshots) {
+ // List only the snapshot with a specific name
+ client.listSnapshots(new SnapshotSelector().setName(snapshot.getName()));
+
+ // Archived the snapshot, it will be deleted automatically when retention period expires.
+ assertEquals(SnapshotStatus.ARCHIVED, client.archiveSnapshot(snapshot.getName()).getStatus());
+ }
+ }
+
+ @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
+ @MethodSource("com.azure.data.appconfiguration.TestHelper#getTestParameters")
+ public void listSettingFromSnapshot(HttpClient httpClient, ConfigurationServiceVersion serviceVersion) {
+ client = getConfigurationClient(httpClient, serviceVersion);
+
+ // Create a snapshot
+ createSnapshotRunner((name, filters) -> {
+ // Prepare 5 settings before creating a snapshot
+ final int numberExpected = 5;
+ List settings = new ArrayList<>(numberExpected);
+ for (int value = 0; value < numberExpected; value++) {
+ settings.add(new ConfigurationSetting().setKey(name + "-" + value));
+ }
+ for (ConfigurationSetting setting : settings) {
+ client.setConfigurationSetting(setting);
+ }
+ SettingSelector filter = new SettingSelector().setKeyFilter(name + "-*");
+ assertEquals(numberExpected, client.listConfigurationSettings(filter).stream().count());
+
+ // Retention period can be setup when creating a snapshot and cannot edit.
+ ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
+ .setRetentionPeriod(MINIMUM_RETENTION_PERIOD);
+ SyncPoller poller =
+ client.beginCreateSnapshot(name, snapshot, Context.NONE);
+ poller.setPollInterval(Duration.ofSeconds(10));
+ poller.waitForCompletion();
+ ConfigurationSettingSnapshot snapshotResult = poller.getFinalResult();
+
+ assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
+ MINIMUM_RETENTION_PERIOD, Long.valueOf(15000), Long.valueOf(numberExpected), null, snapshotResult);
+
+ assertEquals(numberExpected, client.listConfigurationSettingsForSnapshot(name).stream().count());
// Archived the snapshot, it will be deleted automatically when retention period expires.
assertEquals(SnapshotStatus.ARCHIVED, client.archiveSnapshot(name).getStatus());
diff --git a/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTestBase.java b/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTestBase.java
index ff0fec87beab8..99cc31b1418b9 100644
--- a/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTestBase.java
+++ b/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTestBase.java
@@ -9,7 +9,6 @@
import com.azure.core.test.TestProxyTestBase;
import com.azure.core.util.Configuration;
import com.azure.core.util.CoreUtils;
-import com.azure.core.util.logging.ClientLogger;
import com.azure.data.appconfiguration.implementation.ConfigurationClientCredentials;
import com.azure.data.appconfiguration.implementation.ConfigurationSettingHelper;
import com.azure.data.appconfiguration.models.CompositionType;
@@ -56,12 +55,10 @@ public abstract class ConfigurationClientTestBase extends TestProxyTestBase {
public static final String FAKE_CONNECTION_STRING =
"Endpoint=https://localhost:8080;Id=0000000000000;Secret=fakeSecrePlaceholder";
- static final Duration DEFAULT_RETENTION_PERIOD = Duration.ofSeconds(2592000);
static final Duration MINIMUM_RETENTION_PERIOD = Duration.ofHours(1);
static String connectionString;
- private final ClientLogger logger = new ClientLogger(ConfigurationClientTestBase.class);
String keyPrefix;
String labelPrefix;
@@ -558,6 +555,30 @@ void createSnapshotRunner(BiConsumer> testRu
testRunner.accept(snapshotName, filters);
}
+ @Test
+ public abstract void getSnapshot(HttpClient httpClient, ConfigurationServiceVersion serviceVersion);
+
+ @Test
+ public abstract void getSnapshotConvenience(HttpClient httpClient, ConfigurationServiceVersion serviceVersion);
+
+ @Test
+ public abstract void archiveSnapshot(HttpClient httpClient, ConfigurationServiceVersion serviceVersion);
+
+ @Test
+ public abstract void archiveSnapshotConvenience(HttpClient httpClient, ConfigurationServiceVersion serviceVersion);
+
+ @Test
+ public abstract void recoverSnapshot(HttpClient httpClient, ConfigurationServiceVersion serviceVersion);
+
+ @Test
+ public abstract void recoverSnapshotConvenience(HttpClient httpClient, ConfigurationServiceVersion serviceVersion);
+
+ @Test
+ public abstract void listSnapshots(HttpClient httpClient, ConfigurationServiceVersion serviceVersion);
+
+ @Test
+ public abstract void listSettingFromSnapshot(HttpClient httpClient, ConfigurationServiceVersion serviceVersion);
+
/**
* Helper method to verify that the RestResponse matches what was expected. This method assumes a response status of 200.
*
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config-web/CHANGELOG.md b/sdk/spring/spring-cloud-azure-appconfiguration-config-web/CHANGELOG.md
index c33acfa86d4c1..c6ae3e2274edf 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config-web/CHANGELOG.md
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config-web/CHANGELOG.md
@@ -1,14 +1,11 @@
# Release History
-## 5.6.0-beta.1 (Unreleased)
+## 5.6.0-beta.1 (2023-09-11)
-### Features Added
-
-### Breaking Changes
+ ### Features Added
-### Bugs Fixed
-
-### Other Changes
+ * Snapshot support using, `spring.cloud.azure.appconfiguration.stores[0].selects[0].snapshot-name`.
+ * Support for trimming prefixes from keys, default value is the key-filter when key-filter is used. `spring.cloud.azure.appconfiguration.stores[0].trim-key-prefix`
## 5.5.0 (2023-08-28)
diff --git a/sdk/spring/spring-cloud-azure-appconfiguration-config/CHANGELOG.md b/sdk/spring/spring-cloud-azure-appconfiguration-config/CHANGELOG.md
index b884a8a4f71e6..0d1658e04c17a 100644
--- a/sdk/spring/spring-cloud-azure-appconfiguration-config/CHANGELOG.md
+++ b/sdk/spring/spring-cloud-azure-appconfiguration-config/CHANGELOG.md
@@ -1,14 +1,11 @@
# Release History
-## 5.6.0-beta.1 (Unreleased)
+## 5.6.0-beta.1 (2023-09-11)
-### Features Added
-
-### Breaking Changes
+ ### Features Added
-### Bugs Fixed
-
-### Other Changes
+ * Snapshot support using, `spring.cloud.azure.appconfiguration.stores[0].selects[0].snapshot-name`.
+ * Support for trimming prefixes from keys, default value is the key-filter when key-filter is used. `spring.cloud.azure.appconfiguration.stores[0].trim-key-prefix`
## 5.5.0 (2023-08-28)
diff --git a/sdk/spring/spring-cloud-azure-feature-management-web/CHANGELOG.md b/sdk/spring/spring-cloud-azure-feature-management-web/CHANGELOG.md
index 6594559a9261a..a0a6d6ca349a3 100644
--- a/sdk/spring/spring-cloud-azure-feature-management-web/CHANGELOG.md
+++ b/sdk/spring/spring-cloud-azure-feature-management-web/CHANGELOG.md
@@ -1,14 +1,11 @@
# Release History
-## 5.6.0-beta.1 (Unreleased)
+## 5.6.0-beta.1 (2023-09-11)
-### Features Added
+ ### Features Added
-### Breaking Changes
-
-### Bugs Fixed
-
-### Other Changes
+ * Snapshot support using, `spring.cloud.azure.appconfiguration.stores[0].selects[0].snapshot-name`.
+ * Support for trimming prefixes from keys, default value is the key-filter when key-filter is used. `spring.cloud.azure.appconfiguration.stores[0].trim-key-prefix`
## 5.5.0 (2023-08-28)
diff --git a/sdk/spring/spring-cloud-azure-feature-management/CHANGELOG.md b/sdk/spring/spring-cloud-azure-feature-management/CHANGELOG.md
index 70784437b504f..25800b26b7797 100644
--- a/sdk/spring/spring-cloud-azure-feature-management/CHANGELOG.md
+++ b/sdk/spring/spring-cloud-azure-feature-management/CHANGELOG.md
@@ -1,14 +1,11 @@
# Release History
-## 5.6.0-beta.1 (Unreleased)
+## 5.6.0-beta.1 (2023-09-11)
-### Features Added
-
-### Breaking Changes
-
-### Bugs Fixed
+ ### Features Added
-### Other Changes
+ * Snapshot support using, `spring.cloud.azure.appconfiguration.stores[0].selects[0].snapshot-name`.
+ * Support for trimming prefixes from keys, default value is the key-filter when key-filter is used. `spring.cloud.azure.appconfiguration.stores[0].trim-key-prefix`
## 5.5.0 (2023-08-28)
diff --git a/sdk/spring/spring-cloud-azure-starter-appconfiguration-config/CHANGELOG.md b/sdk/spring/spring-cloud-azure-starter-appconfiguration-config/CHANGELOG.md
index e0efa8e931934..0ede9498c2de5 100644
--- a/sdk/spring/spring-cloud-azure-starter-appconfiguration-config/CHANGELOG.md
+++ b/sdk/spring/spring-cloud-azure-starter-appconfiguration-config/CHANGELOG.md
@@ -1,14 +1,11 @@
# Release History
-## 5.6.0-beta.1 (Unreleased)
+## 5.6.0-beta.1 (2023-09-11)
-### Features Added
-
-### Breaking Changes
-
-### Bugs Fixed
+ ### Features Added
-### Other Changes
+ * Snapshot support using, `spring.cloud.azure.appconfiguration.stores[0].selects[0].snapshot-name`.
+ * Support for trimming prefixes from keys, default value is the key-filter when key-filter is used. `spring.cloud.azure.appconfiguration.stores[0].trim-key-prefix`
## 5.5.0 (2023-08-28)
diff --git a/sdk/spring/spring-cloud-azure-starter-appconfiguration-config/README.md b/sdk/spring/spring-cloud-azure-starter-appconfiguration-config/README.md
index 5cc8dd9f84437..e176589b280dd 100644
--- a/sdk/spring/spring-cloud-azure-starter-appconfiguration-config/README.md
+++ b/sdk/spring/spring-cloud-azure-starter-appconfiguration-config/README.md
@@ -63,7 +63,7 @@ spring.cloud.azure.appconfiguration.stores[0].fail-fast | Whether to throw a `Ru
spring.cloud.azure.appconfiguration.stores[0].selects[0].key-filter | The key pattern used to indicate which configuration(s) will be loaded. | No | /application/*
spring.cloud.azure.appconfiguration.stores[0].selects[0].label-filter | The label used to indicate which configuration(s) will be loaded. | No | `${spring.profiles.active}` or if null `\0`
spring.cloud.azure.appconfiguration.stores[0].selects[0].snapshot-name | The snapshot name used to indicate which configuration(s) will be loaded. | No | null
- spring.cloud.azure.appconfiguration.stores[0].trimKeyPrefix[0] | The prefix that will be trimmed from the key when the configuration is loaded. | No | null, unless using key-filter, then it is the key-filter
+ spring.cloud.azure.appconfiguration.stores[0].trim-key-prefix[0] | The prefix that will be trimmed from the key when the configuration is loaded. | No | null, unless using key-filter, then it is the key-filter
Configuration Store Authentication
@@ -187,7 +187,7 @@ spring:
selects:
-
snapshot-name:
- trimKeyPrefix:
+ trim-key-prefix:
- /application/
```
From 94a82b02243107286f8ac12e8a0658fa82c79acf Mon Sep 17 00:00:00 2001
From: Matt Metcalf
Date: Tue, 12 Sep 2023 16:34:04 -0700
Subject: [PATCH 3/7] Update pom.xml
---
sdk/appconfiguration/azure-data-appconfiguration/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sdk/appconfiguration/azure-data-appconfiguration/pom.xml b/sdk/appconfiguration/azure-data-appconfiguration/pom.xml
index f116c853a959d..0d8a1088c7de7 100644
--- a/sdk/appconfiguration/azure-data-appconfiguration/pom.xml
+++ b/sdk/appconfiguration/azure-data-appconfiguration/pom.xml
@@ -127,7 +127,7 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.10.1
+ 3.11.0
default-testCompile
From 176f8edf15372cf8e4e88eb8f44b89873b882f03 Mon Sep 17 00:00:00 2001
From: Matt Metcalf
Date: Thu, 14 Sep 2023 13:46:24 -0700
Subject: [PATCH 4/7] reverting change
---
.../azure-data-appconfiguration/assets.json | 2 +-
.../ConfigurationAsyncClientTest.java | 8 +--
.../ConfigurationClientTest.java | 64 ++++++-------------
.../ConfigurationClientTestBase.java | 27 +-------
4 files changed, 26 insertions(+), 75 deletions(-)
diff --git a/sdk/appconfiguration/azure-data-appconfiguration/assets.json b/sdk/appconfiguration/azure-data-appconfiguration/assets.json
index 3a2147ea900b2..fc8544394a3eb 100644
--- a/sdk/appconfiguration/azure-data-appconfiguration/assets.json
+++ b/sdk/appconfiguration/azure-data-appconfiguration/assets.json
@@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "java",
"TagPrefix": "java/appconfiguration/azure-data-appconfiguration",
- "Tag": "java/appconfiguration/azure-data-appconfiguration_d6483d4636"
+ "Tag": "java/appconfiguration/azure-data-appconfiguration_e4b3d8b190"
}
diff --git a/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationAsyncClientTest.java b/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationAsyncClientTest.java
index 42bab30b6dc21..74c31cecea2f8 100644
--- a/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationAsyncClientTest.java
+++ b/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationAsyncClientTest.java
@@ -1216,7 +1216,6 @@ public void listRevisionsWithPaginationAndRepeatIterator(HttpClient httpClient,
* Verifies that, given a ton of existing settings, we can list the ConfigurationSettings using pagination
* (ie. where 'nextLink' has a URL pointing to the next page of results.
*/
- @Disabled("Error code 403 TOO_MANY_REQUESTS https://github.com/Azure/azure-sdk-for-java/issues/36602")
@ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
@MethodSource("com.azure.data.appconfiguration.TestHelper#getTestParameters")
public void listConfigurationSettingsWithPagination(HttpClient httpClient, ConfigurationServiceVersion serviceVersion) {
@@ -1610,6 +1609,7 @@ public void listSnapshots(HttpClient httpClient, ConfigurationServiceVersion ser
.verifyComplete();
});
+
for (ConfigurationSettingSnapshot snapshot : actualSnapshots) {
// List only the snapshot with a specific name
StepVerifier.create(client.listSnapshots(
@@ -1631,8 +1631,8 @@ public void listSettingFromSnapshot(HttpClient httpClient, ConfigurationServiceV
// Create a snapshot
createSnapshotRunner((name, filters) -> {
- // Prepare 5 settings before creating a snapshot
- final int numberExpected = 5;
+ // Prepare 50 settings before creating a snapshot
+ final int numberExpected = 50;
List settings = new ArrayList<>(numberExpected);
for (int value = 0; value < numberExpected; value++) {
settings.add(new ConfigurationSetting().setKey(name + "-" + value));
@@ -1655,7 +1655,7 @@ public void listSettingFromSnapshot(HttpClient httpClient, ConfigurationServiceV
ConfigurationSettingSnapshot snapshotResult = poller.getFinalResult();
assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
- MINIMUM_RETENTION_PERIOD, Long.valueOf(15000), Long.valueOf(numberExpected), null, snapshotResult);
+ MINIMUM_RETENTION_PERIOD, Long.valueOf(15000), Long.valueOf(50), null, snapshotResult);
StepVerifier.create(client.listConfigurationSettingsForSnapshot(name))
.expectNextCount(numberExpected)
diff --git a/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTest.java b/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTest.java
index c55d3c3598d3d..e0fae44e0aff5 100644
--- a/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTest.java
+++ b/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTest.java
@@ -21,7 +21,6 @@
import com.azure.data.appconfiguration.models.SecretReferenceConfigurationSetting;
import com.azure.data.appconfiguration.models.SettingFields;
import com.azure.data.appconfiguration.models.SettingSelector;
-import com.azure.data.appconfiguration.models.SnapshotSelector;
import com.azure.data.appconfiguration.models.SnapshotStatus;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
@@ -936,7 +935,6 @@ public void listRevisionsWithPaginationAndRepeatIterator(HttpClient httpClient,
* Verifies that, given a ton of existing settings, we can list the ConfigurationSettings using pagination
* (ie. where 'nextLink' has a URL pointing to the next page of results.)
*/
- @Disabled("Error code 403 TOO_MANY_REQUESTS https://github.com/Azure/azure-sdk-for-java/issues/36602")
@ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
@MethodSource("com.azure.data.appconfiguration.TestHelper#getTestParameters")
public void listConfigurationSettingsWithPagination(HttpClient httpClient, ConfigurationServiceVersion serviceVersion) {
@@ -1007,8 +1005,11 @@ public void createSnapshot(HttpClient httpClient, ConfigurationServiceVersion se
client.addConfigurationSettingWithResponse(expected, Context.NONE).getValue()));
createSnapshotRunner((name, filters) -> {
+ // Retention period can be setup when creating a snapshot and cannot edit.
+ Duration retentionPeriod = Duration.ofMinutes(60);
+
ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
- .setRetentionPeriod(MINIMUM_RETENTION_PERIOD);
+ .setRetentionPeriod(retentionPeriod);
SyncPoller poller =
client.beginCreateSnapshot(name, snapshot, Context.NONE);
poller.setPollInterval(Duration.ofSeconds(10));
@@ -1017,7 +1018,7 @@ public void createSnapshot(HttpClient httpClient, ConfigurationServiceVersion se
assertEqualsConfigurationSettingSnapshot(name,
SnapshotStatus.READY, filters, CompositionType.KEY,
- MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
+ retentionPeriod, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
// Archived the snapshot, it will be deleted automatically when retention period expires.
assertEquals(SnapshotStatus.ARCHIVED, client.archiveSnapshot(name).getStatus());
@@ -1033,8 +1034,11 @@ public void getSnapshot(HttpClient httpClient, ConfigurationServiceVersion servi
client.addConfigurationSettingWithResponse(expected, Context.NONE).getValue()));
createSnapshotRunner((name, filters) -> {
+ // Retention period can be setup when creating a snapshot and cannot edit.
+ Duration retentionPeriod = Duration.ofMinutes(60);
+
ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
- .setRetentionPeriod(MINIMUM_RETENTION_PERIOD);
+ .setRetentionPeriod(retentionPeriod);
SyncPoller poller =
client.beginCreateSnapshot(name, snapshot, Context.NONE);
poller.setPollInterval(Duration.ofSeconds(10));
@@ -1042,13 +1046,13 @@ public void getSnapshot(HttpClient httpClient, ConfigurationServiceVersion servi
ConfigurationSettingSnapshot snapshotResult = poller.getFinalResult();
assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
- MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
+ retentionPeriod, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
// Retrieve a snapshot after creation
Response getSnapshot = client.getSnapshotWithResponse(name, Context.NONE);
assertConfigurationSettingSnapshotWithResponse(200, name,
SnapshotStatus.READY, filters, CompositionType.KEY,
- MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, getSnapshot);
+ retentionPeriod, Long.valueOf(1000), Long.valueOf(0), null, getSnapshot);
// Archived the snapshot, it will be deleted automatically when retention period expires.
ConfigurationSettingSnapshot archivedSnapshot = client.archiveSnapshot(name);
@@ -1065,20 +1069,21 @@ public void getSnapshotConvenience(HttpClient httpClient, ConfigurationServiceVe
client.addConfigurationSettingWithResponse(expected, Context.NONE).getValue()));
createSnapshotRunner((name, filters) -> {
- ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
- .setRetentionPeriod(MINIMUM_RETENTION_PERIOD);
+ // Retention period can be setup when creating a snapshot and cannot edit.
+ Duration retentionPeriod = Duration.ofMinutes(60);
+
SyncPoller poller =
- client.beginCreateSnapshot(name, snapshot, Context.NONE);
+ client.beginCreateSnapshot(name, new ConfigurationSettingSnapshot(filters), Context.NONE);
poller.setPollInterval(Duration.ofSeconds(10));
poller.waitForCompletion();
ConfigurationSettingSnapshot snapshotResult = poller.getFinalResult();
assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
- MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
+ retentionPeriod, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
// Retrieve a snapshot after creation
assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
- MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null,
+ retentionPeriod, Long.valueOf(1000), Long.valueOf(0), null,
client.getSnapshot(name));
// Archived the snapshot, it will be deleted automatically when retention period expires.
@@ -1087,36 +1092,6 @@ public void getSnapshotConvenience(HttpClient httpClient, ConfigurationServiceVe
});
}
- @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
- @MethodSource("com.azure.data.appconfiguration.TestHelper#getTestParameters")
- public void archiveSnapshot(HttpClient httpClient, ConfigurationServiceVersion serviceVersion) {
- client = getConfigurationClient(httpClient, serviceVersion);
- // Prepare a setting before creating a snapshot
- addConfigurationSettingRunner((expected) -> assertConfigurationEquals(expected,
- client.addConfigurationSettingWithResponse(expected, Context.NONE).getValue()));
-
- createSnapshotRunner((name, filters) -> {
- // Retention period can be setup when creating a snapshot and cannot edit.
- ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
- .setRetentionPeriod(MINIMUM_RETENTION_PERIOD);
- SyncPoller poller =
- client.beginCreateSnapshot(name, snapshot, Context.NONE);
- poller.setPollInterval(Duration.ofSeconds(10));
- poller.waitForCompletion();
- ConfigurationSettingSnapshot snapshotResult = poller.getFinalResult();
-
- assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
- MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
-
- // Archived the snapshot, it will be deleted automatically when retention period expires.
- Response response = client.archiveSnapshotWithResponse(snapshotResult,
- false, Context.NONE);
- assertConfigurationSettingSnapshotWithResponse(200, name,
- SnapshotStatus.ARCHIVED, filters, CompositionType.KEY,
- MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, response);
- });
- }
-
@ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
@MethodSource("com.azure.data.appconfiguration.TestHelper#getTestParameters")
public void archiveSnapshotConvenience(HttpClient httpClient, ConfigurationServiceVersion serviceVersion) {
@@ -1223,9 +1198,6 @@ public void listSnapshots(HttpClient httpClient, ConfigurationServiceVersion ser
client = getConfigurationClient(httpClient, serviceVersion);
List allExistingSnapshots = new ArrayList<>();
- client.listSnapshots(new SnapshotSelector().setSnapshotStatus(SnapshotStatus.READY))
- .stream()
- .map(snapshot -> allExistingSnapshots.add(snapshot));
// Clean all ready snapshots
for (ConfigurationSettingSnapshot existSnapshot : allExistingSnapshots) {
@@ -1275,7 +1247,6 @@ public void listSnapshots(HttpClient httpClient, ConfigurationServiceVersion ser
for (ConfigurationSettingSnapshot snapshot : actualSnapshots) {
// List only the snapshot with a specific name
- client.listSnapshots(new SnapshotSelector().setName(snapshot.getName()));
// Archived the snapshot, it will be deleted automatically when retention period expires.
assertEquals(SnapshotStatus.ARCHIVED, client.archiveSnapshot(snapshot.getName()).getStatus());
@@ -1336,4 +1307,5 @@ private void filterValueTest(String keyFilter, String labelFilter) {
}
});
}
+
}
diff --git a/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTestBase.java b/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTestBase.java
index 99cc31b1418b9..ff0fec87beab8 100644
--- a/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTestBase.java
+++ b/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTestBase.java
@@ -9,6 +9,7 @@
import com.azure.core.test.TestProxyTestBase;
import com.azure.core.util.Configuration;
import com.azure.core.util.CoreUtils;
+import com.azure.core.util.logging.ClientLogger;
import com.azure.data.appconfiguration.implementation.ConfigurationClientCredentials;
import com.azure.data.appconfiguration.implementation.ConfigurationSettingHelper;
import com.azure.data.appconfiguration.models.CompositionType;
@@ -55,10 +56,12 @@ public abstract class ConfigurationClientTestBase extends TestProxyTestBase {
public static final String FAKE_CONNECTION_STRING =
"Endpoint=https://localhost:8080;Id=0000000000000;Secret=fakeSecrePlaceholder";
+ static final Duration DEFAULT_RETENTION_PERIOD = Duration.ofSeconds(2592000);
static final Duration MINIMUM_RETENTION_PERIOD = Duration.ofHours(1);
static String connectionString;
+ private final ClientLogger logger = new ClientLogger(ConfigurationClientTestBase.class);
String keyPrefix;
String labelPrefix;
@@ -555,30 +558,6 @@ void createSnapshotRunner(BiConsumer> testRu
testRunner.accept(snapshotName, filters);
}
- @Test
- public abstract void getSnapshot(HttpClient httpClient, ConfigurationServiceVersion serviceVersion);
-
- @Test
- public abstract void getSnapshotConvenience(HttpClient httpClient, ConfigurationServiceVersion serviceVersion);
-
- @Test
- public abstract void archiveSnapshot(HttpClient httpClient, ConfigurationServiceVersion serviceVersion);
-
- @Test
- public abstract void archiveSnapshotConvenience(HttpClient httpClient, ConfigurationServiceVersion serviceVersion);
-
- @Test
- public abstract void recoverSnapshot(HttpClient httpClient, ConfigurationServiceVersion serviceVersion);
-
- @Test
- public abstract void recoverSnapshotConvenience(HttpClient httpClient, ConfigurationServiceVersion serviceVersion);
-
- @Test
- public abstract void listSnapshots(HttpClient httpClient, ConfigurationServiceVersion serviceVersion);
-
- @Test
- public abstract void listSettingFromSnapshot(HttpClient httpClient, ConfigurationServiceVersion serviceVersion);
-
/**
* Helper method to verify that the RestResponse matches what was expected. This method assumes a response status of 200.
*
From c378f572e73b173a308795174f90e377595ced64 Mon Sep 17 00:00:00 2001
From: Matt Metcalf
Date: Thu, 14 Sep 2023 13:54:36 -0700
Subject: [PATCH 5/7] more reverts
---
.../ConfigurationAsyncClientTest.java | 2 +-
.../ConfigurationClientTest.java | 144 +-----------------
2 files changed, 8 insertions(+), 138 deletions(-)
diff --git a/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationAsyncClientTest.java b/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationAsyncClientTest.java
index 74c31cecea2f8..3c78d729e6dd9 100644
--- a/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationAsyncClientTest.java
+++ b/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationAsyncClientTest.java
@@ -1609,7 +1609,7 @@ public void listSnapshots(HttpClient httpClient, ConfigurationServiceVersion ser
.verifyComplete();
});
-
+
for (ConfigurationSettingSnapshot snapshot : actualSnapshots) {
// List only the snapshot with a specific name
StepVerifier.create(client.listSnapshots(
diff --git a/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTest.java b/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTest.java
index e0fae44e0aff5..0e849aba34b4e 100644
--- a/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTest.java
+++ b/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTest.java
@@ -1005,9 +1005,9 @@ public void createSnapshot(HttpClient httpClient, ConfigurationServiceVersion se
client.addConfigurationSettingWithResponse(expected, Context.NONE).getValue()));
createSnapshotRunner((name, filters) -> {
- // Retention period can be setup when creating a snapshot and cannot edit.
+ // Retention period can be setup when creating a snapshot and cannot edit.
Duration retentionPeriod = Duration.ofMinutes(60);
-
+
ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
.setRetentionPeriod(retentionPeriod);
SyncPoller poller =
@@ -1034,9 +1034,9 @@ public void getSnapshot(HttpClient httpClient, ConfigurationServiceVersion servi
client.addConfigurationSettingWithResponse(expected, Context.NONE).getValue()));
createSnapshotRunner((name, filters) -> {
- // Retention period can be setup when creating a snapshot and cannot edit.
+ // Retention period can be setup when creating a snapshot and cannot edit.
Duration retentionPeriod = Duration.ofMinutes(60);
-
+
ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
.setRetentionPeriod(retentionPeriod);
SyncPoller poller =
@@ -1068,10 +1068,7 @@ public void getSnapshotConvenience(HttpClient httpClient, ConfigurationServiceVe
addConfigurationSettingRunner((expected) -> assertConfigurationEquals(expected,
client.addConfigurationSettingWithResponse(expected, Context.NONE).getValue()));
- createSnapshotRunner((name, filters) -> {
- // Retention period can be setup when creating a snapshot and cannot edit.
- Duration retentionPeriod = Duration.ofMinutes(60);
-
+ createSnapshotRunner((name, filters) -> {
SyncPoller poller =
client.beginCreateSnapshot(name, new ConfigurationSettingSnapshot(filters), Context.NONE);
poller.setPollInterval(Duration.ofSeconds(10));
@@ -1079,11 +1076,11 @@ public void getSnapshotConvenience(HttpClient httpClient, ConfigurationServiceVe
ConfigurationSettingSnapshot snapshotResult = poller.getFinalResult();
assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
- retentionPeriod, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
+ DEFAULT_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
// Retrieve a snapshot after creation
assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
- retentionPeriod, Long.valueOf(1000), Long.valueOf(0), null,
+ DEFAULT_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null,
client.getSnapshot(name));
// Archived the snapshot, it will be deleted automatically when retention period expires.
@@ -1092,34 +1089,6 @@ public void getSnapshotConvenience(HttpClient httpClient, ConfigurationServiceVe
});
}
- @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
- @MethodSource("com.azure.data.appconfiguration.TestHelper#getTestParameters")
- public void archiveSnapshotConvenience(HttpClient httpClient, ConfigurationServiceVersion serviceVersion) {
- client = getConfigurationClient(httpClient, serviceVersion);
- // Prepare a setting before creating a snapshot
- addConfigurationSettingRunner((expected) -> assertConfigurationEquals(expected,
- client.addConfigurationSettingWithResponse(expected, Context.NONE).getValue()));
-
- createSnapshotRunner((name, filters) -> {
- // Retention period can be setup when creating a snapshot and cannot edit.
- ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
- .setRetentionPeriod(MINIMUM_RETENTION_PERIOD);
- SyncPoller poller =
- client.beginCreateSnapshot(name, snapshot, Context.NONE);
- poller.setPollInterval(Duration.ofSeconds(10));
- poller.waitForCompletion();
- ConfigurationSettingSnapshot snapshotResult = poller.getFinalResult();
-
- assertEqualsConfigurationSettingSnapshot(name,
- SnapshotStatus.READY, filters, CompositionType.KEY,
- MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
-
- // Archived the snapshot, it will be deleted automatically when retention period expires.
- ConfigurationSettingSnapshot archivedSnapshot = client.archiveSnapshot(name);
- assertEquals(SnapshotStatus.ARCHIVED, archivedSnapshot.getStatus());
- });
- }
-
@ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
@MethodSource("com.azure.data.appconfiguration.TestHelper#getTestParameters")
public void recoverSnapshot(HttpClient httpClient, ConfigurationServiceVersion serviceVersion) {
@@ -1192,105 +1161,6 @@ public void recoverSnapshotConvenience(HttpClient httpClient, ConfigurationServi
});
}
- @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
- @MethodSource("com.azure.data.appconfiguration.TestHelper#getTestParameters")
- public void listSnapshots(HttpClient httpClient, ConfigurationServiceVersion serviceVersion) {
- client = getConfigurationClient(httpClient, serviceVersion);
-
- List allExistingSnapshots = new ArrayList<>();
-
- // Clean all ready snapshots
- for (ConfigurationSettingSnapshot existSnapshot : allExistingSnapshots) {
- client.archiveSnapshot(existSnapshot.getName());
- }
-
- // Prepare a setting before creating a snapshot
- addConfigurationSettingRunner((expected) -> assertConfigurationEquals(expected,
- client.addConfigurationSettingWithResponse(expected, Context.NONE).getValue()));
-
- List actualSnapshots = new ArrayList<>();
-
- // Create first snapshot
- createSnapshotRunner((name, filters) -> {
- ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
- .setRetentionPeriod(MINIMUM_RETENTION_PERIOD);
- SyncPoller poller =
- client.beginCreateSnapshot(name, snapshot, Context.NONE);
- poller.setPollInterval(Duration.ofSeconds(10));
- poller.waitForCompletion();
- ConfigurationSettingSnapshot snapshotResult = poller.getFinalResult();
-
- assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
- MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
-
- // Archived the snapshot, it will be deleted automatically when retention period expires.
- assertEquals(SnapshotStatus.ARCHIVED, client.archiveSnapshot(name).getStatus());
- });
-
- // Create second snapshot
- createSnapshotRunner((name, filters) -> {
- ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
- .setRetentionPeriod(MINIMUM_RETENTION_PERIOD);
- SyncPoller poller =
- client.beginCreateSnapshot(name, snapshot, Context.NONE);
- poller.setPollInterval(Duration.ofSeconds(10));
- poller.waitForCompletion();
- ConfigurationSettingSnapshot snapshotResult = poller.getFinalResult();
-
- assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
- MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
-
- // Archived the snapshot, it will be deleted automatically when retention period expires.
- assertEquals(SnapshotStatus.ARCHIVED, client.archiveSnapshot(name).getStatus());
- });
-
-
- for (ConfigurationSettingSnapshot snapshot : actualSnapshots) {
- // List only the snapshot with a specific name
-
- // Archived the snapshot, it will be deleted automatically when retention period expires.
- assertEquals(SnapshotStatus.ARCHIVED, client.archiveSnapshot(snapshot.getName()).getStatus());
- }
- }
-
- @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
- @MethodSource("com.azure.data.appconfiguration.TestHelper#getTestParameters")
- public void listSettingFromSnapshot(HttpClient httpClient, ConfigurationServiceVersion serviceVersion) {
- client = getConfigurationClient(httpClient, serviceVersion);
-
- // Create a snapshot
- createSnapshotRunner((name, filters) -> {
- // Prepare 5 settings before creating a snapshot
- final int numberExpected = 5;
- List settings = new ArrayList<>(numberExpected);
- for (int value = 0; value < numberExpected; value++) {
- settings.add(new ConfigurationSetting().setKey(name + "-" + value));
- }
- for (ConfigurationSetting setting : settings) {
- client.setConfigurationSetting(setting);
- }
- SettingSelector filter = new SettingSelector().setKeyFilter(name + "-*");
- assertEquals(numberExpected, client.listConfigurationSettings(filter).stream().count());
-
- // Retention period can be setup when creating a snapshot and cannot edit.
- ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
- .setRetentionPeriod(MINIMUM_RETENTION_PERIOD);
- SyncPoller poller =
- client.beginCreateSnapshot(name, snapshot, Context.NONE);
- poller.setPollInterval(Duration.ofSeconds(10));
- poller.waitForCompletion();
- ConfigurationSettingSnapshot snapshotResult = poller.getFinalResult();
-
- assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
- MINIMUM_RETENTION_PERIOD, Long.valueOf(15000), Long.valueOf(numberExpected), null, snapshotResult);
-
- assertEquals(numberExpected, client.listConfigurationSettingsForSnapshot(name).stream().count());
-
- // Archived the snapshot, it will be deleted automatically when retention period expires.
- assertEquals(SnapshotStatus.ARCHIVED, client.archiveSnapshot(name).getStatus());
- });
- }
-
/**
* Test helper that calling list configuration setting with given key and label input
*
From 2e26353359b88924a30939263150357e2d4c9358 Mon Sep 17 00:00:00 2001
From: Matt Metcalf
Date: Thu, 14 Sep 2023 14:01:22 -0700
Subject: [PATCH 6/7] other reverts
---
.../ConfigurationAsyncClientTest.java | 1 +
.../ConfigurationClientTest.java | 26 +++++++++++--------
2 files changed, 16 insertions(+), 11 deletions(-)
diff --git a/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationAsyncClientTest.java b/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationAsyncClientTest.java
index 3c78d729e6dd9..9730cd5bde5f5 100644
--- a/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationAsyncClientTest.java
+++ b/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationAsyncClientTest.java
@@ -1657,6 +1657,7 @@ public void listSettingFromSnapshot(HttpClient httpClient, ConfigurationServiceV
assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
MINIMUM_RETENTION_PERIOD, Long.valueOf(15000), Long.valueOf(50), null, snapshotResult);
+
StepVerifier.create(client.listConfigurationSettingsForSnapshot(name))
.expectNextCount(numberExpected)
.verifyComplete();
diff --git a/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTest.java b/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTest.java
index 0e849aba34b4e..82fc640971542 100644
--- a/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTest.java
+++ b/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTest.java
@@ -1005,7 +1005,7 @@ public void createSnapshot(HttpClient httpClient, ConfigurationServiceVersion se
client.addConfigurationSettingWithResponse(expected, Context.NONE).getValue()));
createSnapshotRunner((name, filters) -> {
- // Retention period can be setup when creating a snapshot and cannot edit.
+ // Retention period can be setup when creating a snapshot and cannot edit.
Duration retentionPeriod = Duration.ofMinutes(60);
ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
@@ -1034,7 +1034,7 @@ public void getSnapshot(HttpClient httpClient, ConfigurationServiceVersion servi
client.addConfigurationSettingWithResponse(expected, Context.NONE).getValue()));
createSnapshotRunner((name, filters) -> {
- // Retention period can be setup when creating a snapshot and cannot edit.
+ // Retention period can be setup when creating a snapshot and cannot edit.
Duration retentionPeriod = Duration.ofMinutes(60);
ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
@@ -1068,7 +1068,7 @@ public void getSnapshotConvenience(HttpClient httpClient, ConfigurationServiceVe
addConfigurationSettingRunner((expected) -> assertConfigurationEquals(expected,
client.addConfigurationSettingWithResponse(expected, Context.NONE).getValue()));
- createSnapshotRunner((name, filters) -> {
+ createSnapshotRunner((name, filters) -> {
SyncPoller poller =
client.beginCreateSnapshot(name, new ConfigurationSettingSnapshot(filters), Context.NONE);
poller.setPollInterval(Duration.ofSeconds(10));
@@ -1098,8 +1098,11 @@ public void recoverSnapshot(HttpClient httpClient, ConfigurationServiceVersion s
client.addConfigurationSettingWithResponse(expected, Context.NONE).getValue()));
createSnapshotRunner((name, filters) -> {
+ // Retention period can be setup when creating a snapshot and cannot edit.
+ Duration retentionPeriod = Duration.ofMinutes(60);
+
ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
- .setRetentionPeriod(MINIMUM_RETENTION_PERIOD);
+ .setRetentionPeriod(retentionPeriod);
SyncPoller poller =
client.beginCreateSnapshot(name, snapshot, Context.NONE);
poller.setPollInterval(Duration.ofSeconds(10));
@@ -1107,12 +1110,12 @@ public void recoverSnapshot(HttpClient httpClient, ConfigurationServiceVersion s
ConfigurationSettingSnapshot snapshotResult = poller.getFinalResult();
assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
- MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
+ retentionPeriod, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
// Archived the snapshot
assertEqualsConfigurationSettingSnapshot(name,
SnapshotStatus.ARCHIVED, filters, CompositionType.KEY,
- MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null,
+ retentionPeriod, Long.valueOf(1000), Long.valueOf(0), null,
client.archiveSnapshot(name));
// Recover the snapshot, it will be deleted automatically when retention period expires.
@@ -1120,7 +1123,7 @@ public void recoverSnapshot(HttpClient httpClient, ConfigurationServiceVersion s
client.recoverSnapshotWithResponse(snapshotResult, false, Context.NONE);
assertConfigurationSettingSnapshotWithResponse(200, name,
SnapshotStatus.READY, filters, CompositionType.KEY,
- MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null,
+ retentionPeriod, Long.valueOf(1000), Long.valueOf(0), null,
configurationSettingSnapshotResponse);
// Archived the snapshot, it will be deleted automatically when retention period expires.
@@ -1137,8 +1140,10 @@ public void recoverSnapshotConvenience(HttpClient httpClient, ConfigurationServi
client.addConfigurationSettingWithResponse(expected, Context.NONE).getValue()));
createSnapshotRunner((name, filters) -> {
+ // Retention period can be setup when creating a snapshot and cannot edit.
+ Duration retentionPeriod = Duration.ofMinutes(60);
ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
- .setRetentionPeriod(MINIMUM_RETENTION_PERIOD);
+ .setRetentionPeriod(retentionPeriod);
SyncPoller poller =
client.beginCreateSnapshot(name, snapshot, Context.NONE);
poller.setPollInterval(Duration.ofSeconds(10));
@@ -1146,14 +1151,14 @@ public void recoverSnapshotConvenience(HttpClient httpClient, ConfigurationServi
ConfigurationSettingSnapshot snapshotResult = poller.getFinalResult();
assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
- MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
+ retentionPeriod, Long.valueOf(1000), Long.valueOf(0), null, snapshotResult);
// Archived the snapshot
assertEquals(SnapshotStatus.ARCHIVED, client.archiveSnapshot(name).getStatus());
// Recover the snapshot, it will be deleted automatically when retention period expires.
assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
- MINIMUM_RETENTION_PERIOD, Long.valueOf(1000), Long.valueOf(0), null,
+ retentionPeriod, Long.valueOf(1000), Long.valueOf(0), null,
client.recoverSnapshot(name));
// Archived the snapshot, it will be deleted automatically when retention period expires.
@@ -1177,5 +1182,4 @@ private void filterValueTest(String keyFilter, String labelFilter) {
}
});
}
-
}
From 86b549884da517bbdf8f3f6dd10d812617fdab06 Mon Sep 17 00:00:00 2001
From: Matt Metcalf
Date: Thu, 14 Sep 2023 15:13:16 -0700
Subject: [PATCH 7/7] Update ConfigurationClientTest.java
---
.../data/appconfiguration/ConfigurationClientTest.java | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTest.java b/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTest.java
index 82fc640971542..5b85f7256ba18 100644
--- a/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTest.java
+++ b/sdk/appconfiguration/azure-data-appconfiguration/src/test/java/com/azure/data/appconfiguration/ConfigurationClientTest.java
@@ -1140,8 +1140,9 @@ public void recoverSnapshotConvenience(HttpClient httpClient, ConfigurationServi
client.addConfigurationSettingWithResponse(expected, Context.NONE).getValue()));
createSnapshotRunner((name, filters) -> {
- // Retention period can be setup when creating a snapshot and cannot edit.
+ // Retention period can be setup when creating a snapshot and cannot edit.
Duration retentionPeriod = Duration.ofMinutes(60);
+
ConfigurationSettingSnapshot snapshot = new ConfigurationSettingSnapshot(filters)
.setRetentionPeriod(retentionPeriod);
SyncPoller poller =
@@ -1158,8 +1159,7 @@ public void recoverSnapshotConvenience(HttpClient httpClient, ConfigurationServi
// Recover the snapshot, it will be deleted automatically when retention period expires.
assertEqualsConfigurationSettingSnapshot(name, SnapshotStatus.READY, filters, CompositionType.KEY,
- retentionPeriod, Long.valueOf(1000), Long.valueOf(0), null,
- client.recoverSnapshot(name));
+ retentionPeriod, Long.valueOf(1000), Long.valueOf(0), null, client.recoverSnapshot(name));
// Archived the snapshot, it will be deleted automatically when retention period expires.
assertEquals(SnapshotStatus.ARCHIVED, client.archiveSnapshot(name).getStatus());