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

Parameterstore integration takes priority over profile specific file configuration #1296

Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,26 @@ public ParameterStoreConfigDataLoader(DeferredLogFactory logFactory) {
"io.awspring.cloud.autoconfigure.config.parameterstore.ParameterStorePropertySources");
}

private static final ConfigData.PropertySourceOptions PROFILE_SPECIFIC = ConfigData.PropertySourceOptions
.always(ConfigData.Option.PROFILE_SPECIFIC);

private static final ConfigData.PropertySourceOptions NON_PROFILE_SPECIFIC = ConfigData.PropertySourceOptions.ALWAYS_NONE;

@Override
@Nullable
public ConfigData load(ConfigDataLoaderContext context, ParameterStoreConfigDataResource resource) {
try {

ConfigData.PropertySourceOptions options = (resource.getProfile() != null) ? PROFILE_SPECIFIC
: NON_PROFILE_SPECIFIC;
// resource is disabled if parameter store integration is disabled via
// spring.cloud.aws.parameterstore.enabled=false
if (resource.isEnabled()) {
SsmClient ssm = context.getBootstrapContext().get(SsmClient.class);
ParameterStorePropertySource propertySource = resource.getPropertySources()
.createPropertySource(resource.getContext(), resource.isOptional(), ssm);
if (propertySource != null) {
return new ConfigData(Collections.singletonList(propertySource));
return new ConfigData(Collections.singletonList(propertySource), options);
}
else {
return null;
Expand All @@ -64,7 +72,8 @@ public ConfigData load(ConfigDataLoaderContext context, ParameterStoreConfigData
else {
// create dummy empty config data
return new ConfigData(
Collections.singletonList(new MapPropertySource("aws-parameterstore:" + context, Map.of())));
Collections.singletonList(new MapPropertySource("aws-parameterstore:" + context, Map.of())),
options);
}
}
catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.logging.DeferredLogFactory;
import org.springframework.lang.Nullable;
import software.amazon.awssdk.services.ssm.SsmClient;
import software.amazon.awssdk.services.ssm.SsmClientBuilder;

Expand Down Expand Up @@ -63,26 +64,19 @@ protected String getPrefix() {
public List<ParameterStoreConfigDataResource> resolveProfileSpecific(
ConfigDataLocationResolverContext resolverContext, ConfigDataLocation location, Profiles profiles)
throws ConfigDataLocationNotFoundException {
return resolveLocations(resolverContext, location, profiles);
}

private List<ParameterStoreConfigDataResource> resolveLocations(ConfigDataLocationResolverContext resolverContext,
ConfigDataLocation location, @Nullable Profiles profiles) {
var properties = loadProperties(resolverContext.getBinder());
List<ParameterStoreConfigDataResource> locations = new ArrayList<>();
ParameterStorePropertySources sources = new ParameterStorePropertySources();
List<String> contexts = getCustomContexts(location.getNonPrefixedValue(PREFIX));

if (properties.isEnabled()) {
registerBean(resolverContext, AwsProperties.class, loadAwsProperties(resolverContext.getBinder()));
registerBean(resolverContext, ParameterStoreProperties.class, properties);
registerBean(resolverContext, CredentialsProperties.class,
loadCredentialsProperties(resolverContext.getBinder()));
registerBean(resolverContext, RegionProperties.class, loadRegionProperties(resolverContext.getBinder()));

registerAndPromoteBean(resolverContext, SsmClient.class, this::createSimpleSystemManagementClient);
contexts.forEach(propertySourceContext -> locations
.add(new ParameterStoreConfigDataResource(propertySourceContext, location.isOptional(), sources)));

if (!location.isOptional() && locations.isEmpty()) {
throw new ParameterStoreKeysMissingException(
"No Parameter Store keys provided in `spring.config.import=aws-parameterstore:` configuration.");
}
registerBeans(resolverContext, properties);
populateContext(location, contexts, locations, sources, profiles);
}
else {
// create dummy resources with enabled flag set to false,
Expand All @@ -94,6 +88,41 @@ public List<ParameterStoreConfigDataResource> resolveProfileSpecific(
return locations;
}

private static void populateContext(ConfigDataLocation location, List<String> contexts,
List<ParameterStoreConfigDataResource> locations, ParameterStorePropertySources sources,
@Nullable Profiles profiles) {
if (profiles != null) {
for (String profile : profiles) {
populate(location, contexts, locations, sources, profile);
}
}
else {
populate(location, contexts, locations, sources, null);
}
}

private static void populate(ConfigDataLocation location, List<String> contexts,
List<ParameterStoreConfigDataResource> locations, ParameterStorePropertySources sources,
@Nullable String profile) {
contexts.forEach(
propertySourceContext -> locations.add(new ParameterStoreConfigDataResource(propertySourceContext,
location.isOptional(), true, sources, profile)));
if (!location.isOptional() && locations.isEmpty()) {
throw new ParameterStoreKeysMissingException(
"No Parameter Store keys provided in `spring.config.import=aws-parameterstore:` configuration.");
}
}

void registerBeans(ConfigDataLocationResolverContext resolverContext, ParameterStoreProperties properties) {
registerBean(resolverContext, AwsProperties.class, loadAwsProperties(resolverContext.getBinder()));
registerBean(resolverContext, ParameterStoreProperties.class, properties);
registerBean(resolverContext, CredentialsProperties.class,
loadCredentialsProperties(resolverContext.getBinder()));
registerBean(resolverContext, RegionProperties.class, loadRegionProperties(resolverContext.getBinder()));

registerAndPromoteBean(resolverContext, SsmClient.class, this::createSimpleSystemManagementClient);
}

protected SsmClient createSimpleSystemManagementClient(BootstrapContext context) {
SsmClientBuilder builder = configure(SsmClient.builder(), context.get(ParameterStoreProperties.class), context);
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public class ParameterStoreConfigDataResource extends ConfigDataResource {

private final boolean optional;

private final String profile;

/**
* If resource should be resolved. This flag has the same value as {@link ParameterStoreProperties#isEnabled()}.
*/
Expand All @@ -40,18 +42,28 @@ public class ParameterStoreConfigDataResource extends ConfigDataResource {
private final ParameterStorePropertySources propertySources;

public ParameterStoreConfigDataResource(String context, boolean optional, boolean enabled,
ParameterStorePropertySources propertySources) {
ParameterStorePropertySources propertySources, String profile) {
this.context = context;
this.optional = optional;
this.enabled = enabled;
this.propertySources = propertySources;
this.profile = profile;
}

public ParameterStoreConfigDataResource(String context, boolean optional, boolean enabled,
ParameterStorePropertySources propertySources) {
this(context, optional, enabled, propertySources, null);
}

public ParameterStoreConfigDataResource(String context, boolean optional,
ParameterStorePropertySources propertySources) {
this(context, optional, true, propertySources);
}

public String getProfile() {
return profile;
}

/**
* Returns context which is equal to Parameter Store parameter name.
* @return the context
Expand Down
Loading