2
2
3
3
import static software .amazon .transfer .server .translators .ResourceModelAdapter .prepareDesiredResourceModel ;
4
4
import static software .amazon .transfer .server .translators .ResourceModelAdapter .preparePreviousResourceModel ;
5
+ import static software .amazon .transfer .server .translators .Translator .emptyListIfNull ;
6
+ import static software .amazon .transfer .server .translators .Translator .emptyStringIfNull ;
5
7
import static software .amazon .transfer .server .translators .Translator .translateToSdkProtocols ;
6
8
9
+ import java .util .ArrayList ;
7
10
import java .util .Collection ;
8
11
import java .util .Collections ;
9
- import java .util .HashSet ;
10
12
import java .util .List ;
11
13
import java .util .Map ;
12
14
import java .util .Objects ;
13
- import java .util .Optional ;
14
15
import java .util .Set ;
15
16
16
17
import org .apache .commons .lang3 .StringUtils ;
@@ -58,7 +59,7 @@ protected ProgressEvent<ResourceModel, CallbackContext> handleRequest(
58
59
Translator .ensureServerIdInModel (oldModel );
59
60
Translator .ensureServerIdInModel (newModel );
60
61
61
- prepareDesiredResourceModel (request , newModel );
62
+ prepareDesiredResourceModel (request , newModel , false );
62
63
preparePreviousResourceModel (request , oldModel );
63
64
64
65
return ProgressEvent .progress (request .getDesiredResourceState (), callbackContext )
@@ -101,13 +102,21 @@ private Boolean stabilizeAfterUpdate(
101
102
String serverId = model .getServerId ();
102
103
DescribedServer describedServer = describeServer (client , model );
103
104
105
+ // Always check if the VPC endpoint is ready to modify
106
+ if (EndpointType .VPC .equals (describedServer .endpointType ())) {
107
+ String vpcEndpointId = describedServer .endpointDetails ().vpcEndpointId ();
108
+ if (!waitForVpcEndpoint (vpcEndpointId , ec2Client , model )) {
109
+ return false ;
110
+ }
111
+ }
112
+
104
113
List <String > proposedSubnetIds ;
105
114
List <String > proposedAddressAllocationIds ;
106
115
107
116
if (model .getEndpointDetails () != null ) {
108
- proposedSubnetIds = nullableList (model .getEndpointDetails ().getSubnetIds ());
117
+ proposedSubnetIds = emptyListIfNull (model .getEndpointDetails ().getSubnetIds ());
109
118
proposedAddressAllocationIds =
110
- nullableList (model .getEndpointDetails ().getAddressAllocationIds ());
119
+ emptyListIfNull (model .getEndpointDetails ().getAddressAllocationIds ());
111
120
} else {
112
121
proposedSubnetIds = Collections .emptyList ();
113
122
proposedAddressAllocationIds = Collections .emptyList ();
@@ -124,15 +133,23 @@ private Boolean stabilizeAfterUpdate(
124
133
currentAddressAllocationIds = Collections .emptyList ();
125
134
}
126
135
136
+ log (String .format ("Endpoint current subnet IDs: %s" , currentSubnetIds ), serverId );
137
+ log (String .format ("Endpoint proposed subnet IDs: %s" , proposedSubnetIds ), serverId );
138
+ log (String .format ("Endpoint current address allocation IDs: %s" , currentAddressAllocationIds ), serverId );
139
+ log (String .format ("Endpoint proposed address allocation IDs: %s" , proposedAddressAllocationIds ), serverId );
140
+
127
141
State state = describedServer .state ();
128
142
switch (state ) {
129
143
case OFFLINE :
130
144
if (!Objects .equals (proposedSubnetIds , currentSubnetIds )) {
131
- EndpointDetails removeAddressAllocationIds = EndpointDetails .builder ()
132
- .addressAllocationIds (Collections .emptyList ())
133
- .build ();
134
- updateServerEndpointDetails (client , serverId , removeAddressAllocationIds );
135
-
145
+ if (!currentAddressAllocationIds .isEmpty ()) {
146
+ EndpointDetails removeAddressAllocationIds = EndpointDetails .builder ()
147
+ .addressAllocationIds (Collections .emptyList ())
148
+ .build ();
149
+ log ("EIP address allocation IDs are removed for subnet update." , serverId );
150
+ updateServerEndpointDetails (client , serverId , removeAddressAllocationIds );
151
+ return false ;
152
+ }
136
153
EndpointDetails updateSubnets = EndpointDetails .builder ()
137
154
.subnetIds (proposedSubnetIds )
138
155
.build ();
@@ -151,8 +168,7 @@ private Boolean stabilizeAfterUpdate(
151
168
return false ;
152
169
}
153
170
154
- if (!currentAddressAllocationIds .isEmpty ()
155
- && !privateIpsAvailable (currentAddressAllocationIds , ec2Client )) {
171
+ if (!privateIpsAvailable (currentAddressAllocationIds , ec2Client )) {
156
172
log ("is waiting for endpoint private IPs" , serverId );
157
173
return false ;
158
174
}
@@ -161,14 +177,8 @@ private Boolean stabilizeAfterUpdate(
161
177
log ("is going ONLINE after update." , serverId );
162
178
return false ;
163
179
case ONLINE :
164
- if (EndpointType .VPC .equals (describedServer .endpointType ())) {
165
- String vpcEndpointId = describedServer .endpointDetails ().vpcEndpointId ();
166
- if (!waitForVpcEndpoint (vpcEndpointId , ec2Client , model )) {
167
- return false ;
168
- }
169
- }
170
-
171
- if (Objects .equals (proposedAddressAllocationIds , currentAddressAllocationIds )) {
180
+ if (Objects .equals (proposedSubnetIds , currentSubnetIds )
181
+ && Objects .equals (proposedAddressAllocationIds , currentAddressAllocationIds )) {
172
182
log ("update has been stabilized." , serverId );
173
183
return true ; // no update needed, we are done
174
184
}
@@ -182,10 +192,6 @@ private Boolean stabilizeAfterUpdate(
182
192
}
183
193
}
184
194
185
- private List <String > nullableList (List <String > subnetIds ) {
186
- return Optional .ofNullable (subnetIds ).orElse (Collections .emptyList ());
187
- }
188
-
189
195
private ProgressEvent <ResourceModel , CallbackContext > updateSecurityGroups (
190
196
ProgressEvent <ResourceModel , CallbackContext > progress ,
191
197
ResourceModel oldModel ,
@@ -201,52 +207,57 @@ private ProgressEvent<ResourceModel, CallbackContext> updateSecurityGroups(
201
207
return progress ; // skip this step
202
208
}
203
209
204
- Set <String > sgIdSet = new HashSet <> ();
205
- Set <String > prevSgIdSet = new HashSet <> ();
210
+ List <String > requested = List . of ();
211
+ List <String > previous = List . of ();
206
212
if (isVpcServerEndpoint (oldModel )) {
207
- prevSgIdSet = new HashSet <>(
208
- Optional .ofNullable (oldModel .getEndpointDetails ().getSecurityGroupIds ())
209
- .orElse (Collections .emptyList ()));
213
+ previous = emptyListIfNull (oldModel .getEndpointDetails ().getSecurityGroupIds ());
210
214
}
211
215
if (isVpcServerEndpoint (newModel )) {
212
- sgIdSet = new HashSet <>(
213
- Optional .ofNullable (newModel .getEndpointDetails ().getSecurityGroupIds ())
214
- .orElse (Collections .emptyList ()));
215
- ;
216
+ requested = emptyListIfNull (newModel .getEndpointDetails ().getSecurityGroupIds ());
216
217
}
217
218
218
- Set <String > sgIdsToAdd = new HashSet <>(sgIdSet );
219
- sgIdsToAdd .removeAll (prevSgIdSet );
220
- Set <String > sgIdsToRemove = new HashSet <>(prevSgIdSet );
221
- sgIdsToRemove .removeAll (sgIdSet );
219
+ List <String > toAdd = new ArrayList <>(requested );
220
+ toAdd .removeAll (previous );
221
+ List <String > toRemove = new ArrayList <>(previous );
222
+ toRemove .removeAll (requested );
222
223
223
- if (sgIdsToAdd .isEmpty () && sgIdsToRemove .isEmpty ()) {
224
+ String serverId = newModel .getServerId ();
225
+ if (toAdd .isEmpty () && toRemove .isEmpty ()) {
226
+ log ("VPC endpoint has no modifications for security groups" , serverId );
224
227
return progress ; // skip this step
225
228
}
226
229
230
+ if (!toAdd .isEmpty ()) {
231
+ log (String .format ("security group IDs to add: %s" , toAdd ), serverId );
232
+ }
233
+ if (!toRemove .isEmpty ()) {
234
+ log (String .format ("security group IDs to remove: %s" , toRemove ), serverId );
235
+ }
236
+
227
237
return proxy .initiate (
228
238
"AWS-Transfer-Server::Update::updateSecurityGroups" ,
229
239
proxyEc2Client ,
230
240
progress .getResourceModel (),
231
241
progress .getCallbackContext ())
232
- .translateToServiceRequest (m -> modifyVpcEndpointRequest (vpcEndpointId , sgIdsToAdd , sgIdsToRemove ))
233
- .makeServiceCall ((awsRequest , client ) -> {
234
- try (Ec2Client ec2Client = client .client ()) {
235
- ModifyVpcEndpointResponse awsResponse =
236
- client .injectCredentialsAndInvokeV2 (awsRequest , ec2Client ::modifyVpcEndpoint );
237
- log (
238
- "VPC Endpoint has successfully been updated." ,
239
- progress .getResourceModel ().getServerId ());
240
- return awsResponse ;
241
- }
242
- })
242
+ .translateToServiceRequest (m -> modifyVpcEndpointRequest (vpcEndpointId , toAdd , toRemove ))
243
+ .makeServiceCall ((awsRequest , client ) -> modifyVpcEndpoint (serverId , awsRequest , client ))
243
244
.stabilize ((awsRequest , awsResponse , client , model , context ) ->
244
245
waitForVpcEndpoint (awsRequest .vpcEndpointId (), client , model ))
245
246
.handleError ((ignored , exception , proxyClient1 , model1 , callbackContext1 ) ->
246
247
handleError (UPDATE , exception , model1 , callbackContext1 , clientRequestToken ))
247
248
.progress ();
248
249
}
249
250
251
+ private ModifyVpcEndpointResponse modifyVpcEndpoint (
252
+ String serverId , ModifyVpcEndpointRequest awsRequest , ProxyClient <Ec2Client > client ) {
253
+ try (Ec2Client ec2Client = client .client ()) {
254
+ ModifyVpcEndpointResponse awsResponse =
255
+ client .injectCredentialsAndInvokeV2 (awsRequest , ec2Client ::modifyVpcEndpoint );
256
+ log ("VPC Endpoint has been updated successfully." , serverId );
257
+ return awsResponse ;
258
+ }
259
+ }
260
+
250
261
private Boolean waitForVpcEndpoint (String vpcEndpointId , ProxyClient <Ec2Client > client , ResourceModel model ) {
251
262
if (!isVpcEndpointAvailable (vpcEndpointId , client )) {
252
263
log ("VPC Endpoint is not available yet." , model .getServerId ());
@@ -298,14 +309,14 @@ private UpdateServerRequest translateToFirstUpdateRequest(final ResourceModel ol
298
309
.endpointType (endpointType )
299
310
.endpointDetails (endpointDetails )
300
311
.identityProviderDetails (identityProviderDetails )
301
- .loggingRole (newModel .getLoggingRole ())
302
- .preAuthenticationLoginBanner (newModel .getPreAuthenticationLoginBanner ())
303
- .postAuthenticationLoginBanner (newModel .getPostAuthenticationLoginBanner ())
312
+ .loggingRole (emptyStringIfNull ( newModel .getLoggingRole () ))
313
+ .preAuthenticationLoginBanner (emptyStringIfNull ( newModel .getPreAuthenticationLoginBanner () ))
314
+ .postAuthenticationLoginBanner (emptyStringIfNull ( newModel .getPostAuthenticationLoginBanner () ))
304
315
.protocols (translateToSdkProtocols (newModel .getProtocols ()))
305
316
.protocolDetails (ProtocolDetailsTranslator .toSdk (newModel .getProtocolDetails ()))
306
317
.securityPolicyName (newModel .getSecurityPolicyName ())
307
318
.serverId (newModel .getServerId ())
308
- .structuredLogDestinations (newModel .getStructuredLogDestinations ())
319
+ .structuredLogDestinations (emptyListIfNull ( newModel .getStructuredLogDestinations () ))
309
320
.workflowDetails (WorkflowDetailsTranslator .toSdk (newModel .getWorkflowDetails (), true ))
310
321
.s3StorageOptions (S3StorageOptionsTranslator .toSdk (newModel .getS3StorageOptions ()))
311
322
.build ();
@@ -335,12 +346,15 @@ private UpdateServerResponse updateServer(UpdateServerRequest awsRequest, ProxyC
335
346
}
336
347
337
348
private ModifyVpcEndpointRequest modifyVpcEndpointRequest (
338
- String vpcEndpointId , Set <String > sgIdsToAdd , Set <String > sgIdsToRemove ) {
339
- return ModifyVpcEndpointRequest .builder ()
340
- .vpcEndpointId (vpcEndpointId )
341
- .addSecurityGroupIds (sgIdsToAdd )
342
- .removeSecurityGroupIds (sgIdsToRemove )
343
- .build ();
349
+ String vpcEndpointId , Collection <String > sgIdsToAdd , Collection <String > sgIdsToRemove ) {
350
+ var builder = ModifyVpcEndpointRequest .builder ().vpcEndpointId (vpcEndpointId );
351
+ if (!sgIdsToAdd .isEmpty ()) {
352
+ builder .addSecurityGroupIds (sgIdsToAdd );
353
+ }
354
+ if (!sgIdsToRemove .isEmpty ()) {
355
+ builder .removeSecurityGroupIds (sgIdsToRemove );
356
+ }
357
+ return builder .build ();
344
358
}
345
359
346
360
private ProgressEvent <ResourceModel , CallbackContext > addTags (
0 commit comments