Skip to content

Commit f8cb4b4

Browse files
committed
test(spark): characterize HadoopUtils S3 and Azure credential forwarding
1 parent c5e075a commit f8cb4b4

1 file changed

Lines changed: 149 additions & 0 deletions

File tree

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
package dev.vortex.spark.config;
5+
6+
import static org.junit.jupiter.api.Assertions.assertEquals;
7+
import static org.junit.jupiter.api.Assertions.assertFalse;
8+
import static org.junit.jupiter.api.Assertions.assertTrue;
9+
10+
import java.util.Map;
11+
import org.apache.hadoop.conf.Configuration;
12+
import org.junit.jupiter.api.DisplayName;
13+
import org.junit.jupiter.api.Test;
14+
15+
/**
16+
* Unit tests for {@link HadoopUtils}, which forwards S3 and Azure credentials from a Hadoop {@link Configuration} to
17+
* the Vortex object-store property keys.
18+
*
19+
* <p>Characterizes the {@code fs.s3a.*} to {@code aws_*} key mapping (including https-qualification of bare endpoints),
20+
* the prefix-based Azure account key and SAS token extraction, and the skip-signature fallback for anonymous Azure
21+
* access.
22+
*/
23+
final class HadoopUtilsTest {
24+
/** A Configuration that does not load the default resources, so tests see only the keys they set. */
25+
private static Configuration emptyConf() {
26+
return new Configuration(/* loadDefaults= */ false);
27+
}
28+
29+
// --- s3PropertiesFromHadoopConf ---
30+
31+
@Test
32+
@DisplayName("Maps fs.s3a credentials, session token, and region to the aws_* property keys")
33+
void s3MapsCredentialKeys() {
34+
Configuration conf = emptyConf();
35+
conf.set(HadoopUtils.FS_S3A_ACCESS_KEY, "AKIAEXAMPLE");
36+
conf.set(HadoopUtils.FS_S3A_SECRET_KEY, "secret");
37+
conf.set(HadoopUtils.FS_S3A_SESSION_TOKEN, "token");
38+
conf.set(HadoopUtils.FS_S3A_ENDPOINT_REGION, "us-west-2");
39+
40+
Map<String, String> properties = HadoopUtils.s3PropertiesFromHadoopConf(conf);
41+
42+
assertEquals("AKIAEXAMPLE", properties.get("aws_access_key_id"));
43+
assertEquals("secret", properties.get("aws_secret_access_key"));
44+
assertEquals("token", properties.get("aws_session_token"));
45+
assertEquals("us-west-2", properties.get("aws_region"));
46+
}
47+
48+
@Test
49+
@DisplayName("Qualifies a bare fs.s3a.endpoint with https://")
50+
void s3QualifiesBareEndpoint() {
51+
Configuration conf = emptyConf();
52+
conf.set(HadoopUtils.FS_S3A_ENDPOINT, "s3.us-west-2.amazonaws.com");
53+
54+
Map<String, String> properties = HadoopUtils.s3PropertiesFromHadoopConf(conf);
55+
56+
assertEquals("https://s3.us-west-2.amazonaws.com", properties.get("aws_endpoint"));
57+
}
58+
59+
@Test
60+
@DisplayName("Preserves an fs.s3a.endpoint that already has an http or https scheme")
61+
void s3PreservesSchemedEndpoint() {
62+
Configuration httpConf = emptyConf();
63+
httpConf.set(HadoopUtils.FS_S3A_ENDPOINT, "http://localhost:9000");
64+
assertEquals(
65+
"http://localhost:9000",
66+
HadoopUtils.s3PropertiesFromHadoopConf(httpConf).get("aws_endpoint"));
67+
68+
Configuration httpsConf = emptyConf();
69+
httpsConf.set(HadoopUtils.FS_S3A_ENDPOINT, "https://s3.example.com");
70+
assertEquals(
71+
"https://s3.example.com",
72+
HadoopUtils.s3PropertiesFromHadoopConf(httpsConf).get("aws_endpoint"));
73+
}
74+
75+
@Test
76+
@DisplayName("Ignores Hadoop keys that are not S3-relevant")
77+
void s3IgnoresUnrelatedKeys() {
78+
Configuration conf = emptyConf();
79+
conf.set("fs.defaultFS", "hdfs://namenode:8020");
80+
conf.set("fs.s3a.connection.maximum", "64");
81+
82+
assertTrue(HadoopUtils.s3PropertiesFromHadoopConf(conf).isEmpty());
83+
}
84+
85+
@Test
86+
@DisplayName("Returns no properties for an empty configuration")
87+
void s3EmptyConfYieldsNoProperties() {
88+
assertTrue(HadoopUtils.s3PropertiesFromHadoopConf(emptyConf()).isEmpty());
89+
}
90+
91+
// --- azurePropertiesFromHadoopConf ---
92+
93+
@Test
94+
@DisplayName("Extracts the storage account key from any fs.azure.account.key-prefixed entry")
95+
void azureExtractsAccountKey() {
96+
Configuration conf = emptyConf();
97+
conf.set(HadoopUtils.ACCESS_KEY_PREFIX + ".myaccount.dfs.core.windows.net", "account-key");
98+
99+
Map<String, String> properties = HadoopUtils.azurePropertiesFromHadoopConf(conf);
100+
101+
assertEquals("account-key", properties.get("azure_storage_account_key"));
102+
assertFalse(properties.containsKey("azure_skip_signature"));
103+
}
104+
105+
@Test
106+
@DisplayName("Extracts the SAS token from any fs.azure.sas.fixed.token-prefixed entry")
107+
void azureExtractsSasToken() {
108+
Configuration conf = emptyConf();
109+
conf.set(HadoopUtils.FIXED_TOKEN_PREFIX + "myaccount.dfs.core.windows.net", "sas-token");
110+
111+
Map<String, String> properties = HadoopUtils.azurePropertiesFromHadoopConf(conf);
112+
113+
assertEquals("sas-token", properties.get("azure_storage_sas_key"));
114+
}
115+
116+
@Test
117+
@DisplayName("Falls back to skipping signatures when no account key is configured")
118+
void azureSkipsSignatureWithoutAccountKey() {
119+
Map<String, String> properties = HadoopUtils.azurePropertiesFromHadoopConf(emptyConf());
120+
121+
assertEquals("true", properties.get("azure_skip_signature"));
122+
assertFalse(properties.containsKey("azure_storage_account_key"));
123+
}
124+
125+
@Test
126+
@DisplayName("Skips signatures even when only a SAS token is configured")
127+
void azureSasOnlyStillSkipsSignature() {
128+
Configuration conf = emptyConf();
129+
conf.set(HadoopUtils.FIXED_TOKEN_PREFIX + "myaccount.dfs.core.windows.net", "sas-token");
130+
131+
Map<String, String> properties = HadoopUtils.azurePropertiesFromHadoopConf(conf);
132+
133+
assertEquals("sas-token", properties.get("azure_storage_sas_key"));
134+
assertEquals("true", properties.get("azure_skip_signature"));
135+
}
136+
137+
@Test
138+
@DisplayName("Ignores Hadoop keys that are not Azure-relevant")
139+
void azureIgnoresUnrelatedKeys() {
140+
Configuration conf = emptyConf();
141+
conf.set("fs.azure.io.retry.max.retries", "5");
142+
conf.set("fs.defaultFS", "abfss://container@account.dfs.core.windows.net/");
143+
144+
Map<String, String> properties = HadoopUtils.azurePropertiesFromHadoopConf(conf);
145+
146+
assertFalse(properties.containsKey("azure_storage_account_key"));
147+
assertFalse(properties.containsKey("azure_storage_sas_key"));
148+
}
149+
}

0 commit comments

Comments
 (0)