Skip to content

Commit f6ffe2c

Browse files
authored
Merge pull request #457 from computerlove/more-than-five-labels
Support more than five labels for app configuration.
2 parents bbf4c91 + b4e3f9c commit f6ffe2c

File tree

8 files changed

+186
-9
lines changed

8 files changed

+186
-9
lines changed

.github/create-azure-resources.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,15 @@ az appconfig kv set \
4848
--label prod \
4949
--yes
5050

51+
for i in {1..7}; do
52+
az appconfig kv set \
53+
--name "${APP_CONFIG_NAME}" \
54+
--key "another.prop.l${i}" \
55+
--value "Label ${i}" \
56+
--label "l${i}" \
57+
--yes
58+
done
59+
5160
# Azure Key Vault Extension
5261
# The same commands used in
5362
# - integration-tests/README.md

integration-tests/azure-app-configuration/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,15 @@ az appconfig kv set \
8787
--label prod \
8888
--yes
8989
90+
for i in {1..7}; do
91+
az appconfig kv set \
92+
--name "${APP_CONFIG_NAME}" \
93+
--key "another.prop.l${i}" \
94+
--value "Label ${i}" \
95+
--label "l${i}" \
96+
--yes
97+
done
98+
9099
export QUARKUS_AZURE_APP_CONFIGURATION_ENDPOINT=$(az appconfig show \
91100
--resource-group "${RESOURCE_GROUP_NAME}" \
92101
--name "${APP_CONFIG_NAME}" \

integration-tests/azure-app-configuration/src/test/java/io/quarkiverse/azure/app/configuration/it/AzureAppConfigurationResource.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,13 @@ public void stop() {
6666
private static URL getResource(HttpExchange exchange) {
6767
Map<String, String> params = getQueryParameters(exchange.getRequestURI().getQuery());
6868
URL resource;
69-
69+
String labels = params.get("label");
7070
if (Objects.equals("prod", params.get("label"))) {
7171
resource = loadResource("response_prod.json");
72+
} else if (Objects.equals("l1,l2,l3,l4,l5", labels)) {
73+
resource = loadResource("response_labels_1.json");
74+
} else if (Objects.equals("l6,l7", labels)) {
75+
resource = loadResource("response_labels_2.json");
7276
} else {
7377
resource = loadResource("response.json");
7478
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package io.quarkiverse.azure.app.configuration.it;
2+
3+
import static io.restassured.RestAssured.given;
4+
import static jakarta.ws.rs.core.Response.Status.NO_CONTENT;
5+
import static jakarta.ws.rs.core.Response.Status.OK;
6+
import static org.hamcrest.Matchers.equalTo;
7+
8+
import org.junit.jupiter.api.Test;
9+
import org.junit.jupiter.params.ParameterizedTest;
10+
import org.junit.jupiter.params.provider.ValueSource;
11+
12+
import io.quarkus.test.common.WithTestResource;
13+
import io.quarkus.test.junit.QuarkusTest;
14+
import io.quarkus.test.junit.TestProfile;
15+
16+
@QuarkusTest
17+
@WithTestResource(AzureAppConfigurationResource.class)
18+
@TestProfile(SevenLabelsConfigurationProfile.class)
19+
class AzureAppConfigurationWithSevenLabelsTest {
20+
21+
@ParameterizedTest
22+
@ValueSource(ints = { 1, 2, 3, 4, 5, 6, 7 })
23+
void testAppConfigurationSupportsMoreThanFiveLabels(int labelNumber) {
24+
given()
25+
.get("/config/{name}", "another.prop.l" + labelNumber)
26+
.then()
27+
.statusCode(OK.getStatusCode())
28+
.body(equalTo("Label " + labelNumber));
29+
}
30+
31+
@Test
32+
void configWithoutLabelIsNotProvided() {
33+
given()
34+
.get("/config/{name}", "my.prop")
35+
.then()
36+
.statusCode(NO_CONTENT.getStatusCode());
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package io.quarkiverse.azure.app.configuration.it;
2+
3+
import java.util.Map;
4+
5+
import io.quarkus.test.junit.QuarkusTestProfile;
6+
7+
public class SevenLabelsConfigurationProfile implements QuarkusTestProfile {
8+
public Map<String, String> getConfigOverrides() {
9+
return Map.of("quarkus.azure.app.configuration.labels", "l1,l2,l3,l4,l5,l6,l7");
10+
}
11+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
{
2+
"items": [
3+
{
4+
"etag": "l1hQuZysAyuOXArQpGaZAYxV_7nNctKmKYANd_IUoIw",
5+
"key": "another.prop.l1",
6+
"label": "l1",
7+
"content_type": "",
8+
"value": "Label 1",
9+
"tags": {},
10+
"locked": false,
11+
"last_modified": "2022-11-29T17:07:33+00:00"
12+
},
13+
{
14+
"etag": "l1hQuZysAyuOXArQpGaZAYxV_7nNctKmKYANd_IUoIw",
15+
"key": "another.prop.l2",
16+
"label": "l2",
17+
"content_type": "",
18+
"value": "Label 2",
19+
"tags": {},
20+
"locked": false,
21+
"last_modified": "2022-11-29T17:07:33+00:00"
22+
},
23+
{
24+
"etag": "l1hQuZysAyuOXArQpGaZAYxV_7nNctKmKYANd_IUoIw",
25+
"key": "another.prop.l3",
26+
"label": "l3",
27+
"content_type": "",
28+
"value": "Label 3",
29+
"tags": {},
30+
"locked": false,
31+
"last_modified": "2022-11-29T17:07:33+00:00"
32+
},
33+
{
34+
"etag": "l1hQuZysAyuOXArQpGaZAYxV_7nNctKmKYANd_IUoIw",
35+
"key": "another.prop.l4",
36+
"label": "l4",
37+
"content_type": "",
38+
"value": "Label 4",
39+
"tags": {},
40+
"locked": false,
41+
"last_modified": "2022-11-29T17:07:33+00:00"
42+
},
43+
{
44+
"etag": "l1hQuZysAyuOXArQpGaZAYxV_7nNctKmKYANd_IUoIw",
45+
"key": "another.prop.l5",
46+
"label": "l5",
47+
"content_type": "",
48+
"value": "Label 5",
49+
"tags": {},
50+
"locked": false,
51+
"last_modified": "2022-11-29T17:07:33+00:00"
52+
}
53+
]
54+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"items": [
3+
{
4+
"etag": "l1hQuZysAyuOXArQpGaZAYxV_7nNctKmKYANd_IUoIw",
5+
"key": "another.prop.l6",
6+
"label": "l6",
7+
"content_type": "",
8+
"value": "Label 6",
9+
"tags": {},
10+
"locked": false,
11+
"last_modified": "2022-11-29T17:07:33+00:00"
12+
},
13+
{
14+
"etag": "l1hQuZysAyuOXArQpGaZAYxV_7nNctKmKYANd_IUoIw",
15+
"key": "another.prop.l7",
16+
"label": "l7",
17+
"content_type": "",
18+
"value": "Label 7",
19+
"tags": {},
20+
"locked": false,
21+
"last_modified": "2022-11-29T17:07:33+00:00"
22+
}
23+
]
24+
}

services/azure-app-configuration/runtime/src/main/java/io/quarkiverse/azure/app/configuration/AzureAppConfigurationConfigSourceFactory.java

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package io.quarkiverse.azure.app.configuration;
22

3+
import java.util.ArrayList;
4+
import java.util.Arrays;
35
import java.util.Collections;
46
import java.util.LinkedHashMap;
7+
import java.util.List;
58
import java.util.Map;
69
import java.util.function.Consumer;
710

@@ -26,11 +29,23 @@
2629
public class AzureAppConfigurationConfigSourceFactory
2730
implements ConfigurableConfigSourceFactory<AzureAppConfigurationConfig> {
2831

29-
private static SettingSelector getSettingSelector(final AzureAppConfigurationConfig config) {
30-
var settingSelector = new SettingSelector();
31-
config.labels().ifPresent(settingSelector::setLabelFilter);
32+
/*
33+
* The maximum number of labels that can be specified in a single request.
34+
*/
35+
private static final int MAX_LABELS_PER_REQUEST = 5;
3236

33-
return settingSelector;
37+
private static List<SettingSelector> getSettingSelector(final AzureAppConfigurationConfig config) {
38+
if (config.labels().isEmpty()) {
39+
return List.of(new SettingSelector());
40+
} else {
41+
List<String> allLabels = Arrays.asList(config.labels().get().split(","));
42+
List<List<String>> labelsPartitions = partition(allLabels, MAX_LABELS_PER_REQUEST);
43+
List<SettingSelector> settingSelectors = new ArrayList<>(labelsPartitions.size());
44+
for (List<String> settingSelector : labelsPartitions) {
45+
settingSelectors.add(new SettingSelector().setLabelFilter(String.join(",", settingSelector)));
46+
}
47+
return settingSelectors;
48+
}
3449
}
3550

3651
@Override
@@ -66,14 +81,19 @@ private Map<String, String> getAzureAppConfiguration(final AzureAppConfiguration
6681
ConfigurationClient client = clientBuilder.buildClient();
6782

6883
Map<String, String> properties = new LinkedHashMap<>(); // LinkedHashMap for reproducible ordering
69-
PagedIterable<ConfigurationSetting> listConfigurationSettings = client
70-
.listConfigurationSettings(getSettingSelector(config));
71-
listConfigurationSettings.forEach(new Consumer<ConfigurationSetting>() {
84+
85+
Consumer<ConfigurationSetting> consumer = new Consumer<>() {
7286
@Override
7387
public void accept(final ConfigurationSetting configurationSetting) {
7488
properties.put(configurationSetting.getKey(), configurationSetting.getValue());
7589
}
76-
});
90+
};
91+
List<SettingSelector> settingSelectors = getSettingSelector(config);
92+
for (SettingSelector settingSelector : settingSelectors) {
93+
PagedIterable<ConfigurationSetting> listConfigurationSettings = client
94+
.listConfigurationSettings(settingSelector);
95+
listConfigurationSettings.forEach(consumer);
96+
}
7797

7898
try {
7999
vertx.close().toCompletionStage().toCompletableFuture().get();
@@ -83,4 +103,12 @@ public void accept(final ConfigurationSetting configurationSetting) {
83103

84104
return properties;
85105
}
106+
107+
private static List<List<String>> partition(List<String> list, int chunkSize) {
108+
List<List<String>> chunks = new ArrayList<>();
109+
for (int i = 0; i < list.size(); i += chunkSize) {
110+
chunks.add(list.subList(i, Math.min(list.size(), i + chunkSize)));
111+
}
112+
return chunks;
113+
}
86114
}

0 commit comments

Comments
 (0)