Skip to content

Commit e242715

Browse files
committed
Updated using default framework
1 parent 574d4ee commit e242715

32 files changed

+1183
-965
lines changed

aws-cloudformation-stackset/aws-cloudformation-stackset.json

Lines changed: 62 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,58 @@
7474
}
7575
},
7676
"additionalProperties": false
77+
},
78+
"StackInstances": {
79+
"description": "Stack instances in some specific accounts and Regions.",
80+
"type": "object",
81+
"properties": {
82+
"DeploymentTargets": {
83+
"description": " The AWS OrganizationalUnitIds or Accounts for which to create stack instances in the specified Regions.",
84+
"type": "object",
85+
"properties": {
86+
"Accounts": {
87+
"description": "AWS accounts that you want to create stack instances in the specified Region(s) for.",
88+
"type": "array",
89+
"uniqueItems": true,
90+
"insertionOrder": false,
91+
"items": {
92+
"$ref": "#/definitions/Account"
93+
}
94+
},
95+
"OrganizationalUnitIds": {
96+
"description": "The organization root ID or organizational unit (OU) IDs to which StackSets deploys.",
97+
"type": "array",
98+
"uniqueItems": true,
99+
"insertionOrder": false,
100+
"items": {
101+
"$ref": "#/definitions/OrganizationalUnitId"
102+
}
103+
}
104+
}
105+
},
106+
"Regions": {
107+
"description": "The names of one or more Regions where you want to create stack instances using the specified AWS account(s).",
108+
"type": "array",
109+
"uniqueItems": true,
110+
"insertionOrder": false,
111+
"items": {
112+
"$ref": "#/definitions/Region"
113+
}
114+
},
115+
"ParameterOverrides": {
116+
"description": "A list of stack set parameters whose values you want to override in the selected stack instances.",
117+
"type": "array",
118+
"uniqueItems": true,
119+
"insertionOrder": false,
120+
"items": {
121+
"$ref": "#/definitions/Parameter"
122+
}
123+
}
124+
},
125+
"required": [
126+
"DeploymentTargets",
127+
"Regions"
128+
]
77129
}
78130
},
79131
"properties": {
@@ -100,30 +152,6 @@
100152
"$ref": "#/definitions/Capability"
101153
}
102154
},
103-
"DeploymentTargets": {
104-
"description": "",
105-
"type": "object",
106-
"properties": {
107-
"Accounts" : {
108-
"description": "AWS accounts that you want to create stack instances in the specified Region(s) for.",
109-
"type": "array",
110-
"uniqueItems": true,
111-
"insertionOrder": false,
112-
"items": {
113-
"$ref": "#/definitions/Account"
114-
}
115-
},
116-
"OrganizationalUnitIds": {
117-
"description": "The organization root ID or organizational unit (OU) IDs to which StackSets deploys.",
118-
"type": "array",
119-
"uniqueItems": true,
120-
"insertionOrder": false,
121-
"items": {
122-
"$ref": "#/definitions/OrganizationalUnitId"
123-
}
124-
}
125-
}
126-
},
127155
"Description": {
128156
"description": "A description of the stack set. You can use the description to identify the stack set's purpose or other important information.",
129157
"type": "string",
@@ -166,6 +194,15 @@
166194
}
167195
}
168196
},
197+
"StackInstancesGroup": {
198+
"description": "",
199+
"type": "array",
200+
"uniqueItems": true,
201+
"insertionOrder": false,
202+
"items": {
203+
"$ref": "#/definitions/StackInstances"
204+
}
205+
},
169206
"Parameters": {
170207
"description": "The input parameters for the stack set template.",
171208
"type": "array",
@@ -183,15 +220,6 @@
183220
"SELF_MANAGED"
184221
]
185222
},
186-
"Regions": {
187-
"description": "The names of one or more Regions where you want to create stack instances using the specified AWS account(s).",
188-
"type": "array",
189-
"uniqueItems": true,
190-
"insertionOrder": false,
191-
"items": {
192-
"$ref": "#/definitions/Region"
193-
}
194-
},
195223
"Tags": {
196224
"description": "The key-value pairs to associate with this stack set and the stacks created from it. AWS CloudFormation also propagates these tags to supported resources that are created in the stacks. A maximum number of 50 tags can be specified.",
197225
"type": "array",
@@ -216,8 +244,7 @@
216244
}
217245
},
218246
"required": [
219-
"PermissionModel",
220-
"Regions"
247+
"PermissionModel"
221248
],
222249
"additionalProperties": false,
223250
"createOnlyProperties": [

aws-cloudformation-stackset/src/main/java/software/amazon/cloudformation/stackset/CallbackContext.java

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
66
import lombok.Builder;
77
import lombok.Data;
8-
import software.amazon.cloudformation.stackset.util.EnumUtils.UpdateOperations;
8+
import software.amazon.cloudformation.stackset.util.EnumUtils.Operations;
99

1010
import java.util.Arrays;
11+
import java.util.LinkedList;
1112
import java.util.Map;
13+
import java.util.Queue;
1214
import java.util.stream.Collectors;
1315

1416
@Data
@@ -19,34 +21,42 @@ public class CallbackContext {
1921
// Operation Id to verify stabilization for StackSet operation.
2022
private String operationId;
2123

22-
// Elapsed counts of retries on specific exceptions.
23-
private int retries;
24+
// Indicates initiation of analyzing template.
25+
private boolean templateAnalyzed;
2426

2527
// Indicates initiation of resource stabilization.
26-
private boolean stabilizationStarted;
28+
private boolean stackSetCreated;
2729

2830
// Indicates initiation of stack instances creation.
29-
private boolean addStacksByRegionsStarted;
30-
31-
// Indicates initiation of stack instances creation.
32-
private boolean addStacksByTargetsStarted;
33-
34-
// Indicates initiation of stack instances delete.
35-
private boolean deleteStacksByRegionsStarted;
31+
private boolean addStacksStarted;
3632

3733
// Indicates initiation of stack instances delete.
38-
private boolean deleteStacksByTargetsStarted;
34+
private boolean deleteStacksStarted;
3935

4036
// Indicates initiation of stack set update.
4137
private boolean updateStackSetStarted;
4238

4339
// Indicates initiation of stack instances update.
44-
private boolean updateStackInstancesStarted;
40+
private boolean updateStacksStarted;
4541

4642
// Total running time
4743
@Builder.Default
4844
private int elapsedTime = 0;
4945

46+
private StackInstances stackInstancesInOperation;
47+
48+
// List to keep track on the complete status for creating
49+
@Builder.Default
50+
private Queue<StackInstances> createStacksQueue = new LinkedList<>();
51+
52+
// List to keep track on stack instances for deleting
53+
@Builder.Default
54+
private Queue<StackInstances> deleteStacksQueue = new LinkedList<>();
55+
56+
// List to keep track on stack instances for update
57+
@Builder.Default
58+
private Queue<StackInstances> updateStacksQueue = new LinkedList<>();
59+
5060
/**
5161
* Default as 0, will be {@link software.amazon.cloudformation.stackset.util.Stabilizer#BASE_CALLBACK_DELAY_SECONDS}
5262
* When it enters the first IN_PROGRESS callback
@@ -55,14 +65,9 @@ public class CallbackContext {
5565

5666
// Map to keep track on the complete status for operations in Update
5767
@Builder.Default
58-
private Map<UpdateOperations, Boolean> operationsStabilizationMap = Arrays.stream(UpdateOperations.values())
68+
private Map<Operations, Boolean> operationsStabilizationMap = Arrays.stream(Operations.values())
5969
.collect(Collectors.toMap(e -> e, e -> false));
6070

61-
@JsonIgnore
62-
public void incrementRetryCounter() {
63-
retries++;
64-
}
65-
6671
/**
6772
* Increments {@link CallbackContext#elapsedTime} and returns the total elapsed time
6873
* @return {@link CallbackContext#getElapsedTime()} after incrementing
@@ -72,8 +77,4 @@ public int incrementElapsedTime() {
7277
elapsedTime = elapsedTime + currentDelaySeconds;
7378
return elapsedTime;
7479
}
75-
76-
@JsonPOJOBuilder(withPrefix = "")
77-
public static class CallbackContextBuilder {
78-
}
7980
}
Lines changed: 34 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,62 @@
11
package software.amazon.cloudformation.stackset;
22

3-
import lombok.AllArgsConstructor;
4-
import lombok.Builder;
5-
import lombok.NoArgsConstructor;
63
import software.amazon.awssdk.services.cloudformation.CloudFormationClient;
74
import software.amazon.awssdk.services.cloudformation.model.AlreadyExistsException;
8-
import software.amazon.awssdk.services.cloudformation.model.CreateStackInstancesResponse;
95
import software.amazon.awssdk.services.cloudformation.model.CreateStackSetResponse;
106
import software.amazon.awssdk.services.cloudformation.model.InsufficientCapabilitiesException;
117
import software.amazon.awssdk.services.cloudformation.model.LimitExceededException;
12-
import software.amazon.awssdk.services.cloudformation.model.OperationInProgressException;
13-
import software.amazon.awssdk.services.cloudformation.model.StackSetNotFoundException;
148
import software.amazon.cloudformation.exceptions.CfnAlreadyExistsException;
159
import software.amazon.cloudformation.exceptions.CfnInvalidRequestException;
16-
import software.amazon.cloudformation.exceptions.CfnNotFoundException;
1710
import software.amazon.cloudformation.exceptions.CfnServiceLimitExceededException;
1811
import software.amazon.cloudformation.proxy.AmazonWebServicesClientProxy;
1912
import software.amazon.cloudformation.proxy.Logger;
2013
import software.amazon.cloudformation.proxy.ProgressEvent;
2114
import software.amazon.cloudformation.proxy.ResourceHandlerRequest;
2215
import software.amazon.cloudformation.stackset.util.ClientBuilder;
16+
import software.amazon.cloudformation.stackset.util.InstancesAnalyzer;
17+
import software.amazon.cloudformation.stackset.util.OperationOperator;
2318
import software.amazon.cloudformation.stackset.util.PhysicalIdGenerator;
2419
import software.amazon.cloudformation.stackset.util.Stabilizer;
2520
import software.amazon.cloudformation.stackset.util.Validator;
2621

27-
import static software.amazon.cloudformation.stackset.translator.RequestTranslator.createStackInstancesRequest;
2822
import static software.amazon.cloudformation.stackset.translator.RequestTranslator.createStackSetRequest;
23+
import static software.amazon.cloudformation.stackset.util.Comparator.isAddingStackInstances;
24+
import static software.amazon.cloudformation.stackset.util.EnumUtils.Operations.ADD_INSTANCES;
2925
import static software.amazon.cloudformation.stackset.util.Stabilizer.getDelaySeconds;
3026

31-
@Builder
32-
@NoArgsConstructor
33-
@AllArgsConstructor
3427
public class CreateHandler extends BaseHandler<CallbackContext> {
3528

36-
private AmazonWebServicesClientProxy proxy;
37-
private ResourceModel model;
38-
private CloudFormationClient client;
39-
private CallbackContext context;
40-
private Logger logger;
41-
private Stabilizer stabilizer;
42-
43-
@Builder.Default
44-
private Validator validator = new Validator();
45-
4629
@Override
4730
public ProgressEvent<ResourceModel, CallbackContext> handleRequest(
4831
final AmazonWebServicesClientProxy proxy,
4932
final ResourceHandlerRequest<ResourceModel> request,
5033
final CallbackContext callbackContext,
5134
final Logger logger) {
5235

53-
this.context = callbackContext == null ? CallbackContext.builder().build() : callbackContext;
54-
this.model = request.getDesiredResourceState();
55-
this.logger = logger;
56-
this.proxy = proxy;
57-
this.client = ClientBuilder.getClient();
58-
this.stabilizer = Stabilizer.builder().proxy(proxy).client(client).logger(logger).build();
36+
final CallbackContext context = callbackContext == null ? CallbackContext.builder().build() : callbackContext;
37+
final ResourceModel model = request.getDesiredResourceState();
38+
final CloudFormationClient client = ClientBuilder.getClient();
39+
final Stabilizer stabilizer = Stabilizer.builder().proxy(proxy).client(client).logger(logger).build();
40+
final OperationOperator operator = OperationOperator.builder()
41+
.client(client).desiredModel(model)
42+
.logger(logger).proxy(proxy).context(context)
43+
.build();
44+
InstancesAnalyzer.builder().desiredModel(model).build().analyzeForCreate(context);
5945

6046
// Create a resource when a creation has not initialed
61-
if (!context.isStabilizationStarted()) {
62-
validator.validateTemplate(proxy, model.getTemplateBody(), model.getTemplateURL(), logger);
47+
if (!context.isStackSetCreated()) {
48+
new Validator().validateTemplate(proxy, model.getTemplateBody(), model.getTemplateURL(), logger);
6349
final String stackSetName = PhysicalIdGenerator.generatePhysicalId(request);
64-
createStackSet(stackSetName, request.getClientRequestToken());
50+
createStackSet(proxy, model, logger, client, context, stackSetName, request.getClientRequestToken());
51+
}
52+
53+
if (stabilizer.isPerformingOperation(isAddingStackInstances(context), context.isAddStacksStarted(), null,
54+
ADD_INSTANCES, context.getCreateStacksQueue(), model, context)) {
6555

66-
} else if (stabilizer.isStabilized(model, context)) {
56+
operator.updateStackSet(ADD_INSTANCES);
57+
}
58+
59+
if (context.getOperationsStabilizationMap().get(ADD_INSTANCES)) {
6760
return ProgressEvent.defaultSuccessHandler(model);
6861
}
6962

@@ -73,15 +66,22 @@ public ProgressEvent<ResourceModel, CallbackContext> handleRequest(
7366
model);
7467
}
7568

76-
private void createStackSet(final String stackSetName, final String requestToken) {
69+
private void createStackSet(
70+
final AmazonWebServicesClientProxy proxy,
71+
final ResourceModel model,
72+
final Logger logger,
73+
final CloudFormationClient client,
74+
final CallbackContext context,
75+
final String stackSetName,
76+
final String requestToken) {
77+
7778
try {
7879
final CreateStackSetResponse response = proxy.injectCredentialsAndInvokeV2(
7980
createStackSetRequest(model, stackSetName, requestToken), client::createStackSet);
8081
model.setStackSetId(response.stackSetId());
8182

8283
logger.log(String.format("%s [%s] StackSet creation succeeded", ResourceModel.TYPE_NAME, stackSetName));
83-
84-
createStackInstances(stackSetName);
84+
context.setStackSetCreated(true);
8585

8686
} catch (final AlreadyExistsException e) {
8787
throw new CfnAlreadyExistsException(e);
@@ -93,25 +93,4 @@ private void createStackSet(final String stackSetName, final String requestToken
9393
throw new CfnInvalidRequestException(e);
9494
}
9595
}
96-
97-
private void createStackInstances(final String stackSetName) {
98-
try {
99-
final CreateStackInstancesResponse response = proxy.injectCredentialsAndInvokeV2(
100-
createStackInstancesRequest(stackSetName, model.getOperationPreferences(),
101-
model.getDeploymentTargets(), model.getRegions()),
102-
client::createStackInstances);
103-
104-
logger.log(String.format("%s [%s] stack instances creation initiated",
105-
ResourceModel.TYPE_NAME, stackSetName));
106-
107-
context.setStabilizationStarted(true);
108-
context.setOperationId(response.operationId());
109-
110-
} catch (final StackSetNotFoundException e) {
111-
throw new CfnNotFoundException(e);
112-
113-
} catch (final OperationInProgressException e) {
114-
context.incrementRetryCounter();
115-
}
116-
}
11796
}

0 commit comments

Comments
 (0)