Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/207 node include source factories #214

Merged
merged 6 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion benchmark.ps1
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#$gestaltVersions = @("0.32.0", "0.31.3", "0.31.2", "0.31.1", "0.31.0", "0.30.0", "0.29.0", "0.28.0", "0.27.0", "0.26.0", "0.25.3", "0.25.2", "0.25.1", "0.25.0", "0.24.6", "0.24.5", "0.24.4", "0.24.3", "0.24.2", "0.24.1", "0.24.0", "0.23.3", "0.23.2", "0.23.1", "0.23.0", "0.22.1", "0.21.0", "0.20.6", "0.20.5", "0.20.4", "0.20.3", "0.20.2", "0.20.1", "0.19.0", "0.18.0", "0.16.6", "0.16.5", "0.16.4", "0.16.3", "0.16.2", "0.16.1", "0.16.0", "0.15.0", "0.14.1", "0.14.0", "0.13.0", "0.12.0")
$gestaltVersions = @("0.32.0", "0.31.3", "0.31.2", "0.31.1", "0.31.0")
$gestaltVersions = @("0.32.1","0.32.0", "0.31.3", "0.31.2", "0.31.1", "0.31.0")
#jdkVersions = @(11 17 21)
$jdkVersions = @(11)

Expand Down
3 changes: 3 additions & 0 deletions gestalt-aws/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@

provides org.github.gestalt.config.processor.config.transform.Transformer with
org.github.gestalt.config.aws.transformer.AWSSecretTransformer;

provides org.github.gestalt.config.node.factory.ConfigNodeFactory with
org.github.gestalt.config.aws.node.factory.S3ConfigNodeFactory;
}

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.github.gestalt.config.aws.config;

import org.github.gestalt.config.exceptions.GestaltConfigurationException;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;

/**
Expand All @@ -13,6 +14,7 @@
public final class AWSBuilder {
private String region;
private SecretsManagerClient secretsClient;
private S3Client s3Client;

private AWSBuilder() {

Expand Down Expand Up @@ -49,14 +51,10 @@ public AWSBuilder setRegion(String region) {
}

public AWSModuleConfig build() throws GestaltConfigurationException {
if (region == null && secretsClient == null) {
throw new GestaltConfigurationException("AWSModuleConfig was built but one of the secret client " +
"or the region must be provided");
}

AWSModuleConfig awsModuleConfig = new AWSModuleConfig();
awsModuleConfig.setRegion(region);
awsModuleConfig.setSecretsClient(secretsClient);
awsModuleConfig.setS3Client(s3Client);

return awsModuleConfig;
}
Expand All @@ -82,4 +80,24 @@ public AWSBuilder setSecretsClient(SecretsManagerClient secretsClient) {
this.secretsClient = secretsClient;
return this;
}

/**
* Get the S3 Client.
*
* @return the S3 Client.
*/
public S3Client getS3Client() {
return s3Client;
}

/**
* Set the S3 Client.
*
* @param s3Client the S3 Client
* @return the builder
*/
public AWSBuilder setS3Client(S3Client s3Client) {
this.s3Client = s3Client;
return this;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.github.gestalt.config.aws.config;

import org.github.gestalt.config.entity.GestaltModuleConfig;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;

/**
Expand All @@ -16,6 +17,8 @@ public final class AWSModuleConfig implements GestaltModuleConfig {

private SecretsManagerClient secretsClient;

private S3Client s3Client;

AWSModuleConfig() {
}

Expand Down Expand Up @@ -69,4 +72,31 @@ public SecretsManagerClient getSecretsClient() {
public void setSecretsClient(SecretsManagerClient secretsClient) {
this.secretsClient = secretsClient;
}

/**
* If the AWS Module Config has an S3 client registered.
*
* @return If the AWS Module Config has an S3 client registered.
*/
public boolean hasS3Client() {
return s3Client != null;
}

/**
* Get the S3 Client.
*
* @return the S3 Client.
*/
public S3Client getS3Client() {
return s3Client;
}

/**
* Set the S3 Client.
*
* @param s3Client the S4 Client used to interact with S3
*/
public void setS3Client(S3Client s3Client) {
this.s3Client = s3Client;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,25 @@ public String description() {
", with message: " + ex.getMessage();
}
}

public static class AWSS3ClientConfigNotSet extends ValidationError {
private final String path;
private final String rawSubstitution;

public AWSS3ClientConfigNotSet(String path, String rawSubstitution) {
super(ValidationLevel.ERROR);
this.path = path;
this.rawSubstitution = rawSubstitution;
}

@Override
public String description() {
return "AWSModuleConfig has not been registered and or the S3 Client was not set. Register by creating a AWSBuilder " +
"then registering the AWSBuilder.build() results with the Gestalt Builder.addModuleConfig(). " +
"If you wish to use the aws module with node substitution/include " +
rawSubstitution + " on the path: " + path;
}
}
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package org.github.gestalt.config.aws.node.factory;

import org.github.gestalt.config.aws.config.AWSModuleConfig;
import org.github.gestalt.config.aws.errors.AWSValidationErrors;
import org.github.gestalt.config.aws.s3.S3ConfigSourceBuilder;
import org.github.gestalt.config.entity.ValidationError;
import org.github.gestalt.config.loader.ConfigLoaderService;
import org.github.gestalt.config.loader.ConfigLoaderUtils;
import org.github.gestalt.config.node.ConfigNode;
import org.github.gestalt.config.node.factory.ConfigNodeFactory;
import org.github.gestalt.config.node.factory.ConfigNodeFactoryConfig;
import org.github.gestalt.config.utils.GResultOf;
import software.amazon.awssdk.services.s3.S3Client;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
* Factory for creating a S3 Config Node from parameters.
*
* <p>Load a config source from a File then converts it to a config node
*
* @author <a href="mailto:colin.redmond@outlook.com"> Colin Redmond </a> (c) 2024.
*/
public class S3ConfigNodeFactory implements ConfigNodeFactory {
public static final String SOURCE_TYPE = "s3";
public static final String PARAMETER_BUCKET = "bucket";
public static final String PARAMETER_KEY = "key";
private static final System.Logger logger = System.getLogger(S3ConfigNodeFactory.class.getName());
private ConfigLoaderService configLoaderService;
private S3Client s3Client;

@Override
public void applyConfig(ConfigNodeFactoryConfig config) {
this.configLoaderService = config.getConfigLoaderService();
AWSModuleConfig moduleConfig = config.getConfig().getModuleConfig(AWSModuleConfig.class);

if (moduleConfig == null) {
logger.log(System.Logger.Level.WARNING, "AWSModuleConfig has not been registered. " +
"if you wish to use the aws module with S3 Config Node substitution ${include}=source=s3,bucket=test,key=my.properties " +
"then you must register an AWSModuleConfig config moduleConfig using the builder. " +
"S3 config node substitution/include will not work");
} else {
if (moduleConfig.hasS3Client()) {
s3Client = moduleConfig.getS3Client();
} else {
logger.log(System.Logger.Level.ERROR, "AWSModuleConfig was registered but the S3 client " +
"was not provided. S3 config node substitution/include will not work");
}
}
}

@Override
public Boolean supportsType(String type) {
return SOURCE_TYPE.equalsIgnoreCase(type);
}

@Override
public GResultOf<List<ConfigNode>> build(Map<String, String> parameters) {

if (s3Client == null) {
return GResultOf.errors(new AWSValidationErrors.AWSS3ClientConfigNotSet(SOURCE_TYPE, parameters.toString()));
}

var configSourceBuilder = S3ConfigSourceBuilder.builder();

List<ValidationError> errors = new ArrayList<>();
try {
for (Map.Entry<String, String> entry : parameters.entrySet()) {
switch (entry.getKey()) {
case PARAMETER_BUCKET:
configSourceBuilder.setBucketName(entry.getValue());
break;
case PARAMETER_KEY:
configSourceBuilder.setKeyName(entry.getValue());
break;
default:
errors.add(
new ValidationError.ConfigSourceFactoryUnknownParameter(SOURCE_TYPE, entry.getKey(), entry.getValue()));
break;
}
}

configSourceBuilder.setS3(s3Client);

var fileConfigSource = configSourceBuilder.build().getConfigSource();

GResultOf<List<ConfigNode>> loadedNodes = ConfigLoaderUtils.convertSourceToNodes(fileConfigSource, configLoaderService);
errors.addAll(loadedNodes.getErrors());

return GResultOf.resultOf(loadedNodes.results(), errors);
} catch (Exception ex) {
errors.add(new ValidationError.ConfigSourceFactoryException(SOURCE_TYPE, ex));
return GResultOf.errors(errors);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,12 @@ public void applyConfig(ConfigNodeProcessorConfig config) {

@Override
public GResultOf<String> process(String path, String secretNameKey, String rawValue) {
if (secretNameKey != null) {
if (secretNameKey != null && !secretNameKey.isEmpty()) {
try {
if (secretsClient == null) {
return GResultOf.errors(new AWSValidationErrors.AWSModuleConfigNotSet(path, rawValue));
}

String[] secretParts = secretNameKey.split(":");

if (secretParts.length != 2) {
Expand All @@ -68,10 +72,6 @@ public GResultOf<String> process(String path, String secretNameKey, String rawVa
String secretName = secretParts[0];
String secretKey = secretParts[1];

if (secretsClient == null) {
return GResultOf.errors(new AWSValidationErrors.AWSModuleConfigNotSet(path, rawValue));
}

GetSecretValueRequest valueRequest = GetSecretValueRequest.builder()
.secretId(secretName)
.build();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.github.gestalt.config.aws.node.factory.S3ConfigNodeFactory
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,4 @@ public void createAWSConfigClient() throws GestaltConfigurationException {
Assertions.assertNull(builder.build().getRegion());
Assertions.assertNotNull(builder.build().getSecretsClient());
}

@Test
public void createAWSConfigEmpty() {

AWSBuilder builder = AWSBuilder.builder();

GestaltConfigurationException e = Assertions.assertThrows(GestaltConfigurationException.class, builder::build);
Assertions.assertEquals("AWSModuleConfig was built but one of the secret client or the region must be provided",
e.getMessage());
}


}
Loading