Skip to content
This repository was archived by the owner on Jan 19, 2022. It is now read-only.

Commit 69628d2

Browse files
Fix StackResourceRegistry creation when CloudFormation support is turned off.
Fixes gh-496
1 parent 762a73c commit 69628d2

File tree

5 files changed

+128
-34
lines changed

5 files changed

+128
-34
lines changed

docs/src/main/asciidoc/_configprops.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@
2626
|cloud.aws.region.static | |
2727
|cloud.aws.region.use-default-aws-region-chain | false | Whether default AWS SDK region provider chain should be used when auto is set to true.
2828
|cloud.aws.stack.auto | true | Enables the automatic stack name detection for the application.
29-
|cloud.aws.stack.name | myStackName | The name of the manually configured stack name that will be used to retrieve the resources.
29+
|cloud.aws.stack.name | | The name of the manually configured stack name that will be used to retrieve the resources.
3030

3131
|===

spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/context/ContextStackAutoConfiguration.java

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,33 +22,38 @@
2222
import com.amazonaws.services.ec2.AmazonEC2;
2323

2424
import org.springframework.beans.factory.annotation.Autowired;
25+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
2526
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2627
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
28+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
29+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
30+
import org.springframework.cloud.aws.autoconfigure.context.properties.AwsStackProperties;
2731
import org.springframework.cloud.aws.context.annotation.ConditionalOnMissingAmazonClient;
2832
import org.springframework.cloud.aws.context.config.annotation.ContextDefaultConfigurationRegistrar;
2933
import org.springframework.cloud.aws.core.config.AmazonWebserviceClientFactoryBean;
3034
import org.springframework.cloud.aws.core.env.stack.StackResourceRegistry;
3135
import org.springframework.cloud.aws.core.env.stack.config.AutoDetectingStackNameProvider;
36+
import org.springframework.cloud.aws.core.env.stack.config.StackNameProvider;
3237
import org.springframework.cloud.aws.core.env.stack.config.StackResourceRegistryFactoryBean;
3338
import org.springframework.cloud.aws.core.env.stack.config.StaticStackNameProvider;
3439
import org.springframework.cloud.aws.core.region.RegionProvider;
3540
import org.springframework.context.annotation.Bean;
3641
import org.springframework.context.annotation.Configuration;
3742
import org.springframework.context.annotation.Import;
38-
import org.springframework.core.env.Environment;
39-
import org.springframework.util.StringUtils;
4043

4144
/**
4245
* @author Agim Emruli
46+
* @author Maciej Walkowiak
4347
*/
4448
@Configuration(proxyBeanMethods = false)
4549
@Import({ ContextCredentialsAutoConfiguration.class,
4650
ContextDefaultConfigurationRegistrar.class })
4751
@ConditionalOnClass(name = "com.amazonaws.services.cloudformation.AmazonCloudFormation")
52+
@EnableConfigurationProperties(AwsStackProperties.class)
4853
public class ContextStackAutoConfiguration {
4954

5055
@Autowired
51-
private Environment environment;
56+
private AwsStackProperties properties;
5257

5358
@Autowired(required = false)
5459
private AmazonEC2 amazonEC2;
@@ -60,24 +65,29 @@ public class ContextStackAutoConfiguration {
6065
private AWSCredentialsProvider credentialsProvider;
6166

6267
@Bean
63-
@ConditionalOnMissingBean(StackResourceRegistry.class)
64-
public StackResourceRegistryFactoryBean stackResourceRegistryFactoryBean(
65-
AmazonCloudFormation amazonCloudFormation) {
66-
67-
if (StringUtils.hasText(environment.getProperty("cloud.aws.stack.name"))) {
68-
return new StackResourceRegistryFactoryBean(amazonCloudFormation,
69-
new StaticStackNameProvider(
70-
this.environment.getProperty("cloud.aws.stack.name")));
71-
}
68+
@ConditionalOnMissingBean
69+
@ConditionalOnProperty("cloud.aws.stack.name")
70+
public StackNameProvider staticStackNameProvider() {
71+
return new StaticStackNameProvider(properties.getName());
72+
}
7273

73-
if (environment.getProperty("cloud.aws.stack.auto") == null || "true"
74-
.equalsIgnoreCase(environment.getProperty("cloud.aws.stack.auto"))) {
75-
return new StackResourceRegistryFactoryBean(amazonCloudFormation,
76-
new AutoDetectingStackNameProvider(amazonCloudFormation,
77-
this.amazonEC2));
78-
}
74+
@Bean
75+
@ConditionalOnMissingBean
76+
@ConditionalOnProperty(name = "cloud.aws.stack.auto", havingValue = "true",
77+
matchIfMissing = true)
78+
public StackNameProvider autoDetectingStackNameProvider(
79+
AmazonCloudFormation amazonCloudFormation) {
80+
return new AutoDetectingStackNameProvider(amazonCloudFormation, this.amazonEC2);
81+
}
7982

80-
return null;
83+
@Bean
84+
@ConditionalOnMissingBean(StackResourceRegistry.class)
85+
@ConditionalOnBean(StackNameProvider.class)
86+
public StackResourceRegistryFactoryBean stackResourceRegistryFactoryBean(
87+
AmazonCloudFormation amazonCloudFormation,
88+
StackNameProvider stackNameProvider) {
89+
return new StackResourceRegistryFactoryBean(amazonCloudFormation,
90+
stackNameProvider);
8191
}
8292

8393
@Bean
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2013-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.aws.autoconfigure.context.properties;
18+
19+
import org.springframework.boot.context.properties.ConfigurationProperties;
20+
21+
/**
22+
* Properties related to CloudFormation stack support.
23+
*
24+
* @author Maciej Walkowiak
25+
*/
26+
@ConfigurationProperties("cloud.aws.stack")
27+
public class AwsStackProperties {
28+
29+
/**
30+
* Enables the automatic stack name detection for the application.
31+
*/
32+
private boolean auto = true;
33+
34+
/**
35+
* The name of the manually configured stack name that will be used to retrieve the
36+
* resources.
37+
*/
38+
private String name;
39+
40+
public boolean isAuto() {
41+
return auto;
42+
}
43+
44+
public void setAuto(boolean auto) {
45+
this.auto = auto;
46+
}
47+
48+
public String getName() {
49+
return name;
50+
}
51+
52+
public void setName(String name) {
53+
this.name = name;
54+
}
55+
56+
}
Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,5 @@
11
{
22
"properties": [
3-
{
4-
"defaultValue": "true",
5-
"name": "cloud.aws.stack.auto",
6-
"description": "Enables the automatic stack name detection for the application.",
7-
"type": "java.lang.Boolean"
8-
},
9-
{
10-
"defaultValue": "myStackName",
11-
"name": "cloud.aws.stack.name",
12-
"description": "The name of the manually configured stack name that will be used to retrieve the resources.",
13-
"type": "java.lang.String"
14-
},
153
{
164
"defaultValue": "",
175
"name": "management.metrics.export.cloudwatch.namespace",
@@ -25,4 +13,4 @@
2513
"type": "java.lang.Boolean"
2614
}
2715
]
28-
}
16+
}

spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/context/ContextStackAutoConfigurationTest.java

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,20 @@
3232
import org.junit.Test;
3333
import org.mockito.Mockito;
3434

35+
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
3536
import org.springframework.boot.test.util.TestPropertyValues;
3637
import org.springframework.cloud.aws.context.support.env.AwsCloudEnvironmentCheckUtils;
3738
import org.springframework.cloud.aws.core.env.ResourceIdResolver;
3839
import org.springframework.cloud.aws.core.env.stack.StackResourceRegistry;
40+
import org.springframework.cloud.aws.core.env.stack.config.AutoDetectingStackNameProvider;
41+
import org.springframework.cloud.aws.core.env.stack.config.StaticStackNameProvider;
3942
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
4043
import org.springframework.context.annotation.Bean;
4144
import org.springframework.context.annotation.Configuration;
4245
import org.springframework.util.ReflectionUtils;
4346

4447
import static org.assertj.core.api.Assertions.assertThat;
48+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
4549

4650
public class ContextStackAutoConfigurationTest {
4751

@@ -92,7 +96,8 @@ public void stackRegistry_manualConfigurationEnabled_returnsAutoConfiguredStackR
9296
this.context = new AnnotationConfigApplicationContext();
9397
this.context.register(ManualConfigurationStackRegistryTestConfiguration.class);
9498
this.context.register(ContextStackAutoConfiguration.class);
95-
TestPropertyValues.of("cloud.aws.stack.name:manualStackName")
99+
TestPropertyValues
100+
.of("cloud.aws.stack.name:manualStackName", "cloud.aws.stack.auto:true")
96101
.applyTo(this.context);
97102

98103
// Act
@@ -102,6 +107,27 @@ public void stackRegistry_manualConfigurationEnabled_returnsAutoConfiguredStackR
102107
assertThat(this.context.getBean(StackResourceRegistry.class)).isNotNull();
103108
}
104109

110+
@Test
111+
public void stackRegistry_manualConfigurationEnabledAndStackNameProvided_returnsStaticStackNameProvider()
112+
throws Exception {
113+
// Arrange
114+
this.context = new AnnotationConfigApplicationContext();
115+
this.context.register(ManualConfigurationStackRegistryTestConfiguration.class);
116+
this.context.register(ContextStackAutoConfiguration.class);
117+
TestPropertyValues
118+
.of("cloud.aws.stack.name:manualStackName", "cloud.aws.stack.auto:true")
119+
.applyTo(this.context);
120+
121+
// Act
122+
this.context.refresh();
123+
124+
// Assert
125+
assertThat(this.context.getBean(StaticStackNameProvider.class)).isNotNull();
126+
assertThatThrownBy(
127+
() -> this.context.getBean(AutoDetectingStackNameProvider.class))
128+
.isInstanceOf(NoSuchBeanDefinitionException.class);
129+
}
130+
105131
@Test
106132
public void resourceIdResolver_withoutAnyStackConfiguration_availableAsConfiguredBean()
107133
throws Exception {
@@ -118,6 +144,20 @@ public void resourceIdResolver_withoutAnyStackConfiguration_availableAsConfigure
118144
.isTrue();
119145
}
120146

147+
@Test
148+
public void stackResourceRegistryFactoryBean_isNotCreatedWhenStackNameAbsentAndStackAutoFalse() {
149+
// Arrange
150+
this.context = new AnnotationConfigApplicationContext();
151+
this.context.register(ContextStackAutoConfiguration.class);
152+
TestPropertyValues.of("cloud.aws.stack.auto:false").applyTo(this.context);
153+
// Act
154+
this.context.refresh();
155+
156+
// Assert
157+
assertThatThrownBy(() -> this.context.getBean("stackResourceRegistryFactoryBean"))
158+
.isInstanceOf(NoSuchBeanDefinitionException.class);
159+
}
160+
121161
@Configuration(proxyBeanMethods = false)
122162
static class AutoConfigurationStackRegistryTestConfiguration {
123163

0 commit comments

Comments
 (0)