Skip to content

Commit 3e52bec

Browse files
committed
feat(hdfs): add support for localHdfsSitePath configuration
- Introduced `localHdfsSitePath` to enable writing host-side Hadoop XML files with HDFS client properties. - Updated `BigDataContainerFactory` to generate and manage `hdfs-site.xml` files dynamically. - Enhanced Gradle plugin and test framework to integrate the new configuration option. - Updated user documentation to explain the usage and behavior of `localHdfsSitePath`.
1 parent f14f336 commit 3e52bec

8 files changed

Lines changed: 49 additions & 7 deletions

File tree

core/src/main/kotlin/org/openprojectx/bigdata/test/core/BigDataTestKitOptions.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ data class HdfsOptions(
7070
val nameNodePort: Int = 8020,
7171
val dataNodePort: Int = 9866,
7272
val dataNodeHostname: String = "hdfs",
73+
val localHdfsSitePath: String? = null,
7374
val webPort: Int = 9870,
7475
val webTls: HttpTlsOptions = HttpTlsOptions(),
7576
val kerberos: KerberosAuthOptions = KerberosAuthOptions(

core/src/main/kotlin/org/openprojectx/bigdata/test/core/config/BigDataTestConfig.kt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,13 @@ data class BigDataTestConfig(
7070

7171
data class BigDataTestHdfsConfig(
7272
val dataNodeHostname: String? = null,
73+
val localHdfsSitePath: String? = null,
7374
) {
7475
fun merge(override: BigDataTestHdfsConfig): BigDataTestHdfsConfig =
75-
BigDataTestHdfsConfig(dataNodeHostname = override.dataNodeHostname ?: dataNodeHostname)
76+
BigDataTestHdfsConfig(
77+
dataNodeHostname = override.dataNodeHostname ?: dataNodeHostname,
78+
localHdfsSitePath = override.localHdfsSitePath ?: localHdfsSitePath,
79+
)
7680
}
7781

7882
data class BigDataTestHiveMetastoreConfig(
@@ -361,7 +365,10 @@ class BigDataTestConfigLoader(
361365
trustStorePassword = tls.string("trustStorePassword"),
362366
haproxyImage = tls.string("haproxyImage"),
363367
),
364-
hdfs = BigDataTestHdfsConfig(dataNodeHostname = hdfs.string("dataNodeHostname")),
368+
hdfs = BigDataTestHdfsConfig(
369+
dataNodeHostname = hdfs.string("dataNodeHostname"),
370+
localHdfsSitePath = hdfs.string("localHdfsSitePath"),
371+
),
365372
hiveMetastore = BigDataTestHiveMetastoreConfig(
366373
databaseName = hiveMetastore.string("databaseName"),
367374
databaseUser = hiveMetastore.string("databaseUser"),

core/src/main/kotlin/org/openprojectx/bigdata/test/core/container/BigDataContainerFactory.kt

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ internal class BigDataContainerFactory(
4949
} else {
5050
null
5151
}
52+
private val hdfsClientDir: Path by lazy {
53+
options.hdfs.localHdfsSitePath
54+
?.let { Path.of(it).parent }
55+
?.let { Files.createDirectories(it) }
56+
?: kerberosDir
57+
?: Files.createTempDirectory("bigdata-test-hdfs-client-")
58+
}
5259
private val tlsMaterial: TlsMaterial by lazy { TlsMaterial(options.tls.copy(enabled = true)) }
5360

5461
fun healthCheck(service: BigDataService, container: GenericContainer<*>, endpoint: BigDataEndpoint) {
@@ -198,6 +205,13 @@ internal class BigDataContainerFactory(
198205
backendPort = hdfs.webPort,
199206
hostPort = tlsHostPort(options.portBindings.hdfsWebTls),
200207
)
208+
val clientProperties = mapOf(
209+
"fs.defaultFS" to "hdfs://$nameNode",
210+
"dfs.client.use.datanode.hostname" to "true",
211+
"dfs.datanode.hostname" to hdfs.dataNodeHostname,
212+
) + hdfsKerberosClientProperties(hdfs.kerberos) +
213+
webTls.property("dfs.namenode.https-address")
214+
val localHdfsSite = writeLocalHdfsSiteXml(hdfs, clientProperties)
201215
BigDataEndpoint(
202216
service = BigDataService.HDFS,
203217
host = container.host,
@@ -207,12 +221,10 @@ internal class BigDataContainerFactory(
207221
"web" to container.getMappedPort(hdfs.webPort),
208222
) + webTls.port("web-tls"),
209223
properties = mapOf(
210-
"fs.defaultFS" to "hdfs://$nameNode",
211224
"spring.hadoop.fs-uri" to "hdfs://$nameNode",
212-
"dfs.client.use.datanode.hostname" to "true",
213-
"dfs.datanode.hostname" to hdfs.dataNodeHostname,
214-
) + hdfsKerberosClientProperties(hdfs.kerberos) +
215-
webTls.property("dfs.namenode.https-address") +
225+
"bigdata.test.hdfs.hdfs-site" to localHdfsSite,
226+
"bigdata.test.hdfs.hdfs-site.container" to "/opt/hadoop/etc/hadoop/hdfs-site.xml",
227+
) + clientProperties +
216228
webTls.jvmProperties() +
217229
kerberosProperties("hadoop", hdfs.kerberos),
218230
)
@@ -743,6 +755,7 @@ internal class BigDataContainerFactory(
743755
}
744756

745757
private fun writeConfigurationXml(path: Path, properties: Map<String, String>) {
758+
path.parent?.let { Files.createDirectories(it) }
746759
Files.writeString(path, configurationXml(properties), StandardCharsets.UTF_8)
747760
}
748761

@@ -1165,6 +1178,14 @@ internal class BigDataContainerFactory(
11651178
emptyMap()
11661179
}
11671180

1181+
private fun writeLocalHdfsSiteXml(hdfs: HdfsOptions, properties: Map<String, String>): String {
1182+
val path = hdfs.localHdfsSitePath
1183+
?.let { Path.of(it) }
1184+
?: hdfsClientDir.resolve("hdfs-site.xml")
1185+
writeConfigurationXml(path, properties)
1186+
return path.toString()
1187+
}
1188+
11681189
private fun hdfsSiteSecurity(kerberos: KerberosAuthOptions): String =
11691190
if (kerberos.enabled) {
11701191
"""

doc/user-guide.adoc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,13 +290,16 @@ HDFS-specific startup settings use the `[hdfs]` table. Keep the default `dataNod
290290
----
291291
[hdfs]
292292
dataNodeHostname = "localhost"
293+
localHdfsSitePath = "build/bigdata-test/hadoop/hdfs-site.xml"
293294
294295
[ports]
295296
hdfsNameNode = 8020
296297
hdfsDataNode = 9866
297298
hdfsWeb = 9870
298299
----
299300

301+
`localHdfsSitePath` is optional. When set, the framework writes a host-side Hadoop XML file with the resolved HDFS client properties, including the mapped NameNode URI, DataNode hostname mode, and Kerberos client settings when HDFS Kerberos is enabled. When omitted, the file is generated in framework-managed temporary material.
302+
300303
=== Container Customization Escape Hatch
301304

302305
Typed service options should cover the normal path, but integration-test containers sometimes need image-specific workarounds before the framework has first-class support. Use container customizations as an escape hatch for troubleshooting or temporary overrides.
@@ -1484,6 +1487,7 @@ bigDataTest {
14841487
hdfs {
14851488
kerberosEnabled.set(true)
14861489
dataNodeHostname.set("localhost")
1490+
localHdfsSitePath.set("build/bigdata-test/hadoop/hdfs-site.xml")
14871491
}
14881492
ports {
14891493
hdfsNameNode.set(8020)
@@ -1614,11 +1618,14 @@ The plugin injects raw endpoint properties, such as `fs.defaultFS`, `hive.metast
16141618
[source,text]
16151619
----
16161620
bigdata.test.endpoint.hdfs.properties.fs.defaultFS
1621+
bigdata.test.endpoint.hdfs.properties.bigdata.test.hdfs.hdfs-site
16171622
bigdata.test.endpoint.hdfs.ports.namenode
16181623
bigdata.test.endpoint.localstack-s3.properties.aws.endpoint-url.s3
16191624
bigdata.test.extensions.s3-jceks.credential-provider.path
16201625
----
16211626

1627+
For HDFS clients that prefer Hadoop XML resources, read `bigdata.test.endpoint.hdfs.properties.bigdata.test.hdfs.hdfs-site` and add that file to the Hadoop `Configuration`. The Gradle plugin also injects the same value as an environment variable for launched tasks.
1628+
16221629
Environment variable names are generated by uppercasing property keys and replacing non-alphanumeric characters with `_`:
16231630

16241631
[source,text]

example/spring-gradle-plugin/src/main/resources/spring-bigdata-test.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ debug = true
1313

1414
[hdfs]
1515
dataNodeHostname = "localhost"
16+
localHdfsSitePath = "build/bigdata-test/hadoop/hdfs-site.xml"
1617

1718
[ports]
1819
hdfsNameNode = 8020

gradle-plugin/src/main/kotlin/org/openprojectx/bigdata/test/gradle/BigDataTestGradleExtension.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ abstract class BigDataTestGradleHdfs @Inject constructor(objects: ObjectFactory)
157157
val image: Property<String> = objects.property(String::class.java).convention("apache/hadoop:3.5.0")
158158
val kerberosEnabled: Property<Boolean> = objects.property(Boolean::class.java).convention(false)
159159
val dataNodeHostname: Property<String> = objects.property(String::class.java).convention("hdfs")
160+
val localHdfsSitePath: Property<String> = objects.property(String::class.java).convention("")
160161
}
161162

162163
abstract class BigDataTestGradleHiveMetastore @Inject constructor(objects: ObjectFactory) {

gradle-plugin/src/main/kotlin/org/openprojectx/bigdata/test/gradle/BigDataTestGradlePlugin.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ class BigDataTestGradlePlugin : Plugin<Project> {
9393
spec.parameters.hdfsImage.set(extension.hdfs.image)
9494
spec.parameters.hdfsKerberosEnabled.set(extension.hdfs.kerberosEnabled)
9595
spec.parameters.hdfsDataNodeHostname.set(extension.hdfs.dataNodeHostname)
96+
spec.parameters.hdfsLocalHdfsSitePath.set(extension.hdfs.localHdfsSitePath)
9697

9798
spec.parameters.hiveMetastoreImage.set(extension.hiveMetastore.image)
9899
spec.parameters.hiveMetastoreDatabaseImage.set(extension.hiveMetastore.databaseImage)
@@ -307,6 +308,7 @@ class BigDataTestGradlePlugin : Plugin<Project> {
307308
extension.tls.haproxyImage.tomlConvention(config.tls.haproxyImage)
308309

309310
extension.hdfs.dataNodeHostname.tomlConvention(config.hdfs.dataNodeHostname)
311+
extension.hdfs.localHdfsSitePath.tomlConvention(config.hdfs.localHdfsSitePath)
310312
extension.hiveMetastore.databaseName.tomlConvention(config.hiveMetastore.databaseName)
311313
extension.hiveMetastore.databaseUser.tomlConvention(config.hiveMetastore.databaseUser)
312314
extension.hiveMetastore.databasePassword.tomlConvention(config.hiveMetastore.databasePassword)

gradle-plugin/src/main/kotlin/org/openprojectx/bigdata/test/gradle/BigDataTestGradleService.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ abstract class BigDataTestGradleService : BuildService<BigDataTestGradleService.
8585
val hdfsImage: Property<String>
8686
val hdfsKerberosEnabled: Property<Boolean>
8787
val hdfsDataNodeHostname: Property<String>
88+
val hdfsLocalHdfsSitePath: Property<String>
8889

8990
val hiveMetastoreImage: Property<String>
9091
val hiveMetastoreDatabaseImage: Property<String>
@@ -205,6 +206,7 @@ abstract class BigDataTestGradleService : BuildService<BigDataTestGradleService.
205206
enabled = true,
206207
image = parameters.hdfsImage.get(),
207208
dataNodeHostname = parameters.hdfsDataNodeHostname.get(),
209+
localHdfsSitePath = projectPath(parameters.hdfsLocalHdfsSitePath.get()),
208210
kerberos = KerberosAuthOptions(
209211
enabled = parameters.hdfsKerberosEnabled.get(),
210212
servicePrincipal = "nn/hdfs.${parameters.kerberosDomain.get()}@${parameters.kerberosRealm.get()}",

0 commit comments

Comments
 (0)