@@ -18,10 +18,12 @@ import (
18
18
"errors"
19
19
"fmt"
20
20
"strings"
21
+ "time"
21
22
22
23
svcapitypes "github.com/aws-controllers-k8s/kafka-controller/apis/v1alpha1"
23
24
ackcompare "github.com/aws-controllers-k8s/runtime/pkg/compare"
24
25
ackcondition "github.com/aws-controllers-k8s/runtime/pkg/condition"
26
+ ackerr "github.com/aws-controllers-k8s/runtime/pkg/errors"
25
27
ackrequeue "github.com/aws-controllers-k8s/runtime/pkg/requeue"
26
28
ackrtlog "github.com/aws-controllers-k8s/runtime/pkg/runtime/log"
27
29
ackutil "github.com/aws-controllers-k8s/runtime/pkg/util"
38
40
string (svcsdktypes .ClusterStateDeleting ),
39
41
string (svcsdktypes .ClusterStateFailed ),
40
42
}
43
+ RequeueAfterUpdateDuration = 15 * time .Second
41
44
)
42
45
43
46
var (
@@ -113,6 +116,18 @@ func clusterDeleting(r *resource) bool {
113
116
return cs == strings .ToLower (string (svcsdktypes .ClusterStateDeleting ))
114
117
}
115
118
119
+ // requeueAfterAsyncUpdate returns a `ackrequeue.RequeueNeededAfter` struct
120
+ // explaining the cluster cannot be modified until after the asynchronous update
121
+ // has (first, started and then) completed and the cluster reaches an active
122
+ // status.
123
+ func requeueAfterAsyncUpdate () * ackrequeue.RequeueNeededAfter {
124
+ return ackrequeue .NeededAfter (
125
+ fmt .Errorf ("cluster has started asynchronously updating, cannot be modified until '%s'" ,
126
+ "Active" ),
127
+ RequeueAfterUpdateDuration ,
128
+ )
129
+ }
130
+
116
131
func (rm * resourceManager ) customUpdate (
117
132
ctx context.Context ,
118
133
desired * resource ,
@@ -133,12 +148,6 @@ func (rm *resourceManager) customUpdate(
133
148
// Copy status from latest since it has the current cluster state
134
149
updatedRes .ko .Status = latest .ko .Status
135
150
136
- if clusterDeleting (latest ) {
137
- msg := "Cluster is currently being deleted"
138
- ackcondition .SetSynced (updatedRes , corev1 .ConditionFalse , & msg , nil )
139
- return updatedRes , requeueWaitWhileDeleting
140
- }
141
-
142
151
if ! clusterActive (latest ) {
143
152
msg := "Cluster is in '" + * latest .ko .Status .State + "' state"
144
153
ackcondition .SetSynced (updatedRes , corev1 .ConditionFalse , & msg , nil )
@@ -149,16 +158,120 @@ func (rm *resourceManager) customUpdate(
149
158
return updatedRes , requeueWaitUntilCanModify (latest )
150
159
}
151
160
152
- if delta .DifferentAt ("Spec.AssociatedSCRAMSecrets" ) {
161
+ switch {
162
+ case delta .DifferentAt ("Spec.ClientAuthentication" ):
163
+ input := & svcsdk.UpdateSecurityInput {}
164
+ if desired .ko .Status .CurrentVersion != nil {
165
+ input .CurrentVersion = desired .ko .Status .CurrentVersion
166
+ }
167
+ if desired .ko .Status .ACKResourceMetadata .ARN != nil {
168
+ input .ClusterArn = (* string )(desired .ko .Status .ACKResourceMetadata .ARN )
169
+ }
170
+ if desired .ko .Spec .ClientAuthentication != nil {
171
+ f0 := & svcsdktypes.ClientAuthentication {}
172
+ if desired .ko .Spec .ClientAuthentication .SASL != nil {
173
+ f0f0 := & svcsdktypes.Sasl {}
174
+ if desired .ko .Spec .ClientAuthentication .SASL .IAM != nil &&
175
+ desired .ko .Spec .ClientAuthentication .SASL .IAM .Enabled != nil {
176
+ f0f0f0 := & svcsdktypes.Iam {
177
+ Enabled : desired .ko .Spec .ClientAuthentication .SASL .IAM .Enabled ,
178
+ }
179
+ f0f0 .Iam = f0f0f0
180
+ }
181
+ if desired .ko .Spec .ClientAuthentication .SASL .SCRAM != nil &&
182
+ desired .ko .Spec .ClientAuthentication .SASL .SCRAM .Enabled != nil {
183
+ f0f0f1 := & svcsdktypes.Scram {
184
+ Enabled : desired .ko .Spec .ClientAuthentication .SASL .SCRAM .Enabled ,
185
+ }
186
+ f0f0 .Scram = f0f0f1
187
+ }
188
+ f0 .Sasl = f0f0
189
+ }
190
+ if desired .ko .Spec .ClientAuthentication .TLS != nil {
191
+ f0f1 := & svcsdktypes.Tls {}
192
+ if desired .ko .Spec .ClientAuthentication .TLS .CertificateAuthorityARNList != nil {
193
+ f0f1 .CertificateAuthorityArnList = aws .ToStringSlice (desired .ko .Spec .ClientAuthentication .TLS .CertificateAuthorityARNList )
194
+ }
195
+ if desired .ko .Spec .ClientAuthentication .TLS .Enabled != nil {
196
+ f0f1 .Enabled = desired .ko .Spec .ClientAuthentication .TLS .Enabled
197
+ }
198
+ f0 .Tls = f0f1
199
+ }
200
+ if desired .ko .Spec .ClientAuthentication .Unauthenticated != nil &&
201
+ desired .ko .Spec .ClientAuthentication .Unauthenticated .Enabled != nil {
202
+ f0 .Unauthenticated = & svcsdktypes.Unauthenticated {
203
+ Enabled : desired .ko .Spec .ClientAuthentication .Unauthenticated .Enabled ,
204
+ }
205
+ }
206
+ input .ClientAuthentication = f0
207
+ }
208
+
209
+ _ , err = rm .sdkapi .UpdateSecurity (ctx , input )
210
+ rm .metrics .RecordAPICall ("UPDATE" , "UpdateSecurity" , err )
211
+ if err != nil {
212
+ return nil , err
213
+ }
214
+ ackcondition .SetSynced (updatedRes , corev1 .ConditionFalse , nil , nil )
215
+ err = requeueAfterAsyncUpdate ()
216
+
217
+ case delta .DifferentAt ("Spec.AssociatedSCRAMSecrets" ):
153
218
err = rm .syncAssociatedScramSecrets (ctx , updatedRes , latest )
154
219
if err != nil {
155
220
return nil , err
156
221
}
222
+ // Set synced condition to True after successful update
223
+ ackcondition .SetSynced (updatedRes , corev1 .ConditionFalse , nil , nil )
224
+
225
+ case delta .DifferentAt ("Spec.BrokerNodeGroupInfo.StorageInfo.EBSStorageInfo.VolumeSize" ):
226
+ _ , err := rm .sdkapi .UpdateBrokerStorage (ctx , & svcsdk.UpdateBrokerStorageInput {
227
+ ClusterArn : (* string )(latest .ko .Status .ACKResourceMetadata .ARN ),
228
+ CurrentVersion : latest .ko .Status .CurrentVersion ,
229
+ TargetBrokerEBSVolumeInfo : []svcsdktypes.BrokerEBSVolumeInfo {
230
+ {
231
+ KafkaBrokerNodeId : aws .String ("ALL" ),
232
+ VolumeSizeGB : aws .Int32 (int32 (* desired .ko .Spec .BrokerNodeGroupInfo .StorageInfo .EBSStorageInfo .VolumeSize )),
233
+ },
234
+ },
235
+ })
236
+ rm .metrics .RecordAPICall ("UPDATE" , "UpdateBrokerStorage" , err )
237
+ if err != nil {
238
+ return nil , err
239
+ }
240
+ message := fmt .Sprintf ("kafka is updating broker storage" )
241
+ ackcondition .SetSynced (updatedRes , corev1 .ConditionFalse , & message , nil )
242
+ err = requeueAfterAsyncUpdate ()
243
+
244
+ case delta .DifferentAt ("Spec.BrokerNodeGroupInfo.InstanceType" ):
245
+ _ , err := rm .sdkapi .UpdateBrokerType (ctx , & svcsdk.UpdateBrokerTypeInput {
246
+ ClusterArn : (* string )(latest .ko .Status .ACKResourceMetadata .ARN ),
247
+ CurrentVersion : latest .ko .Status .CurrentVersion ,
248
+ TargetInstanceType : desired .ko .Spec .BrokerNodeGroupInfo .InstanceType ,
249
+ })
250
+ rm .metrics .RecordAPICall ("UPDATE" , "UpdateBrokerType" , err )
251
+ if err != nil {
252
+ return nil , err
253
+ }
254
+ message := fmt .Sprintf ("kafka is updating broker instanceType" )
255
+ ackcondition .SetSynced (updatedRes , corev1 .ConditionFalse , & message , nil )
256
+ err = requeueAfterAsyncUpdate ()
257
+
258
+ case delta .DifferentAt ("Spec.NumberOfBrokerNodes" ):
259
+ _ , err := rm .sdkapi .UpdateBrokerCount (ctx , & svcsdk.UpdateBrokerCountInput {
260
+ ClusterArn : (* string )(latest .ko .Status .ACKResourceMetadata .ARN ),
261
+ CurrentVersion : latest .ko .Status .CurrentVersion ,
262
+ TargetNumberOfBrokerNodes : aws .Int32 (int32 (* desired .ko .Spec .NumberOfBrokerNodes )),
263
+ })
264
+ rm .metrics .RecordAPICall ("UPDATE" , "UpdateBrokerCount" , err )
265
+ if err != nil {
266
+ return nil , err
267
+ }
268
+ message := fmt .Sprintf ("kafka is updating broker instanceType" )
269
+ ackcondition .SetSynced (updatedRes , corev1 .ConditionFalse , & message , nil )
270
+ err = requeueAfterAsyncUpdate ()
271
+
157
272
}
158
273
159
- // Set synced condition to True after successful update
160
- ackcondition .SetSynced (updatedRes , corev1 .ConditionTrue , nil , nil )
161
- return updatedRes , nil
274
+ return updatedRes , err
162
275
}
163
276
164
277
// syncAssociatedScramSecrets examines the Secret ARNs in the supplied Cluster
@@ -242,6 +355,16 @@ func (rm *resourceManager) getAssociatedScramSecrets(
242
355
return res , err
243
356
}
244
357
358
+ type unprocessedSecret struct {
359
+ errorCode string
360
+ errorMessage string
361
+ secretArn string
362
+ }
363
+
364
+ func (us unprocessedSecret ) String () string {
365
+ return fmt .Sprintf ("ErrorCode: %s, ErrorMessage %s, SecretArn: %s" , us .errorCode , us .errorMessage , us .secretArn )
366
+ }
367
+
245
368
// batchAssociateScramSecret associates the supplied scram secrets to the supplied Cluster
246
369
// resource
247
370
func (rm * resourceManager ) batchAssociateScramSecret (
@@ -255,14 +378,27 @@ func (rm *resourceManager) batchAssociateScramSecret(
255
378
256
379
input := & svcsdk.BatchAssociateScramSecretInput {}
257
380
input .ClusterArn = (* string )(r .ko .Status .ACKResourceMetadata .ARN )
258
- // Convert []*string to []string
259
- unrefSecrets := make ([]string , len (secretARNs ))
260
- for i , s := range secretARNs {
261
- unrefSecrets [i ] = * s
262
- }
263
- input .SecretArnList = unrefSecrets
264
- _ , err = rm .sdkapi .BatchAssociateScramSecret (ctx , input )
381
+ input .SecretArnList = aws .ToStringSlice (secretARNs )
382
+ resp , err := rm .sdkapi .BatchAssociateScramSecret (ctx , input )
265
383
rm .metrics .RecordAPICall ("UPDATE" , "BatchAssociateScramSecret" , err )
384
+ if err != nil {
385
+ return err
386
+ }
387
+
388
+ if len (resp .UnprocessedScramSecrets ) > 0 {
389
+ unprocessedSecrets := []unprocessedSecret {}
390
+ for _ , uss := range resp .UnprocessedScramSecrets {
391
+ us := unprocessedSecret {
392
+ errorCode : aws .ToString (uss .ErrorCode ),
393
+ errorMessage : aws .ToString (uss .ErrorMessage ),
394
+ secretArn : aws .ToString (uss .SecretArn ),
395
+ }
396
+ unprocessedSecrets = append (unprocessedSecrets , us )
397
+ }
398
+
399
+ return ackerr .NewTerminalError (fmt .Errorf ("Cant attach secret arns: %v" , unprocessedSecrets ))
400
+ }
401
+
266
402
return err
267
403
}
268
404
0 commit comments