Skip to content

Commit 223797f

Browse files
authored
174 ojdbc extension azure app configuration provider even if label is removed from url next run use the label (#177)
* fix label issue in azure app configuration provider, add test and update README * revise comment in test * use enum.name() for properties key comparison instead of enum object in AzureAppConfigurationProviderURLParserTest * ensure restore with try-finally in AzureAppConfigurationProviderTest#testCachePurged
1 parent 5651e71 commit 223797f

File tree

4 files changed

+126
-20
lines changed

4 files changed

+126
-20
lines changed

ojdbc-provider-azure/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,14 @@ For example, let's suppose a URL like:
7878
jdbc:oracle:thin:@config-azure://myappconfig?key=/sales_app1/&label=dev
7979
</pre>
8080

81-
And the configuration in App Configuration '**myappconfig**' as follows (note that some values such as password can be a reference to a Key Vault secret):
81+
And the configuration in App Configuration '**myappconfig**' as follows (note that some values such as password can be a reference to a Key Vault secret rather than a raw Key Vault URI):
8282

8383
| Key | Value | Label |
8484
|-------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------| ----- |
8585
| /sales_app1/user | scott | dev |
8686
| /sales_app1/connect_descriptor | (description=(address=(protocol=tcps)(port=1521)(host=adb.us-phoenix-1.oraclecloud.com))(connect_data=(service_name=gebqqvpozhjbqbs_dbtest_medium.adb.oraclecloud.com))) | dev |
87-
| /sales_app1/password | {"uri":"myvault.vault.azure.net/secrets/mysecret"} | dev |
88-
| /sales_app1/wallet_location | {"uri":"myvault.vault.azure.net/secrets/mywallet"} | dev |
87+
| /sales_app1/password | {"uri":"https://myvault.vault.azure.net/secrets/mysecret"} | dev |
88+
| /sales_app1/wallet_location | {"uri":"https://myvault.vault.azure.net/secrets/mywallet"} | dev |
8989
| /sales_app1/jdbc/autoCommit | false | dev |
9090
| /sales_app1/jdbc/oracle.jdbc.fanEnabled | true | dev |
9191
| /sales_app1/jdbc/oracle.jdbc.loginTimeout | 20 | dev |

ojdbc-provider-azure/src/main/java/oracle/jdbc/provider/azure/configuration/AzureAppConfigurationProvider.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,25 @@ private Properties getRemoteProperties(String location) {
182182
selector.setKeyFilter(prefix + "*");
183183
}
184184

185+
// Only allow a single label.
186+
// If not specified, use "%00" to match empty label.
185187
if (parameters.contains(AzureAppConfigurationURLParser.LABEL)) {
186-
selector.setLabelFilter(
187-
parameters.getOptional(AzureAppConfigurationURLParser.LABEL));
188+
String label =
189+
parameters.getOptional(AzureAppConfigurationURLParser.LABEL);
190+
191+
if ("all".equalsIgnoreCase(label) || "*".equals(label)) {
192+
throw new IllegalArgumentException(
193+
"Label 'all' or '*' is not allowed");
194+
}
195+
196+
if (label.contains(",") || label.contains("*")) {
197+
throw new IllegalArgumentException(
198+
"Multiple labels and wildcards are not supported");
199+
}
200+
201+
selector.setLabelFilter(label);
202+
} else {
203+
selector.setLabelFilter("%00");
188204
}
189205

190206
ConfigurationClient configurationClient = new ConfigurationClientBuilder()

ojdbc-provider-azure/src/test/java/oracle/jdbc/provider/azure/configuration/AzureAppConfigurationProviderTest.java

Lines changed: 103 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import oracle.jdbc.provider.azure.AzureTestProperty;
1010
import oracle.jdbc.provider.azure.authentication.AzureAuthenticationMethod;
1111
import org.junit.jupiter.api.Assertions;
12+
import org.junit.jupiter.api.Nested;
1213
import org.junit.jupiter.api.Test;
1314

1415
import java.sql.Connection;
@@ -20,13 +21,81 @@
2021

2122
class AzureAppConfigurationProviderTest {
2223

24+
/**
25+
* Label-related tests
26+
*/
27+
@Nested
28+
class LabelTests {
29+
@Test
30+
public void testNoLabel() throws SQLException {
31+
String url = buildUrlWithLabel(null);
32+
try (Connection conn = tryConnection(url)) {
33+
} catch (IllegalArgumentException e) {
34+
// no connect descriptor is set for no label
35+
Assertions.assertTrue(e.getMessage().contains(
36+
"Missing mandatory attributes: connect_descriptor"));
37+
}
38+
}
39+
40+
@Test
41+
public void testEmptyLabel() throws SQLException {
42+
String url = buildUrlWithLabel("");
43+
try (Connection conn = tryConnection(url)) {
44+
} catch (IllegalArgumentException e) {
45+
// no connect descriptor is set for empty label
46+
Assertions.assertTrue(e.getMessage().contains(
47+
"Missing mandatory attributes: connect_descriptor"));
48+
}
49+
}
50+
51+
@Test
52+
public void testLabelEqualsAll() throws SQLException {
53+
String url = buildUrlWithLabel("all");
54+
try (Connection conn = tryConnection(url)) {
55+
} catch (IllegalArgumentException e) {
56+
Assertions.assertTrue(e.getMessage().contains(
57+
"Label 'all' or '*' is not allowed"));
58+
}
59+
}
60+
61+
@Test
62+
public void testLabelEqualsStar() throws SQLException {
63+
String url = buildUrlWithLabel("*");
64+
try (Connection conn = tryConnection(url)) {
65+
} catch (IllegalArgumentException e) {
66+
Assertions.assertTrue(e.getMessage().contains(
67+
"Label 'all' or '*' is not allowed"));
68+
}
69+
}
70+
71+
@Test
72+
public void testMultipleLabels() throws SQLException {
73+
String url = buildUrlWithLabel("dev,prod");
74+
try (Connection conn = tryConnection(url)) {
75+
} catch (IllegalArgumentException e) {
76+
Assertions.assertTrue(e.getMessage().contains(
77+
"Multiple labels and wildcards are not supported"));
78+
}
79+
}
80+
81+
@Test
82+
public void testWildcardLabel() throws SQLException {
83+
String url = buildUrlWithLabel("dev*");
84+
try (Connection conn = tryConnection(url)) {
85+
} catch (IllegalArgumentException e) {
86+
Assertions.assertTrue(e.getMessage().contains(
87+
"Multiple labels and wildcards are not supported"));
88+
}
89+
}
90+
}
91+
2392
/**
2493
* Verify that the cache is purged after hitting 1017 error.
2594
* Specifically, get connection to the same url twice, but modify the 'user'
2695
* every time.
2796
* The provided app configuration should have correct username, password and
2897
* correct connect descriptor to connect to Database.
29-
**/
98+
*/
3099
@Test
31100
public void testCachePurged() throws SQLException {
32101
ConfigurationClient client = getSecretCredentialClient();
@@ -36,6 +105,7 @@ public void testCachePurged() throws SQLException {
36105
TestProperties.getOrAbort(AzureTestProperty.AZURE_APP_CONFIG_KEY);
37106
String APP_CONFIG_LABEL =
38107
TestProperties.getOrAbort(AzureTestProperty.AZURE_APP_CONFIG_LABEL);
108+
39109
String username = "user";
40110
String originalUrl =
41111
"jdbc:oracle:thin:@config-azure://" + APP_CONFIG_NAME +
@@ -52,16 +122,18 @@ public void testCachePurged() throws SQLException {
52122
client.setConfigurationSetting( APP_CONFIG_KEY + username,
53123
APP_CONFIG_LABEL, originalKeyValue + "wrong");
54124

55-
// Connection fails: hit 1017
56-
SQLException exception = assertThrows(SQLException.class,
57-
() -> tryConnection(url), "Should throw an SQLException");
58-
Assertions.assertEquals(exception.getErrorCode(), 1017);
59-
60-
// Set value of 'user' correct
61-
ConfigurationSetting result =
62-
client.setConfigurationSetting(APP_CONFIG_KEY + username,
63-
APP_CONFIG_LABEL, originalKeyValue);
64-
Assertions.assertEquals(originalKeyValue, result.getValue());
125+
try {
126+
// Connection fails: hit 1017
127+
SQLException exception = assertThrows(SQLException.class,
128+
() -> tryConnection(url), "Should throw an SQLException");
129+
Assertions.assertEquals(exception.getErrorCode(), 1017);
130+
} finally {
131+
// Set value of 'user' correct
132+
ConfigurationSetting result =
133+
client.setConfigurationSetting(APP_CONFIG_KEY + username,
134+
APP_CONFIG_LABEL, originalKeyValue);
135+
Assertions.assertEquals(originalKeyValue, result.getValue());
136+
}
65137

66138
// Connection succeeds
67139
try (Connection conn = tryConnection(url)) {
@@ -76,7 +148,7 @@ public void testCachePurged() throws SQLException {
76148

77149
/**
78150
* Helper function: try to get connection form specified url
79-
**/
151+
*/
80152
private Connection tryConnection(String url) throws SQLException {
81153
OracleDataSource ds = new OracleDataSource();
82154
ds.setURL(url);
@@ -86,7 +158,7 @@ private Connection tryConnection(String url) throws SQLException {
86158

87159
/**
88160
* Similar to the method in AzureAppConfigurationProviderURLParserTest
89-
**/
161+
*/
90162
private static ConfigurationClient getSecretCredentialClient() {
91163
return new ConfigurationClientBuilder()
92164
.credential( new ClientSecretCredentialBuilder()
@@ -103,7 +175,7 @@ private static ConfigurationClient getSecretCredentialClient() {
103175
/**
104176
* Use {@link AzureAuthenticationMethod#SERVICE_PRINCIPLE} as its
105177
* authentication method.
106-
**/
178+
*/
107179
private String composeUrlWithServicePrincipleAuthentication(String originalUrl){
108180
String[] options = new String[] {
109181
"AUTHENTICATION=AZURE_SERVICE_PRINCIPAL",
@@ -115,4 +187,21 @@ private String composeUrlWithServicePrincipleAuthentication(String originalUrl){
115187
AzureTestProperty.AZURE_TENANT_ID)};
116188
return String.format("%s&%s", originalUrl, String.join("&", options));
117189
}
190+
191+
/**
192+
* Helper function: to construct a URL with label parameter.
193+
*/
194+
private String buildUrlWithLabel(String label) {
195+
String APP_CONFIG_NAME=
196+
TestProperties.getOrAbort(AzureTestProperty.AZURE_APP_CONFIG_NAME);
197+
String APP_CONFIG_KEY =
198+
TestProperties.getOrAbort(AzureTestProperty.AZURE_APP_CONFIG_KEY);
199+
String baseUrl =
200+
"jdbc:oracle:thin:@config-azure://" + APP_CONFIG_NAME +
201+
"?key=" + APP_CONFIG_KEY;
202+
if (label != null) {
203+
baseUrl += "&label=" + label;
204+
}
205+
return composeUrlWithServicePrincipleAuthentication(baseUrl);
206+
}
118207
}

ojdbc-provider-azure/src/test/java/oracle/jdbc/provider/azure/configuration/AzureAppConfigurationProviderURLParserTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,8 @@ private static String composeURL(List<String> options) {
233233
String optionsString = String.join("&", options);
234234

235235
Properties properties = getProperties();
236-
if (properties.containsKey(AzureTestProperty.AZURE_APP_CONFIG_LABEL)) {
236+
if (properties.containsKey(
237+
AzureTestProperty.AZURE_APP_CONFIG_LABEL.name())) {
237238
optionsString = String.format("label=%s&%s",
238239
properties.getProperty(AzureTestProperty.AZURE_APP_CONFIG_LABEL.name()),
239240
optionsString);

0 commit comments

Comments
 (0)