Skip to content

Commit b523fcd

Browse files
authored
Merge pull request #43779 from renaudhager/f-add_eks_deletion_protection
Add support for `deletion_protection` flag for EKS support
2 parents fd2ab1c + 8225d92 commit b523fcd

File tree

9 files changed

+198
-57
lines changed

9 files changed

+198
-57
lines changed

.changelog/43752.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
```release-note:enhancement
2+
resource/aws_eks_cluster: Add `deletion_protection` argument
3+
```
4+
5+
```release-note:enhancement
6+
data-source/aws_eks_cluster: Add `deletion_protection` attribute
7+
```

internal/service/eks/cluster.go

Lines changed: 87 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,11 @@ func resourceCluster() *schema.Resource {
168168
Type: schema.TypeString,
169169
Computed: true,
170170
},
171+
names.AttrDeletionProtection: {
172+
Type: schema.TypeBool,
173+
Optional: true,
174+
Computed: true,
175+
},
171176
"enabled_cluster_log_types": {
172177
Type: schema.TypeSet,
173178
Optional: true,
@@ -511,7 +516,7 @@ func resourceClusterCreate(ctx context.Context, d *schema.ResourceData, meta any
511516
conn := meta.(*conns.AWSClient).EKSClient(ctx)
512517

513518
name := d.Get(names.AttrName).(string)
514-
input := &eks.CreateClusterInput{
519+
input := eks.CreateClusterInput{
515520
BootstrapSelfManagedAddons: aws.Bool(d.Get("bootstrap_self_managed_addons").(bool)),
516521
EncryptionConfig: expandEncryptionConfig(d.Get("encryption_config").([]any)),
517522
Logging: expandLogging(d.Get("enabled_cluster_log_types").(*schema.Set)),
@@ -521,12 +526,16 @@ func resourceClusterCreate(ctx context.Context, d *schema.ResourceData, meta any
521526
Tags: getTagsIn(ctx),
522527
}
523528

529+
if v, ok := d.GetOk("access_config"); ok {
530+
input.AccessConfig = expandCreateAccessConfigRequest(v.([]any))
531+
}
532+
524533
if v, ok := d.GetOk("compute_config"); ok {
525534
input.ComputeConfig = expandComputeConfigRequest(v.([]any))
526535
}
527536

528-
if v, ok := d.GetOk("access_config"); ok {
529-
input.AccessConfig = expandCreateAccessConfigRequest(v.([]any))
537+
if v, ok := d.GetOk(names.AttrDeletionProtection); ok {
538+
input.DeletionProtection = aws.Bool(v.(bool))
530539
}
531540

532541
if v, ok := d.GetOk("kubernetes_network_config"); ok {
@@ -559,7 +568,7 @@ func resourceClusterCreate(ctx context.Context, d *schema.ResourceData, meta any
559568

560569
outputRaw, err := tfresource.RetryWhen(ctx, propagationTimeout,
561570
func() (any, error) {
562-
return conn.CreateCluster(ctx, input)
571+
return conn.CreateCluster(ctx, &input)
563572
},
564573
func(err error) (bool, error) {
565574
// InvalidParameterException: roleArn, arn:aws:iam::123456789012:role/XXX, does not exist
@@ -643,6 +652,7 @@ func resourceClusterRead(ctx context.Context, d *schema.ResourceData, meta any)
643652
return sdkdiag.AppendErrorf(diags, "setting compute_config: %s", err)
644653
}
645654
d.Set(names.AttrCreatedAt, cluster.CreatedAt.Format(time.RFC3339))
655+
d.Set(names.AttrDeletionProtection, cluster.DeletionProtection)
646656
if err := d.Set("enabled_cluster_log_types", flattenLogging(cluster.Logging)); err != nil {
647657
return sdkdiag.AppendErrorf(diags, "setting enabled_cluster_log_types: %s", err)
648658
}
@@ -692,7 +702,7 @@ func resourceClusterUpdate(ctx context.Context, d *schema.ResourceData, meta any
692702

693703
// Do any version update first.
694704
if d.HasChange(names.AttrVersion) {
695-
input := &eks.UpdateClusterVersionInput{
705+
input := eks.UpdateClusterVersionInput{
696706
Name: aws.String(d.Id()),
697707
Version: aws.String(d.Get(names.AttrVersion).(string)),
698708
}
@@ -701,7 +711,7 @@ func resourceClusterUpdate(ctx context.Context, d *schema.ResourceData, meta any
701711
input.Force = v.(bool)
702712
}
703713

704-
output, err := conn.UpdateClusterVersion(ctx, input)
714+
output, err := conn.UpdateClusterVersion(ctx, &input)
705715

706716
if err != nil {
707717
return sdkdiag.AppendErrorf(diags, "updating EKS Cluster (%s) version: %s", d.Id(), err)
@@ -716,12 +726,12 @@ func resourceClusterUpdate(ctx context.Context, d *schema.ResourceData, meta any
716726

717727
if d.HasChange("access_config") {
718728
if v, ok := d.GetOk("access_config"); ok {
719-
input := &eks.UpdateClusterConfigInput{
729+
input := eks.UpdateClusterConfigInput{
720730
AccessConfig: expandUpdateAccessConfigRequest(v.([]any)),
721731
Name: aws.String(d.Id()),
722732
}
723733

724-
output, err := conn.UpdateClusterConfig(ctx, input)
734+
output, err := conn.UpdateClusterConfig(ctx, &input)
725735

726736
if err != nil {
727737
return sdkdiag.AppendErrorf(diags, "updating EKS Cluster (%s) access configuration: %s", d.Id(), err)
@@ -741,15 +751,14 @@ func resourceClusterUpdate(ctx context.Context, d *schema.ResourceData, meta any
741751
computeConfig := expandComputeConfigRequest(d.Get("compute_config").([]any))
742752
kubernetesNetworkConfig := expandKubernetesNetworkConfigRequest(d.Get("kubernetes_network_config").([]any))
743753
storageConfig := expandStorageConfigRequest(d.Get("storage_config").([]any))
744-
745-
input := &eks.UpdateClusterConfigInput{
746-
Name: aws.String(d.Id()),
754+
input := eks.UpdateClusterConfigInput{
747755
ComputeConfig: computeConfig,
748756
KubernetesNetworkConfig: kubernetesNetworkConfig,
757+
Name: aws.String(d.Id()),
749758
StorageConfig: storageConfig,
750759
}
751760

752-
output, err := conn.UpdateClusterConfig(ctx, input)
761+
output, err := conn.UpdateClusterConfig(ctx, &input)
753762

754763
if err != nil {
755764
return sdkdiag.AppendErrorf(diags, "updating EKS Cluster (%s) compute config: %s", d.Id(), err)
@@ -762,16 +771,20 @@ func resourceClusterUpdate(ctx context.Context, d *schema.ResourceData, meta any
762771
}
763772
}
764773

765-
if d.HasChange("encryption_config") {
766-
o, n := d.GetChange("encryption_config")
774+
if d.HasChange(names.AttrDeletionProtection) {
775+
if err := updateClusterDeletionProtection(ctx, conn, d.Id(), d.Get(names.AttrDeletionProtection).(bool), d.Timeout(schema.TimeoutUpdate)); err != nil {
776+
return sdkdiag.AppendFromErr(diags, err)
777+
}
778+
}
767779

768-
if len(o.([]any)) == 0 && len(n.([]any)) == 1 {
769-
input := &eks.AssociateEncryptionConfigInput{
780+
if d.HasChange("encryption_config") {
781+
if o, n := d.GetChange("encryption_config"); len(o.([]any)) == 0 && len(n.([]any)) == 1 {
782+
input := eks.AssociateEncryptionConfigInput{
770783
ClusterName: aws.String(d.Id()),
771784
EncryptionConfig: expandEncryptionConfig(d.Get("encryption_config").([]any)),
772785
}
773786

774-
output, err := conn.AssociateEncryptionConfig(ctx, input)
787+
output, err := conn.AssociateEncryptionConfig(ctx, &input)
775788

776789
if err != nil {
777790
return sdkdiag.AppendErrorf(diags, "associating EKS Cluster (%s) encryption config: %s", d.Id(), err)
@@ -786,12 +799,12 @@ func resourceClusterUpdate(ctx context.Context, d *schema.ResourceData, meta any
786799
}
787800

788801
if d.HasChange("enabled_cluster_log_types") {
789-
input := &eks.UpdateClusterConfigInput{
802+
input := eks.UpdateClusterConfigInput{
790803
Logging: expandLogging(d.Get("enabled_cluster_log_types").(*schema.Set)),
791804
Name: aws.String(d.Id()),
792805
}
793806

794-
output, err := conn.UpdateClusterConfig(ctx, input)
807+
output, err := conn.UpdateClusterConfig(ctx, &input)
795808

796809
if err != nil {
797810
return sdkdiag.AppendErrorf(diags, "updating EKS Cluster (%s) logging: %s", d.Id(), err)
@@ -805,12 +818,12 @@ func resourceClusterUpdate(ctx context.Context, d *schema.ResourceData, meta any
805818
}
806819

807820
if d.HasChange("upgrade_policy") {
808-
input := &eks.UpdateClusterConfigInput{
821+
input := eks.UpdateClusterConfigInput{
809822
Name: aws.String(d.Id()),
810823
UpgradePolicy: expandUpgradePolicy(d.Get("upgrade_policy").([]any)),
811824
}
812825

813-
output, err := conn.UpdateClusterConfig(ctx, input)
826+
output, err := conn.UpdateClusterConfig(ctx, &input)
814827

815828
if err != nil {
816829
return sdkdiag.AppendErrorf(diags, "updating EKS Cluster (%s) upgrade policy: %s", d.Id(), err)
@@ -824,7 +837,7 @@ func resourceClusterUpdate(ctx context.Context, d *schema.ResourceData, meta any
824837
}
825838

826839
if d.HasChanges("vpc_config.0.endpoint_private_access", "vpc_config.0.endpoint_public_access", "vpc_config.0.public_access_cidrs") {
827-
config := &types.VpcConfigRequest{
840+
config := types.VpcConfigRequest{
828841
EndpointPrivateAccess: aws.Bool(d.Get("vpc_config.0.endpoint_private_access").(bool)),
829842
EndpointPublicAccess: aws.Bool(d.Get("vpc_config.0.endpoint_public_access").(bool)),
830843
}
@@ -833,39 +846,39 @@ func resourceClusterUpdate(ctx context.Context, d *schema.ResourceData, meta any
833846
config.PublicAccessCidrs = flex.ExpandStringValueSet(v.(*schema.Set))
834847
}
835848

836-
if err := updateVPCConfig(ctx, conn, d.Id(), config, d.Timeout(schema.TimeoutUpdate)); err != nil {
849+
if err := updateClusterVPCConfig(ctx, conn, d.Id(), &config, d.Timeout(schema.TimeoutUpdate)); err != nil {
837850
return sdkdiag.AppendFromErr(diags, err)
838851
}
839852
}
840853

841854
// API only allows one type of update at at time.
842855
if d.HasChange("vpc_config.0.subnet_ids") {
843-
config := &types.VpcConfigRequest{
856+
config := types.VpcConfigRequest{
844857
SubnetIds: flex.ExpandStringValueSet(d.Get("vpc_config.0.subnet_ids").(*schema.Set)),
845858
}
846859

847-
if err := updateVPCConfig(ctx, conn, d.Id(), config, d.Timeout(schema.TimeoutUpdate)); err != nil {
860+
if err := updateClusterVPCConfig(ctx, conn, d.Id(), &config, d.Timeout(schema.TimeoutUpdate)); err != nil {
848861
return sdkdiag.AppendFromErr(diags, err)
849862
}
850863
}
851864

852865
if d.HasChange("vpc_config.0.security_group_ids") {
853-
config := &types.VpcConfigRequest{
866+
config := types.VpcConfigRequest{
854867
SecurityGroupIds: flex.ExpandStringValueSet(d.Get("vpc_config.0.security_group_ids").(*schema.Set)),
855868
}
856869

857-
if err := updateVPCConfig(ctx, conn, d.Id(), config, d.Timeout(schema.TimeoutUpdate)); err != nil {
870+
if err := updateClusterVPCConfig(ctx, conn, d.Id(), &config, d.Timeout(schema.TimeoutUpdate)); err != nil {
858871
return sdkdiag.AppendFromErr(diags, err)
859872
}
860873
}
861874

862875
if d.HasChange("zonal_shift_config") {
863-
input := &eks.UpdateClusterConfigInput{
876+
input := eks.UpdateClusterConfigInput{
864877
Name: aws.String(d.Id()),
865878
ZonalShiftConfig: expandZonalShiftConfig(d.Get("zonal_shift_config").([]any)),
866879
}
867880

868-
output, err := conn.UpdateClusterConfig(ctx, input)
881+
output, err := conn.UpdateClusterConfig(ctx, &input)
869882

870883
if err != nil {
871884
return sdkdiag.AppendErrorf(diags, "updating EKS Cluster (%s) zonal shift config: %s", d.Id(), err)
@@ -886,20 +899,19 @@ func resourceClusterDelete(ctx context.Context, d *schema.ResourceData, meta any
886899

887900
conn := meta.(*conns.AWSClient).EKSClient(ctx)
888901

889-
input := &eks.DeleteClusterInput{
890-
Name: aws.String(d.Id()),
891-
}
892-
893902
// If a cluster is scaling up due to load a delete request will fail
894903
// This is a temporary workaround until EKS supports multiple parallel mutating operations
895904
const (
896905
timeout = 60 * time.Minute
897906
)
898907
log.Printf("[DEBUG] Deleting EKS Cluster: %s", d.Id())
908+
input := eks.DeleteClusterInput{
909+
Name: aws.String(d.Id()),
910+
}
899911
err := tfresource.Retry(ctx, timeout, func() *retry.RetryError {
900912
var err error
901913

902-
_, err = conn.DeleteCluster(ctx, input)
914+
_, err = conn.DeleteCluster(ctx, &input)
903915

904916
if errs.IsAErrorMessageContains[*types.ResourceInUseException](err, "in progress") {
905917
return retry.RetryableError(err)
@@ -913,7 +925,7 @@ func resourceClusterDelete(ctx context.Context, d *schema.ResourceData, meta any
913925
}, tfresource.WithDelayRand(1*time.Minute), tfresource.WithPollInterval(30*time.Second))
914926

915927
if tfresource.TimedOut(err) {
916-
_, err = conn.DeleteCluster(ctx, input)
928+
_, err = conn.DeleteCluster(ctx, &input)
917929
}
918930

919931
if errs.IsA[*types.ResourceNotFoundException](err) {
@@ -938,10 +950,14 @@ func resourceClusterDelete(ctx context.Context, d *schema.ResourceData, meta any
938950
}
939951

940952
func findClusterByName(ctx context.Context, conn *eks.Client, name string) (*types.Cluster, error) {
941-
input := &eks.DescribeClusterInput{
953+
input := eks.DescribeClusterInput{
942954
Name: aws.String(name),
943955
}
944956

957+
return findCluster(ctx, conn, &input)
958+
}
959+
960+
func findCluster(ctx context.Context, conn *eks.Client, input *eks.DescribeClusterInput) (*types.Cluster, error) {
945961
output, err := conn.DescribeCluster(ctx, input)
946962

947963
// Sometimes the EKS API returns the ResourceNotFound error in this form:
@@ -964,33 +980,58 @@ func findClusterByName(ctx context.Context, conn *eks.Client, name string) (*typ
964980
return output.Cluster, nil
965981
}
966982

967-
func updateVPCConfig(ctx context.Context, conn *eks.Client, name string, vpcConfig *types.VpcConfigRequest, timeout time.Duration) error {
968-
input := &eks.UpdateClusterConfigInput{
983+
func updateClusterDeletionProtection(ctx context.Context, conn *eks.Client, name string, deletionProtection bool, timeout time.Duration) error {
984+
input := eks.UpdateClusterConfigInput{
985+
DeletionProtection: aws.Bool(deletionProtection),
986+
Name: aws.String(name),
987+
}
988+
989+
output, err := conn.UpdateClusterConfig(ctx, &input)
990+
991+
if err != nil {
992+
return fmt.Errorf("updating EKS Cluster (%s) deletion protection (%t): %w", name, deletionProtection, err)
993+
}
994+
995+
updateID := aws.ToString(output.Update.Id)
996+
997+
if _, err := waitClusterUpdateSuccessful(ctx, conn, name, updateID, timeout); err != nil {
998+
return fmt.Errorf("waiting for EKS Cluster (%s) deletion protection update (%s): %w", name, updateID, err)
999+
}
1000+
1001+
return nil
1002+
}
1003+
1004+
func updateClusterVPCConfig(ctx context.Context, conn *eks.Client, name string, vpcConfig *types.VpcConfigRequest, timeout time.Duration) error {
1005+
input := eks.UpdateClusterConfigInput{
9691006
Name: aws.String(name),
9701007
ResourcesVpcConfig: vpcConfig,
9711008
}
9721009

973-
output, err := conn.UpdateClusterConfig(ctx, input)
1010+
output, err := conn.UpdateClusterConfig(ctx, &input)
9741011

9751012
if err != nil {
976-
return fmt.Errorf("updating EKS Cluster (%s) VPC configuration: %s", name, err)
1013+
return fmt.Errorf("updating EKS Cluster (%s) VPC configuration: %w", name, err)
9771014
}
9781015

9791016
updateID := aws.ToString(output.Update.Id)
9801017

9811018
if _, err := waitClusterUpdateSuccessful(ctx, conn, name, updateID, timeout); err != nil {
982-
return fmt.Errorf("waiting for EKS Cluster (%s) VPC configuration update (%s): %s", name, updateID, err)
1019+
return fmt.Errorf("waiting for EKS Cluster (%s) VPC configuration update (%s): %w", name, updateID, err)
9831020
}
9841021

9851022
return nil
9861023
}
9871024

988-
func findClusterUpdateByTwoPartKey(ctx context.Context, conn *eks.Client, name, id string) (*types.Update, error) {
989-
input := &eks.DescribeUpdateInput{
1025+
func findUpdateByTwoPartKey(ctx context.Context, conn *eks.Client, name, id string) (*types.Update, error) {
1026+
input := eks.DescribeUpdateInput{
9901027
Name: aws.String(name),
9911028
UpdateId: aws.String(id),
9921029
}
9931030

1031+
return findUpdate(ctx, conn, &input)
1032+
}
1033+
1034+
func findUpdate(ctx context.Context, conn *eks.Client, input *eks.DescribeUpdateInput) (*types.Update, error) {
9941035
output, err := conn.DescribeUpdate(ctx, input)
9951036

9961037
if errs.IsA[*types.ResourceNotFoundException](err) {
@@ -1027,9 +1068,9 @@ func statusCluster(ctx context.Context, conn *eks.Client, name string) retry.Sta
10271068
}
10281069
}
10291070

1030-
func statusClusterUpdate(ctx context.Context, conn *eks.Client, name, id string) retry.StateRefreshFunc {
1071+
func statusUpdate(ctx context.Context, conn *eks.Client, name, id string) retry.StateRefreshFunc {
10311072
return func() (any, string, error) {
1032-
output, err := findClusterUpdateByTwoPartKey(ctx, conn, name, id)
1073+
output, err := findUpdateByTwoPartKey(ctx, conn, name, id)
10331074

10341075
if tfresource.NotFound(err) {
10351076
return nil, "", nil
@@ -1085,7 +1126,7 @@ func waitClusterUpdateSuccessful(ctx context.Context, conn *eks.Client, name, id
10851126
stateConf := &retry.StateChangeConf{
10861127
Pending: enum.Slice(types.UpdateStatusInProgress),
10871128
Target: enum.Slice(types.UpdateStatusSuccessful),
1088-
Refresh: statusClusterUpdate(ctx, conn, name, id),
1129+
Refresh: statusUpdate(ctx, conn, name, id),
10891130
Timeout: timeout,
10901131
}
10911132

0 commit comments

Comments
 (0)