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: map decoder supports flattening maps and arrays. https://github… #101

Merged
merged 1 commit into from
Jul 23, 2023
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
4 changes: 2 additions & 2 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ max_line_length = 140
ij_visual_guides = 140
ij_continuation_indent_size = 4

[*.{kt, kts}]
[*.{kt,kts}]
indent_size = 4
max_line_length = 140
ij_visual_guides = 140
ij_continuation_indent_size = 4

# Markdown & YAML Settings
[*.{md, yml, yaml}]
[*.{md,yml,yaml}]
trim_trailing_whitespace = false
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ plugins {

allprojects {
group = "com.github.gestalt-config"
version = "0.22.0"
version = "0.22.1"
}


2 changes: 1 addition & 1 deletion buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ plugins {
}

kotlin {
jvmToolchain(libs.versions.java.get().toInt())
jvmToolchain(libs.versions.java.get().toInt())
}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ dependencies {

detekt {
toolVersion = libs.versions.detekt.get()
config = files(project.rootDir.resolve("config/detekt/config.yml"))
config.setFrom("$rootDir/config/detekt/config.yml")
debug = false
parallel = false
}
Expand All @@ -25,7 +25,7 @@ tasks.withType<io.gitlab.arturbosch.detekt.Detekt> {
exclude(".*/build/.*")

reports {
xml.required.set(false)
html.required.set(false)
xml.required.set(true)
html.required.set(true)
}
}
2 changes: 1 addition & 1 deletion config/detekt/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -731,7 +731,7 @@ style:
UntilInsteadOfRangeTo:
active: false
UnusedImports:
active: false
active: true
UnusedParameter:
active: true
allowedNames: 'ignored|expected'
Expand Down
22 changes: 12 additions & 10 deletions gestalt-aws/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
plugins {
id("gestalt.java-library-conventions")
id("gestalt.java-test-conventions")
id("gestalt.java-code-quality-conventions")
id("gestalt.java-publish-conventions")
id("gestalt.java-library-conventions")
id("gestalt.java-test-conventions")
id("gestalt.java-code-quality-conventions")
id("gestalt.java-publish-conventions")
}

dependencies {
implementation(project(":gestalt-core"))
implementation(libs.aws.s3)
implementation(libs.aws.secret)
implementation(libs.aws.url.client)
implementation(libs.jackson.databind)
testImplementation(libs.aws.mock)
implementation(project(":gestalt-core"))
implementation(platform(libs.aws.bom))
api(libs.aws.s3)
api(libs.aws.secret)
api(libs.aws.url.client)
implementation(libs.jackson.databind)
testImplementation(libs.aws.mock)
testImplementation(libs.testcontainers.junit5)
}


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

import com.adobe.testing.s3mock.testcontainers.S3MockContainer;
import org.github.gestalt.config.exceptions.GestaltException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.S3Configuration;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.utils.AttributeMap;

import java.io.File;
import java.net.URI;
import java.util.Collection;

import static java.util.Arrays.asList;
import static software.amazon.awssdk.http.SdkHttpConfigurationOption.TRUST_ALL_CERTIFICATES;

@Testcontainers
class S3ConfigSourceDockerTest {
private static final String BUCKET_NAME = "testbucket";
private static final String BUCKET_NAME_2 = "testbucket2";

private static final String S3MOCK_VERSION = System.getProperty("s3mock.version", "latest");
private static final Collection<String> INITIAL_BUCKET_NAMES = asList(BUCKET_NAME, BUCKET_NAME_2);
private static final String TEST_ENC_KEYREF =
"arn:aws:kms:us-east-1:1234567890:key/valid-test-key-ref";

private static final String UPLOAD_FILE_NAME = "src/test/resources/default.properties";

private S3Client s3Client;

@Container
private static final S3MockContainer s3Mock =
new S3MockContainer(S3MOCK_VERSION)
.withValidKmsKeys(TEST_ENC_KEYREF)
.withInitialBuckets(String.join(",", INITIAL_BUCKET_NAMES));

@BeforeEach
void setUp() {
// Must create S3Client after S3MockContainer is started, otherwise we can't request the random
// locally mapped port for the endpoint
var endpoint = s3Mock.getHttpsEndpoint();
s3Client = createS3ClientV2(endpoint);
}

protected S3Client createS3ClientV2(String endpoint) {
return S3Client.builder()
.region(Region.of("us-east-1"))
.credentialsProvider(
StaticCredentialsProvider.create(AwsBasicCredentials.create("foo", "bar")))
.serviceConfiguration(S3Configuration.builder().pathStyleAccessEnabled(true).build())
.endpointOverride(URI.create(endpoint))
.httpClient(UrlConnectionHttpClient.builder().buildWithDefaults(
AttributeMap.builder().put(TRUST_ALL_CERTIFICATES, Boolean.TRUE).build()))
.build();
}

@Test
void loadFile() throws GestaltException {

final File uploadFile = new File(UPLOAD_FILE_NAME);

s3Client.putObject(
PutObjectRequest.builder().bucket(BUCKET_NAME).key(uploadFile.getName()).build(),
RequestBody.fromFile(uploadFile));


S3ConfigSource source = new S3ConfigSource(s3Client, BUCKET_NAME, uploadFile.getName());

Assertions.assertTrue(source.hasStream());
Assertions.assertNotNull(source.loadStream());
}

@Test
void loadFileDoesNotExist() throws GestaltException {

final File uploadFile = new File(UPLOAD_FILE_NAME);

s3Client.putObject(
PutObjectRequest.builder().bucket(BUCKET_NAME_2).key(uploadFile.getName()).build(),
RequestBody.fromFile(uploadFile));


S3ConfigSource source = new S3ConfigSource(s3Client, BUCKET_NAME_2, uploadFile.getName() + ".noMatch");

Assertions.assertTrue(source.hasStream());
GestaltException ex = Assertions.assertThrows(GestaltException.class, source::loadStream);

Assertions.assertEquals("Exception loading S3 key: default.properties.noMatch, bucket: testbucket2, " +
"with error: The specified key does not exist.", ex.getMessage());
}
}
Original file line number Diff line number Diff line change
@@ -1,65 +1,26 @@
package org.github.gestalt.config.aws.s3;

import com.adobe.testing.s3mock.junit5.S3MockExtension;
import org.github.gestalt.config.exceptions.GestaltException;
import org.github.gestalt.config.tag.Tags;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import software.amazon.awssdk.core.sync.RequestBody;
import org.mockito.Mockito;
import org.testcontainers.junit.jupiter.Testcontainers;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.CreateBucketRequest;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;

import java.io.File;

class S3ConfigSourceTest {

@RegisterExtension
static final S3MockExtension S3_MOCK =
S3MockExtension.builder().silent().withSecureConnection(false).build();
@Testcontainers
class S3ConfigSourceMockTest {

private static final String BUCKET_NAME = "testbucket";
private static final String BUCKET_NAME_2 = "testbucket2";
private static final String UPLOAD_FILE_NAME = "src/test/resources/default.properties";

private final S3Client s3Client = S3_MOCK.createS3ClientV2();

@Test
void loadFile() throws GestaltException {

final File uploadFile = new File(UPLOAD_FILE_NAME);

s3Client.createBucket(CreateBucketRequest.builder().bucket(BUCKET_NAME).build());
s3Client.putObject(
PutObjectRequest.builder().bucket(BUCKET_NAME).key(uploadFile.getName()).build(),
RequestBody.fromFile(uploadFile));


S3ConfigSource source = new S3ConfigSource(s3Client, BUCKET_NAME, uploadFile.getName());

Assertions.assertTrue(source.hasStream());
Assertions.assertNotNull(source.loadStream());
}

@Test
void loadFileDoesNotExist() throws GestaltException {

final File uploadFile = new File(UPLOAD_FILE_NAME);

s3Client.createBucket(CreateBucketRequest.builder().bucket(BUCKET_NAME_2).build());
s3Client.putObject(
PutObjectRequest.builder().bucket(BUCKET_NAME_2).key(uploadFile.getName()).build(),
RequestBody.fromFile(uploadFile));

private static final String UPLOAD_FILE_NAME = "src/test/resources/default.properties";

S3ConfigSource source = new S3ConfigSource(s3Client, BUCKET_NAME_2, uploadFile.getName() + ".noMatch");

Assertions.assertTrue(source.hasStream());
GestaltException ex = Assertions.assertThrows(GestaltException.class, source::loadStream);
private final S3Client s3Client = Mockito.mock();

Assertions.assertEquals("Exception loading S3 key: default.properties.noMatch, bucket: testbucket2, " +
"with error: The specified key does not exist.", ex.getMessage());
@BeforeEach
void setUp() {
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public <T> T getConfig(String path, TypeCapture<T> klass) throws GestaltExceptio
@SuppressWarnings("unchecked")
public <T> T getConfig(String path, TypeCapture<T> klass, Tags tags) throws GestaltException {
Triple<String, TypeCapture<?>, Tags> key = new Triple<>(path, klass, tags);
if (cache.containsKey(key) && cache.get(key) != null) {
if (cache.get(key) != null) {
return (T) cache.get(key);
} else {
T result = delegate.getConfig(path, klass, tags);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ private <T> T getConfigInternal(String path, boolean failOnErrors, T defaultVal,
if (logger.isLoggable(gestaltConfig.getLogLevelForMissingValuesWhenDefaultOrOptional())) {
String errorMsg = ErrorsUtil.buildErrorMessage("Failed getting config path: " + combinedPath +
", for class: " + klass.getName() + " returning empty Optional", results.getErrors());
logger.log(DEBUG, errorMsg);
logger.log(gestaltConfig.getLogLevelForMissingValuesWhenDefaultOrOptional(), errorMsg);
}

return defaultVal;
Expand All @@ -354,7 +354,7 @@ private <T> T getConfigInternal(String path, boolean failOnErrors, T defaultVal,
if (logger.isLoggable(gestaltConfig.getLogLevelForMissingValuesWhenDefaultOrOptional())) {
String errorMsg = ErrorsUtil.buildErrorMessage("No results for Optional config path: " + combinedPath +
", and class: " + klass.getName() + " returning empty Optional", tokens.getErrors());
logger.log(DEBUG, errorMsg);
logger.log(gestaltConfig.getLogLevelForMissingValuesWhenDefaultOrOptional(), errorMsg);
}

if (failOnErrors) {
Expand Down
Loading