Skip to content

Commit 3e8c113

Browse files
kelRyan Ernst
authored andcommitted
Add azure storage endpoint suffix #26432 (#26568)
Allow specifying azure storage endpoint suffix for an azure client.
1 parent 8bfa3b7 commit 3e8c113

File tree

5 files changed

+54
-6
lines changed

5 files changed

+54
-6
lines changed

docs/plugins/repository-azure.asciidoc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,18 @@ The initial backoff period is defined by Azure SDK as `30s`. Which means `30s` o
4444
before retrying after a first timeout or failure. The maximum backoff period is defined by Azure SDK as
4545
`90s`.
4646

47+
`endpoint_suffix` can be used to specify Azure endpoint suffix explicitly. Defaults to `core.windows.net`.
48+
4749
[source,yaml]
4850
----
4951
cloud.azure.storage.timeout: 10s
5052
azure.client.default.max_retries: 7
53+
azure.client.default.endpoint_suffix: core.chinacloudapi.cn
5154
azure.client.secondary.timeout: 30s
5255
----
5356

5457
In this example, timeout will be `10s` per try for `default` with `7` retries before failing
55-
and `30s` per try for `secondary` with `3` retries.
58+
and endpoint suffix will be `core.chinacloudapi.cn` and `30s` per try for `secondary` with `3` retries.
5659

5760
[IMPORTANT]
5861
.Supported Azure Storage Account types

plugins/repository-azure/src/main/java/org/elasticsearch/cloud/azure/storage/AzureStorageServiceImpl.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,14 +106,18 @@ public AzureStorageServiceImpl(Settings settings, Map<String, AzureStorageSettin
106106

107107
void createClient(AzureStorageSettings azureStorageSettings) {
108108
try {
109-
logger.trace("creating new Azure storage client using account [{}], key [{}]",
110-
azureStorageSettings.getAccount(), azureStorageSettings.getKey());
109+
logger.trace("creating new Azure storage client using account [{}], key [{}], endpoint suffix [{}]",
110+
azureStorageSettings.getAccount(), azureStorageSettings.getKey(), azureStorageSettings.getEndpointSuffix());
111111

112112
String storageConnectionString =
113113
"DefaultEndpointsProtocol=https;"
114114
+ "AccountName=" + azureStorageSettings.getAccount() + ";"
115115
+ "AccountKey=" + azureStorageSettings.getKey();
116116

117+
String endpointSuffix = azureStorageSettings.getEndpointSuffix();
118+
if (endpointSuffix != null && !endpointSuffix.isEmpty()) {
119+
storageConnectionString += ";EndpointSuffix=" + endpointSuffix;
120+
}
117121
// Retrieve storage account from connection-string.
118122
CloudStorageAccount storageAccount = CloudStorageAccount.parse(storageConnectionString);
119123

plugins/repository-azure/src/main/java/org/elasticsearch/cloud/azure/storage/AzureStorageSettings.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ public final class AzureStorageSettings {
5858
private static final Setting<Integer> MAX_RETRIES_SETTING =
5959
Setting.affixKeySetting(PREFIX, "max_retries",
6060
(key) -> Setting.intSetting(key, RetryPolicy.DEFAULT_CLIENT_RETRY_COUNT, Setting.Property.NodeScope));
61+
/**
62+
* Azure endpoint suffix. Default to core.windows.net (CloudStorageAccount.DEFAULT_DNS).
63+
*/
64+
public static final Setting<String> ENDPOINT_SUFFIX_SETTING = Setting.affixKeySetting(PREFIX, "endpoint_suffix",
65+
key -> Setting.simpleString(key, Property.NodeScope));
6166

6267
/** Azure key */
6368
public static final AffixSetting<SecureString> KEY_SETTING = Setting.affixKeySetting(PREFIX, "key",
@@ -97,18 +102,20 @@ public final class AzureStorageSettings {
97102
private final String name;
98103
private final String account;
99104
private final String key;
105+
private final String endpointSuffix;
100106
private final TimeValue timeout;
101107
@Deprecated
102108
private final boolean activeByDefault;
103109
private final int maxRetries;
104110
private final Proxy proxy;
105111

106112

107-
public AzureStorageSettings(String account, String key, TimeValue timeout, int maxRetries, Proxy.Type proxyType, String proxyHost,
108-
Integer proxyPort) {
113+
public AzureStorageSettings(String account, String key, String endpointSuffix, TimeValue timeout, int maxRetries,
114+
Proxy.Type proxyType, String proxyHost, Integer proxyPort) {
109115
this.name = null;
110116
this.account = account;
111117
this.key = key;
118+
this.endpointSuffix = endpointSuffix;
112119
this.timeout = timeout;
113120
this.activeByDefault = false;
114121
this.maxRetries = maxRetries;
@@ -138,6 +145,7 @@ public AzureStorageSettings(String name, String account, String key, TimeValue t
138145
this.name = name;
139146
this.account = account;
140147
this.key = key;
148+
this.endpointSuffix = null;
141149
this.timeout = timeout;
142150
this.activeByDefault = activeByDefault;
143151
this.maxRetries = maxRetries;
@@ -157,6 +165,10 @@ public String getAccount() {
157165
return account;
158166
}
159167

168+
public String getEndpointSuffix() {
169+
return endpointSuffix;
170+
}
171+
160172
public TimeValue getTimeout() {
161173
return timeout;
162174
}
@@ -182,6 +194,7 @@ public String toString() {
182194
sb.append(", key='").append(key).append('\'');
183195
sb.append(", activeByDefault='").append(activeByDefault).append('\'');
184196
sb.append(", timeout=").append(timeout);
197+
sb.append(", endpointSuffix='").append(endpointSuffix).append('\'');
185198
sb.append(", maxRetries=").append(maxRetries);
186199
sb.append(", proxy=").append(proxy);
187200
sb.append('}');
@@ -227,6 +240,7 @@ static AzureStorageSettings getClientSettings(Settings settings, String clientNa
227240
try (SecureString account = getConfigValue(settings, clientName, ACCOUNT_SETTING);
228241
SecureString key = getConfigValue(settings, clientName, KEY_SETTING)) {
229242
return new AzureStorageSettings(account.toString(), key.toString(),
243+
getValue(settings, clientName, ENDPOINT_SUFFIX_SETTING),
230244
getValue(settings, clientName, TIMEOUT_SETTING),
231245
getValue(settings, clientName, MAX_RETRIES_SETTING),
232246
getValue(settings, clientName, PROXY_TYPE_SETTING),

plugins/repository-azure/src/main/java/org/elasticsearch/plugin/repository/azure/AzureRepositoryPlugin.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ public List<Setting<?>> getSettings() {
6565
AzureStorageService.Storage.STORAGE_ACCOUNTS,
6666
AzureStorageSettings.ACCOUNT_SETTING,
6767
AzureStorageSettings.KEY_SETTING,
68+
AzureStorageSettings.ENDPOINT_SUFFIX_SETTING,
6869
AzureStorageSettings.TIMEOUT_SETTING,
6970
AzureStorageSettings.PROXY_TYPE_SETTING,
7071
AzureStorageSettings.PROXY_HOST_SETTING,

plugins/repository-azure/src/test/java/org/elasticsearch/cloud/azure/storage/AzureStorageServiceTests.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import com.microsoft.azure.storage.OperationContext;
2424
import com.microsoft.azure.storage.RetryExponentialRetry;
2525
import com.microsoft.azure.storage.blob.CloudBlobClient;
26+
import com.microsoft.azure.storage.core.Base64;
27+
2628
import org.elasticsearch.common.settings.MockSecureSettings;
2729
import org.elasticsearch.common.settings.Setting;
2830
import org.elasticsearch.common.settings.Settings;
@@ -35,6 +37,7 @@
3537
import java.net.URI;
3638
import java.net.URISyntaxException;
3739
import java.net.UnknownHostException;
40+
import java.nio.charset.StandardCharsets;
3841
import java.util.Map;
3942

4043
import static org.elasticsearch.cloud.azure.storage.AzureStorageServiceImpl.blobNameFromUri;
@@ -44,8 +47,10 @@
4447
import static org.elasticsearch.cloud.azure.storage.AzureStorageSettings.DEPRECATED_TIMEOUT_SETTING;
4548
import static org.elasticsearch.repositories.azure.AzureSettingsParserTests.getConcreteSetting;
4649
import static org.hamcrest.Matchers.containsInAnyOrder;
50+
import static org.hamcrest.Matchers.equalTo;
4751
import static org.hamcrest.Matchers.instanceOf;
4852
import static org.hamcrest.Matchers.is;
53+
import static org.hamcrest.Matchers.isEmptyString;
4954
import static org.hamcrest.Matchers.notNullValue;
5055
import static org.hamcrest.Matchers.nullValue;
5156

@@ -88,10 +93,31 @@ public void testReadSecuredSettings() {
8893
secureSettings.setString("azure.client.azure2.key", "mykey2");
8994
secureSettings.setString("azure.client.azure3.account", "myaccount3");
9095
secureSettings.setString("azure.client.azure3.key", "mykey3");
91-
Settings settings = Settings.builder().setSecureSettings(secureSettings).build();
96+
Settings settings = Settings.builder().setSecureSettings(secureSettings)
97+
.put("azure.client.azure3.endpoint_suffix", "my_endpoint_suffix").build();
9298

9399
Map<String, AzureStorageSettings> loadedSettings = AzureStorageSettings.load(settings);
94100
assertThat(loadedSettings.keySet(), containsInAnyOrder("azure1","azure2","azure3","default"));
101+
102+
assertThat(loadedSettings.get("azure1").getEndpointSuffix(), isEmptyString());
103+
assertThat(loadedSettings.get("azure2").getEndpointSuffix(), isEmptyString());
104+
assertThat(loadedSettings.get("azure3").getEndpointSuffix(), equalTo("my_endpoint_suffix"));
105+
}
106+
107+
public void testCreateClientWithEndpointSuffix() {
108+
MockSecureSettings secureSettings = new MockSecureSettings();
109+
secureSettings.setString("azure.client.azure1.account", "myaccount1");
110+
secureSettings.setString("azure.client.azure1.key", Base64.encode("mykey1".getBytes(StandardCharsets.UTF_8)));
111+
secureSettings.setString("azure.client.azure2.account", "myaccount2");
112+
secureSettings.setString("azure.client.azure2.key", Base64.encode("mykey2".getBytes(StandardCharsets.UTF_8)));
113+
Settings settings = Settings.builder().setSecureSettings(secureSettings)
114+
.put("azure.client.azure1.endpoint_suffix", "my_endpoint_suffix").build();
115+
AzureStorageServiceImpl azureStorageService = new AzureStorageServiceImpl(settings, AzureStorageSettings.load(settings));
116+
CloudBlobClient client1 = azureStorageService.getSelectedClient("azure1", LocationMode.PRIMARY_ONLY);
117+
assertThat(client1.getEndpoint().toString(), equalTo("https://myaccount1.blob.my_endpoint_suffix"));
118+
119+
CloudBlobClient client2 = azureStorageService.getSelectedClient("azure2", LocationMode.PRIMARY_ONLY);
120+
assertThat(client2.getEndpoint().toString(), equalTo("https://myaccount2.blob.core.windows.net"));
95121
}
96122

97123
public void testGetSelectedClientWithNoPrimaryAndSecondary() {

0 commit comments

Comments
 (0)