@@ -1560,15 +1560,17 @@ func resourceInstanceUpdate(ctx context.Context, d *schema.ResourceData, meta in
1560
1560
// HasChange() thinks there is a diff between what is set on the instance and what is set in state. We need to ensure that
1561
1561
// if a diff has occurred, it's not because it's a new instance.
1562
1562
if d .HasChange ("source_dest_check" ) && ! d .IsNewResource () || d .IsNewResource () && ! sourceDestCheck {
1563
- log .Printf ("[INFO] Modifying `source_dest_check` on Instance %s" , d .Id ())
1564
- _ , err := conn .ModifyInstanceAttributeWithContext (ctx , & ec2.ModifyInstanceAttributeInput {
1563
+ input := & ec2.ModifyInstanceAttributeInput {
1565
1564
InstanceId : aws .String (d .Id ()),
1566
1565
SourceDestCheck : & ec2.AttributeBooleanValue {
1567
1566
Value : aws .Bool (sourceDestCheck ),
1568
1567
},
1569
- })
1568
+ }
1569
+
1570
+ _ , err := conn .ModifyInstanceAttributeWithContext (ctx , input )
1571
+
1570
1572
if err != nil {
1571
- return create . AppendDiagError (diags , names . EC2 , create . ErrActionUpdating , " Instance" , d .Id (), err )
1573
+ return sdkdiag . AppendErrorf (diags , "modifying EC2 Instance (%s) SourceDestCheck attribute: %s " , d .Id (), err )
1572
1574
}
1573
1575
}
1574
1576
}
@@ -1668,17 +1670,18 @@ func resourceInstanceUpdate(ctx context.Context, d *schema.ResourceData, meta in
1668
1670
// Only one attribute can be modified at a time, else we get
1669
1671
// "InvalidParameterCombination: Fields for multiple attribute types specified"
1670
1672
if d .HasChange ("instance_type" ) {
1671
- log . Printf ( "[INFO] Modifying instance type %s" , d . Id ())
1672
-
1673
- input := & ec2.ModifyInstanceAttributeInput {
1674
- InstanceId : aws .String (d .Id ()),
1675
- InstanceType : & ec2.AttributeValue {
1676
- Value : aws .String (d . Get ( "instance_type" ).( string ) ),
1677
- },
1678
- }
1673
+ if ! d . HasChange ( "capacity_reservation_specification.0.capacity_reservation_target.0.capacity_reservation_id" ) {
1674
+ instanceType := d . Get ( "instance_type" ).( string )
1675
+ input := & ec2.ModifyInstanceAttributeInput {
1676
+ InstanceId : aws .String (d .Id ()),
1677
+ InstanceType : & ec2.AttributeValue {
1678
+ Value : aws .String (instanceType ),
1679
+ },
1680
+ }
1679
1681
1680
- if err := modifyInstanceAttributeWithStopStart (ctx , conn , input ); err != nil {
1681
- return sdkdiag .AppendErrorf (diags , "updating EC2 Instance (%s) type: %s" , d .Id (), err )
1682
+ if err := modifyInstanceAttributeWithStopStart (ctx , conn , input , fmt .Sprintf ("InstanceType (%s)" , instanceType )); err != nil {
1683
+ return sdkdiag .AppendErrorf (diags , "updating EC2 Instance (%s) type: %s" , d .Id (), err )
1684
+ }
1682
1685
}
1683
1686
}
1684
1687
@@ -1704,7 +1707,7 @@ func resourceInstanceUpdate(ctx context.Context, d *schema.ResourceData, meta in
1704
1707
},
1705
1708
}
1706
1709
1707
- if err := modifyInstanceAttributeWithStopStart (ctx , conn , input ); err != nil {
1710
+ if err := modifyInstanceAttributeWithStopStart (ctx , conn , input , "UserData" ); err != nil {
1708
1711
return sdkdiag .AppendErrorf (diags , "updating EC2 Instance (%s) user data: %s" , d .Id (), err )
1709
1712
}
1710
1713
}
@@ -1727,7 +1730,7 @@ func resourceInstanceUpdate(ctx context.Context, d *schema.ResourceData, meta in
1727
1730
},
1728
1731
}
1729
1732
1730
- if err := modifyInstanceAttributeWithStopStart (ctx , conn , input ); err != nil {
1733
+ if err := modifyInstanceAttributeWithStopStart (ctx , conn , input , "UserData (base64)" ); err != nil {
1731
1734
return sdkdiag .AppendErrorf (diags , "updating EC2 Instance (%s) user data base64: %s" , d .Id (), err )
1732
1735
}
1733
1736
}
@@ -1746,15 +1749,17 @@ func resourceInstanceUpdate(ctx context.Context, d *schema.ResourceData, meta in
1746
1749
}
1747
1750
1748
1751
if d .HasChange ("instance_initiated_shutdown_behavior" ) {
1749
- log .Printf ("[INFO] Modifying instance %s" , d .Id ())
1750
- _ , err := conn .ModifyInstanceAttributeWithContext (ctx , & ec2.ModifyInstanceAttributeInput {
1752
+ input := & ec2.ModifyInstanceAttributeInput {
1751
1753
InstanceId : aws .String (d .Id ()),
1752
1754
InstanceInitiatedShutdownBehavior : & ec2.AttributeValue {
1753
1755
Value : aws .String (d .Get ("instance_initiated_shutdown_behavior" ).(string )),
1754
1756
},
1755
- })
1757
+ }
1758
+
1759
+ _ , err := conn .ModifyInstanceAttributeWithContext (ctx , input )
1760
+
1756
1761
if err != nil {
1757
- return sdkdiag .AppendErrorf (diags , "updating EC2 Instance (%s): modifying InstanceInitiatedShutdownBehavior: %s" , d .Id (), err )
1762
+ return sdkdiag .AppendErrorf (diags , "modifying EC2 Instance (%s) InstanceInitiatedShutdownBehavior attribute : %s" , d .Id (), err )
1758
1763
}
1759
1764
}
1760
1765
@@ -1919,11 +1924,10 @@ func resourceInstanceUpdate(ctx context.Context, d *schema.ResourceData, meta in
1919
1924
InstanceId : aws .String (d .Id ()),
1920
1925
}
1921
1926
1922
- log .Printf ("[DEBUG] Modifying EC2 Instance attribute: %s" , input )
1923
1927
_ , err := conn .ModifyInstanceAttributeWithContext (ctx , input )
1924
1928
1925
1929
if err != nil {
1926
- return sdkdiag .AppendErrorf (diags , "updating EC2 Instance (%s) root block device (%s) DeleteOnTermination attribute: %s" , d .Id (), deviceName , err )
1930
+ return sdkdiag .AppendErrorf (diags , "modifying EC2 Instance (%s) BlockDeviceMappings (%s) attribute: %s" , d .Id (), deviceName , err )
1927
1931
}
1928
1932
1929
1933
if _ , err := WaitInstanceRootBlockDeviceDeleteOnTerminationUpdated (ctx , conn , d .Id (), v , d .Timeout (schema .TimeoutUpdate )); err != nil {
@@ -1946,12 +1950,31 @@ func resourceInstanceUpdate(ctx context.Context, d *schema.ResourceData, meta in
1946
1950
if d .HasChange ("capacity_reservation_specification" ) && ! d .IsNewResource () {
1947
1951
if v , ok := d .GetOk ("capacity_reservation_specification" ); ok && len (v .([]interface {})) > 0 && v .([]interface {})[0 ] != nil {
1948
1952
if v := expandCapacityReservationSpecification (v .([]interface {})[0 ].(map [string ]interface {})); v != nil && (v .CapacityReservationPreference != nil || v .CapacityReservationTarget != nil ) {
1953
+ if err := stopInstance (ctx , conn , d .Id (), false , InstanceStopTimeout ); err != nil {
1954
+ return sdkdiag .AppendFromErr (diags , err )
1955
+ }
1956
+
1957
+ if d .HasChange ("capacity_reservation_specification.0.capacity_reservation_target.0.capacity_reservation_id" ) && d .HasChange ("instance_type" ) {
1958
+ instanceType := d .Get ("instance_type" ).(string )
1959
+ input := & ec2.ModifyInstanceAttributeInput {
1960
+ InstanceId : aws .String (d .Id ()),
1961
+ InstanceType : & ec2.AttributeValue {
1962
+ Value : aws .String (instanceType ),
1963
+ },
1964
+ }
1965
+
1966
+ if _ , err := conn .ModifyInstanceAttributeWithContext (ctx , input ); err != nil {
1967
+ return sdkdiag .AppendErrorf (diags , "modifying EC2 Instance (%s) InstanceType (%s) attribute: %s" , d .Id (), instanceType , err )
1968
+ }
1969
+ }
1970
+
1949
1971
input := & ec2.ModifyInstanceCapacityReservationAttributesInput {
1950
1972
CapacityReservationSpecification : v ,
1951
1973
InstanceId : aws .String (d .Id ()),
1952
1974
}
1953
1975
1954
1976
log .Printf ("[DEBUG] Modifying EC2 Instance capacity reservation attributes: %s" , input )
1977
+
1955
1978
_ , err := conn .ModifyInstanceCapacityReservationAttributesWithContext (ctx , input )
1956
1979
1957
1980
if err != nil {
@@ -1961,6 +1984,10 @@ func resourceInstanceUpdate(ctx context.Context, d *schema.ResourceData, meta in
1961
1984
if _ , err := WaitInstanceCapacityReservationSpecificationUpdated (ctx , conn , d .Id (), v ); err != nil {
1962
1985
return sdkdiag .AppendErrorf (diags , "waiting for EC2 Instance (%s) capacity reservation attributes update: %s" , d .Id (), err )
1963
1986
}
1987
+
1988
+ if err := startInstance (ctx , conn , d .Id (), true , InstanceStartTimeout ); err != nil {
1989
+ return sdkdiag .AppendFromErr (diags , err )
1990
+ }
1964
1991
}
1965
1992
}
1966
1993
}
@@ -2032,40 +2059,44 @@ func resourceInstanceDelete(ctx context.Context, d *schema.ResourceData, meta in
2032
2059
}
2033
2060
2034
2061
func disableInstanceAPIStop (ctx context.Context , conn * ec2.EC2 , id string , disableAPIStop bool ) error {
2035
- _ , err := conn . ModifyInstanceAttributeWithContext ( ctx , & ec2.ModifyInstanceAttributeInput {
2062
+ input := & ec2.ModifyInstanceAttributeInput {
2036
2063
DisableApiStop : & ec2.AttributeBooleanValue {
2037
2064
Value : aws .Bool (disableAPIStop ),
2038
2065
},
2039
2066
InstanceId : aws .String (id ),
2040
- })
2067
+ }
2068
+
2069
+ _ , err := conn .ModifyInstanceAttributeWithContext (ctx , input )
2041
2070
2042
2071
if tfawserr .ErrMessageContains (err , errCodeUnsupportedOperation , "not supported for spot instances" ) {
2043
2072
log .Printf ("[WARN] failed to modify EC2 Instance (%s) attribute: %s" , id , err )
2044
2073
return nil
2045
2074
}
2046
2075
2047
2076
if err != nil {
2048
- return fmt .Errorf ("modifying DisableApiStop: %w" , err )
2077
+ return fmt .Errorf ("modifying EC2 Instance (%s) DisableApiStop attribute : %s" , id , err )
2049
2078
}
2050
2079
2051
2080
return nil
2052
2081
}
2053
2082
2054
2083
func disableInstanceAPITermination (ctx context.Context , conn * ec2.EC2 , id string , disableAPITermination bool ) error {
2055
- _ , err := conn . ModifyInstanceAttributeWithContext ( ctx , & ec2.ModifyInstanceAttributeInput {
2084
+ input := & ec2.ModifyInstanceAttributeInput {
2056
2085
DisableApiTermination : & ec2.AttributeBooleanValue {
2057
2086
Value : aws .Bool (disableAPITermination ),
2058
2087
},
2059
2088
InstanceId : aws .String (id ),
2060
- })
2089
+ }
2090
+
2091
+ _ , err := conn .ModifyInstanceAttributeWithContext (ctx , input )
2061
2092
2062
2093
if tfawserr .ErrMessageContains (err , errCodeUnsupportedOperation , "not supported for spot instances" ) {
2063
2094
log .Printf ("[WARN] failed to modify EC2 Instance (%s) attribute: %s" , id , err )
2064
2095
return nil
2065
2096
}
2066
2097
2067
2098
if err != nil {
2068
- return fmt .Errorf ("modifying DisableApiTermination: %w" , err )
2099
+ return fmt .Errorf ("modifying EC2 Instance (%s) DisableApiTermination attribute : %s" , id , err )
2069
2100
}
2070
2101
2071
2102
return nil
@@ -2075,33 +2106,19 @@ func disableInstanceAPITermination(ctx context.Context, conn *ec2.EC2, id string
2075
2106
// as input by first stopping the EC2 instance before the modification
2076
2107
// and then starting up the EC2 instance after modification.
2077
2108
// Reference: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Stop_Start.html
2078
- func modifyInstanceAttributeWithStopStart (ctx context.Context , conn * ec2.EC2 , input * ec2.ModifyInstanceAttributeInput ) error {
2109
+ func modifyInstanceAttributeWithStopStart (ctx context.Context , conn * ec2.EC2 , input * ec2.ModifyInstanceAttributeInput , attrName string ) error {
2079
2110
id := aws .StringValue (input .InstanceId )
2080
2111
2081
2112
if err := stopInstance (ctx , conn , id , false , InstanceStopTimeout ); err != nil {
2082
2113
return err
2083
2114
}
2084
2115
2085
2116
if _ , err := conn .ModifyInstanceAttributeWithContext (ctx , input ); err != nil {
2086
- return fmt .Errorf ("modifying EC2 Instance (%s) attribute: %w" , id , err )
2117
+ return fmt .Errorf ("modifying EC2 Instance (%s) %s attribute: %w" , id , attrName , err )
2087
2118
}
2088
2119
2089
- // Reference: https://github.com/hashicorp/terraform-provider-aws/issues/16433.
2090
- _ , err := tfresource .RetryWhenAWSErrMessageContains (ctx , ec2PropagationTimeout ,
2091
- func () (interface {}, error ) {
2092
- return conn .StartInstancesWithContext (ctx , & ec2.StartInstancesInput {
2093
- InstanceIds : aws .StringSlice ([]string {id }),
2094
- })
2095
- },
2096
- errCodeInvalidParameterValue , "LaunchPlan instance type does not match attribute value" ,
2097
- )
2098
-
2099
- if err != nil {
2100
- return fmt .Errorf ("starting EC2 Instance (%s): %w" , id , err )
2101
- }
2102
-
2103
- if _ , err := waitInstanceStarted (ctx , conn , id , InstanceStartTimeout ); err != nil {
2104
- return fmt .Errorf ("starting EC2 Instance (%s): waiting for completion: %w" , id , err )
2120
+ if err := startInstance (ctx , conn , id , true , InstanceStartTimeout ); err != nil {
2121
+ return err
2105
2122
}
2106
2123
2107
2124
return nil
@@ -2977,20 +2994,34 @@ func buildInstanceOpts(ctx context.Context, d *schema.ResourceData, meta interfa
2977
2994
}
2978
2995
2979
2996
// startInstance starts an EC2 instance and waits for the instance to start.
2980
- func startInstance (ctx context.Context , conn * ec2.EC2 , id string , timeout time.Duration ) error {
2997
+ func startInstance (ctx context.Context , conn * ec2.EC2 , id string , retry bool , timeout time.Duration ) error {
2998
+ var err error
2999
+
2981
3000
tflog .Info (ctx , "Starting EC2 Instance" , map [string ]any {
2982
3001
"ec2_instance_id" : id ,
2983
3002
})
2984
- _ , err := conn .StartInstancesWithContext (ctx , & ec2.StartInstancesInput {
2985
- InstanceIds : aws .StringSlice ([]string {id }),
2986
- })
3003
+ if retry {
3004
+ // Reference: https://github.com/hashicorp/terraform-provider-aws/issues/16433.
3005
+ _ , err = tfresource .RetryWhenAWSErrMessageContains (ctx , ec2PropagationTimeout ,
3006
+ func () (interface {}, error ) {
3007
+ return conn .StartInstancesWithContext (ctx , & ec2.StartInstancesInput {
3008
+ InstanceIds : aws .StringSlice ([]string {id }),
3009
+ })
3010
+ },
3011
+ errCodeInvalidParameterValue , "LaunchPlan instance type does not match attribute value" ,
3012
+ )
3013
+ } else {
3014
+ _ , err = conn .StartInstancesWithContext (ctx , & ec2.StartInstancesInput {
3015
+ InstanceIds : aws .StringSlice ([]string {id }),
3016
+ })
3017
+ }
2987
3018
2988
3019
if err != nil {
2989
3020
return fmt .Errorf ("starting EC2 Instance (%s): %w" , id , err )
2990
3021
}
2991
3022
2992
3023
if _ , err := waitInstanceStarted (ctx , conn , id , timeout ); err != nil {
2993
- return fmt .Errorf ("starting EC2 Instance (%s): waiting for completion : %w" , id , err )
3024
+ return fmt .Errorf ("waiting for EC2 Instance (%s) start : %w" , id , err )
2994
3025
}
2995
3026
2996
3027
return nil
@@ -3003,6 +3034,7 @@ func stopInstance(ctx context.Context, conn *ec2.EC2, id string, force bool, tim
3003
3034
"force" : force ,
3004
3035
})
3005
3036
_ , err := conn .StopInstancesWithContext (ctx , & ec2.StopInstancesInput {
3037
+ Force : aws .Bool (force ),
3006
3038
InstanceIds : aws .StringSlice ([]string {id }),
3007
3039
})
3008
3040
@@ -3011,7 +3043,7 @@ func stopInstance(ctx context.Context, conn *ec2.EC2, id string, force bool, tim
3011
3043
}
3012
3044
3013
3045
if _ , err := waitInstanceStopped (ctx , conn , id , timeout ); err != nil {
3014
- return fmt .Errorf ("stopping EC2 Instance (%s): waiting for completion : %w" , id , err )
3046
+ return fmt .Errorf ("waiting for EC2 Instance (%s) stop : %w" , id , err )
3015
3047
}
3016
3048
3017
3049
return nil
@@ -3114,7 +3146,7 @@ func waitInstanceReady(ctx context.Context, conn *ec2.EC2, id string, timeout ti
3114
3146
return nil , err
3115
3147
}
3116
3148
3117
- func waitInstanceStarted (ctx context.Context , conn * ec2.EC2 , id string , timeout time.Duration ) (* ec2.Instance , error ) { //nolint:unparam
3149
+ func waitInstanceStarted (ctx context.Context , conn * ec2.EC2 , id string , timeout time.Duration ) (* ec2.Instance , error ) {
3118
3150
stateConf := & retry.StateChangeConf {
3119
3151
Pending : []string {ec2 .InstanceStateNamePending , ec2 .InstanceStateNameStopped },
3120
3152
Target : []string {ec2 .InstanceStateNameRunning },
0 commit comments