Skip to main content

Node Substitution

Using the $include keyword as part of a config path, you can include the referenced config node tree into the path provided. By default, the node is merged into the provided node under the current node as defaults that will be overridden. You can control the order of the nodes, by including a number where < 0 is included below the current node and > 0 is included above the current node. The root node is always 0. Having two nodes share the same order is undefined. For example: $include:-1 for included under the current node, and $include:1 for included over the current node. If you are included multiple nodes each node must have an order, or the results are undefined, and some includes may be lost.

You can include into the root or any sub node. It also supports nested include.

The include node must provide a source that is used to determine how to include the source. Each source accepts different parameters that can be provided in the form of a key value with a comma separated list. One of the key value pairs must be source that is used to determine the source type. For example a classPath source with the resource includes.properties would look like:

$include=source=classPath,resource=includes.properties

Example of include a classPath Node into a sub path with properties file imports.properties.

b=b changed
c=c

In the first example we include the loaded file node with default settings of order -1 $include:-1, where the root node is always order 0. So the node will be loaded under the current root nodes so will provide defaults that will be overwritten.

  Map<String, String> configs = new HashMap<>();
configs.put("a", "a");
configs.put("b", "b");
configs.put("$include", "source=classPath,resource=includes.properties");


Gestalt gestalt = new GestaltBuilder()
.addSource(MapConfigSourceBuilder.builder().setCustomConfig(configs).build())
.build();

gestalt.loadConfigs();

Assertions.assertEquals("a", gestalt.getConfig("a", String.class));
Assertions.assertEquals("b", gestalt.getConfig("b", String.class));
Assertions.assertEquals("c", gestalt.getConfig("c", String.class));

That is why we don't see b=b changed as it will be overwritten by b=b, but we still see c=c as it was in the included defaults and not overwritten.

In this second example we include the node with $include:1. Since the root node is always order 0, the included nodes will override the root.

  Map<String, String> configs = new HashMap<>();
configs.put("a", "a");
configs.put("b", "b");
configs.put("$include:1", "source=classPath,resource=includes.properties");

Gestalt gestalt = new GestaltBuilder()
.addSource(MapConfigSourceBuilder.builder().setCustomConfig(configs).build())
.build();

gestalt.loadConfigs();

Assertions.assertEquals("a", gestalt.getConfig("a", String.class));
Assertions.assertEquals("b changed", gestalt.getConfig("b", String.class));
Assertions.assertEquals("c", gestalt.getConfig("c", String.class));

That is why we see b=b changed as it is overwritten the root b=b.

In the final example, we include the loaded file node in the sub path sub.

  Map<String, String> configs = new HashMap<>();
configs.put("a", "a");
configs.put("b", "b");
configs.put("sub.a", "a");
configs.put("sub.$include:1", "source=classPath,resource=includes.properties");

Gestalt gestalt = new GestaltBuilder()
.addSource(MapConfigSourceBuilder.builder().setCustomConfig(configs).build())
.build();

gestalt.loadConfigs();

Assertions.assertEquals("a", gestalt.getConfig("a", String.class));
Assertions.assertEquals("b", gestalt.getConfig("b", String.class));
Assertions.assertEquals("a", gestalt.getConfig("sub.a", String.class));
Assertions.assertEquals("b changed", gestalt.getConfig("sub.b", String.class));
Assertions.assertEquals("c", gestalt.getConfig("sub.c", String.class));

As you can see the nodes from the file includes.properties were included in the sub path sub. As can bee seen with sub.b = b changed and sub.c = c.

Supported substitution sources:

Source TypeModuleParameterDescription
classPathgestalt-coreresourceThe name of the classpath resource to load.
nodegestalt-corepathLoad an node at the given path into the current node.
envgestalt-corefailOnErrorsIf we should fail on errors. Since Env Vars may not always conform to Gestalt expectations we can disable the errors and make it more lenient while loading Env Vars.
prefixOnly include Env Vars that match the prefix.
ignoreCaseOnPrefixWhen matching the prefix should it ignore case.
removePrefixIf we should remove the prefix after matching.
filegestalt-corefileLoad a file at a given location to the current node.
pathLoad a file as a path at a given location to the current node.
k8Secretgestalt-corepathThe directory to scan for kubernetes secrets.
fileThe file directory to scan for kubernetes secrets.
systemgestalt-corefailOnErrorsIf we should fail on errors. Since System Variables may not always conform to Gestalt expectations we can disable the errors and make it more lenient while loading System Vars.
s3gestalt-awsModule ConfigTo use S3 with the include node feature you must register an S3Client via the AWSModuleConfig: Gestalt gestalt = builder.addModuleConfig(AWSBuilder.builder().setRegion("us-east-1").setS3Client(s3Client).build()).build();
bucketThe S3 bucket to search in.
keyThe Key of the config file to load.
blobgestalt-azureModule ConfigTo use Azure Blob with the include node feature you must register an BlobClient or a StorageSharedKeyCredential via the AzureModuleBuilder : Gestalt gestalt = builder.addModuleConfig(AzureModuleBuilder.builder().setBlobClient(blobClient).build())).build();
endpointAzure endpoint to access the blob storage.
containerAzure Container containing the blob.
blobThe blob with the file.
gitgestalt-gitModule ConfigWhen accessing private repos you must register the GitModuleConfig with Gestalt. Gestalt gestalt = new GestaltBuilder().addModuleConfig(GitModuleConfigBuilder.builder().setCredentials(new UsernamePasswordCredentialsProvider(userName, password)).build()).build();
repoURIWhere to locate the repo
branchWhat branch to find the config files.
configFilePathThe subpath in the repo URI to find the config file.
localRepoDirectoryWhere to save the git files Gestalt Syncs.
gcsgestalt-google-cloudModule ConfigTo use GCS with the include node feature you can register a Storage client via the GoogleModuleConfig : Gestalt gestalt = builder.addModuleConfig(GoogleModuleConfigBuilder.builder().setStorage(storage).build())).build();. Otherwise it will fallback to the default storage client.
bucketNameWhat bucket to find the config files.
objectNameThe specific config file to include.