From 147b47d7eb8ff14fca36e03e8f03dc1d21c6c751 Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 3 Jan 2023 10:00:37 -0500 Subject: [PATCH 01/18] ec2: Amend Find, add FindInstanceStateById --- internal/service/ec2/find.go | 26 ++++++++++++++++++ internal/service/ec2/wait.go | 51 ++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/internal/service/ec2/find.go b/internal/service/ec2/find.go index 05d3cef7ecf..da83c6936a9 100644 --- a/internal/service/ec2/find.go +++ b/internal/service/ec2/find.go @@ -10,6 +10,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go/service/lightsail" "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" @@ -6539,3 +6540,28 @@ func FindNetworkPerformanceMetricSubscriptionByFourPartKey(ctx context.Context, return nil, &resource.NotFoundError{} } + +func FindInstanceStateById(ctx context.Context, conn *ec2.EC2, id string) (*ec2.InstanceState, error) { + in := &ec2.DescribeInstancesInput{ + InstanceIds: aws.StringSlice([]string{id}), + } + + out, err := conn.DescribeInstancesWithContext(ctx, in) + + if tfawserr.ErrCodeEquals(err, lightsail.ErrCodeNotFoundException) { + return nil, &resource.NotFoundError{ + LastError: err, + LastRequest: in, + } + } + + if err != nil { + return nil, err + } + + if out == nil || len(out.Reservations) == 0 || len(out.Reservations[0].Instances) == 0 || out.Reservations[0].Instances[0].State == nil { + return nil, tfresource.NewEmptyResultError(in) + } + + return out.Reservations[0].Instances[0].State, nil +} diff --git a/internal/service/ec2/wait.go b/internal/service/ec2/wait.go index 7f892303b89..4f7ba63f0cf 100644 --- a/internal/service/ec2/wait.go +++ b/internal/service/ec2/wait.go @@ -2979,3 +2979,54 @@ func WaitIPAMScopeUpdated(conn *ec2.EC2, id string, timeout time.Duration) (*ec2 return nil, err } + +func WaitInstanceStoppedWithContext(ctx context.Context, conn *ec2.EC2, id string, timeout time.Duration) (*ec2.Instance, error) { + stateConf := &resource.StateChangeConf{ + Pending: []string{ + ec2.InstanceStateNamePending, + ec2.InstanceStateNameRunning, + ec2.InstanceStateNameShuttingDown, + ec2.InstanceStateNameStopping, + }, + Target: []string{ec2.InstanceStateNameStopped}, + Refresh: StatusInstanceState(conn, id), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 3 * time.Second, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*ec2.Instance); ok { + if stateReason := output.StateReason; stateReason != nil { + tfresource.SetLastError(err, errors.New(aws.StringValue(stateReason.Message))) + } + + return output, err + } + + return nil, err +} + +func WaitInstanceStartedWithContext(ctx context.Context, conn *ec2.EC2, id string, timeout time.Duration) (*ec2.Instance, error) { + stateConf := &resource.StateChangeConf{ + Pending: []string{ec2.InstanceStateNamePending, ec2.InstanceStateNameStopped}, + Target: []string{ec2.InstanceStateNameRunning}, + Refresh: StatusInstanceState(conn, id), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 3 * time.Second, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*ec2.Instance); ok { + if stateReason := output.StateReason; stateReason != nil { + tfresource.SetLastError(err, errors.New(aws.StringValue(stateReason.Message))) + } + + return output, err + } + + return nil, err +} From 3a352e240009f459cc5b8f44337d979d88913827 Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 3 Jan 2023 10:00:54 -0500 Subject: [PATCH 02/18] ec2: Add instance_state --- internal/provider/provider.go | 1 + internal/service/ec2/consts.go | 5 + internal/service/ec2/instance_state.go | 150 +++++++++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 internal/service/ec2/instance_state.go diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 3a599e0c48a..279bcfe6882 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -1383,6 +1383,7 @@ func New(ctx context.Context) (*schema.Provider, error) { "aws_eip_association": ec2.ResourceEIPAssociation(), "aws_flow_log": ec2.ResourceFlowLog(), "aws_instance": ec2.ResourceInstance(), + "aws_instance_state": ec2.ResourceInstanceState(), "aws_internet_gateway": ec2.ResourceInternetGateway(), "aws_internet_gateway_attachment": ec2.ResourceInternetGatewayAttachment(), "aws_key_pair": ec2.ResourceKeyPair(), diff --git a/internal/service/ec2/consts.go b/internal/service/ec2/consts.go index 931579188a3..737fd9225f3 100644 --- a/internal/service/ec2/consts.go +++ b/internal/service/ec2/consts.go @@ -276,3 +276,8 @@ func securityGroupRuleType_Values() []string { securityGroupRuleTypeIngress, } } + +const ( + ResInstance = "Instance" + ResInstanceState = "Instance State" +) diff --git a/internal/service/ec2/instance_state.go b/internal/service/ec2/instance_state.go new file mode 100644 index 00000000000..79ff4a2fc19 --- /dev/null +++ b/internal/service/ec2/instance_state.go @@ -0,0 +1,150 @@ +package ec2 + +import ( + "context" + "log" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/ec2" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func ResourceInstanceState() *schema.Resource { + return &schema.Resource{ + CreateWithoutTimeout: resourceInstanceStateCreate, + ReadWithoutTimeout: resourceInstanceStateRead, + UpdateWithoutTimeout: resourceInstanceStateUpdate, + DeleteWithoutTimeout: resourceInstanceStateDelete, + + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + ForceNew: true, + Required: true, + }, + "state": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ec2.InstanceStateNameRunning, ec2.InstanceStateNameStopped}, false), + }, + "force": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + }, + } +} + +func resourceInstanceStateCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).EC2Conn() + instanceId := d.Get("instance_id").(string) + instance, instanceErr := FindInstanceByID(conn, instanceId) + + if instanceErr != nil { + return create.DiagError(names.EC2, create.ErrActionReading, ResInstance, instanceId, instanceErr) + } + + err := UpdateInstanceState(ctx, conn, instanceId, aws.StringValue(instance.State.Name), d.Get("state").(string), d.Get("force").(bool)) + + if err != nil { + return err + } + + d.SetId(d.Get("instance_id").(string)) + + return resourceInstanceStateRead(ctx, d, meta) + +} + +func resourceInstanceStateRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).EC2Conn() + + state, err := FindInstanceStateById(ctx, conn, d.Id()) + + if !d.IsNewResource() && tfresource.NotFound(err) { + create.LogNotFoundRemoveState(names.EC2, create.ErrActionReading, ResInstanceState, d.Id()) + d.SetId("") + return nil + } + + if err != nil { + return create.DiagError(names.EC2, create.ErrActionReading, ResInstanceState, d.Id(), err) + } + + d.Set("instance_id", d.Id()) + d.Set("state", state.Name) + d.Set("force", d.Get("force").(bool)) + + return nil +} + +func resourceInstanceStateUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).EC2Conn() + + if d.HasChange("state") { + o, n := d.GetChange("state") + err := UpdateInstanceState(ctx, conn, d.Id(), o.(string), n.(string), d.Get("force").(bool)) + + if err != nil { + return err + } + } + + return resourceInstanceStateRead(ctx, d, meta) +} + +func resourceInstanceStateDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + log.Printf("[DEBUG] %s %s deleting an aws_instance_state resource only stops managing instance state, The Instance is left in its current state.: %s", names.EC2, ResInstanceState, d.Id()) + + return nil +} + +func UpdateInstanceState(ctx context.Context, conn *ec2.EC2, id string, currentState string, configuredState string, force bool) diag.Diagnostics { + if currentState == configuredState { + return nil + } + + if configuredState == "running" { + if err := StopInstanceWithContext(ctx, conn, id, force, InstanceStopTimeout); err != nil { + return err + } + } + + if configuredState == "stopped" { + if _, err := WaitInstanceStartedWithContext(ctx, conn, id, InstanceStartTimeout); err != nil { + return create.DiagError(names.EC2, "starting Instance", ResInstance, id, err) + } + } + + return nil +} + +func StopInstanceWithContext(ctx context.Context, conn *ec2.EC2, id string, force bool, timeout time.Duration) diag.Diagnostics { + log.Printf("[INFO] Stopping EC2 Instance: %s, force: %t", id, force) + _, err := conn.StopInstancesWithContext(ctx, &ec2.StopInstancesInput{ + InstanceIds: aws.StringSlice([]string{id}), + Force: aws.Bool(force), + }) + + if err != nil { + return create.DiagError(names.EC2, "stopping Instance", ResInstance, id, err) + } + + if _, err := WaitInstanceStoppedWithContext(ctx, conn, id, timeout); err != nil { + return create.DiagError(names.EC2, "waiting for instance to stop", ResInstance, id, err) + } + + return nil +} From 987ae3a74ba008712dd871081172bafe42d1c211 Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 3 Jan 2023 10:01:06 -0500 Subject: [PATCH 03/18] ec2: Add instance_state_test --- internal/service/ec2/instance_state_test.go | 170 ++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 internal/service/ec2/instance_state_test.go diff --git a/internal/service/ec2/instance_state_test.go b/internal/service/ec2/instance_state_test.go new file mode 100644 index 00000000000..ef18e88bceb --- /dev/null +++ b/internal/service/ec2/instance_state_test.go @@ -0,0 +1,170 @@ +package ec2_test + +import ( + "context" + "errors" + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/service/ec2" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/create" + tfec2 "github.com/hashicorp/terraform-provider-aws/internal/service/ec2" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccEC2InstanceState_basic(t *testing.T) { + resourceName := "aws_instance_state.test" + state := "stopped" + force := "false" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckInstanceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccInstanceStateConfig_basic(state, force), + Check: resource.ComposeTestCheckFunc( + testAccCheckInstanceStateExists(resourceName), + resource.TestCheckResourceAttrSet(resourceName, "instance_id"), + resource.TestCheckResourceAttr(resourceName, "state", state), + ), + }, + }, + }) +} + +func TestAccEC2InstanceState_state(t *testing.T) { + resourceName := "aws_instance_state.test" + stateStopped := "stopped" + stateRunning := "running" + force := "false" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckInstanceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccInstanceStateConfig_basic(stateStopped, force), + Check: resource.ComposeTestCheckFunc( + testAccCheckInstanceStateExists(resourceName), + resource.TestCheckResourceAttrSet(resourceName, "instance_id"), + resource.TestCheckResourceAttr(resourceName, "state", stateStopped), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccInstanceStateConfig_basic(stateRunning, force), + Check: resource.ComposeTestCheckFunc( + testAccCheckInstanceStateExists(resourceName), + resource.TestCheckResourceAttrSet(resourceName, "instance_id"), + resource.TestCheckResourceAttr(resourceName, "state", stateRunning), + ), + }, + }, + }) +} +func TestAccEC2InstanceState_disappears_Instance(t *testing.T) { + resourceName := "aws_instance_state.test" + parentResourceName := "aws_instance.test" + state := "stopped" + force := "false" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckInstanceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccInstanceStateConfig_basic(state, force), + Check: resource.ComposeTestCheckFunc( + testAccCheckInstanceStateExists(resourceName), + acctest.CheckResourceDisappears(acctest.Provider, tfec2.ResourceInstance(), parentResourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckInstanceStateExists(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return errors.New("No EC2InstanceState ID is set") + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).EC2Conn() + + out, err := tfec2.FindInstanceStateById(context.Background(), conn, rs.Primary.ID) + + if err != nil { + return err + } + + if out == nil { + return fmt.Errorf("Instance State %q does not exist", rs.Primary.ID) + } + + return nil + } +} + +func testAccCheckInstanceStateDestroy(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_instance_state" { + continue + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).EC2Conn() + + _, err := tfec2.FindInstanceStateById(context.Background(), conn, rs.Primary.ID) + + if tfresource.NotFound(err) { + continue + } + + if err != nil { + return err + } + + return create.Error(names.EC2, create.ErrActionCheckingDestroyed, tfec2.ResInstanceState, rs.Primary.ID, errors.New("still exists")) + } + + return nil +} + +func testAccInstanceStateConfig_basic(state string, force string) string { + return acctest.ConfigCompose( + acctest.ConfigLatestAmazonLinuxHVMEBSAMI(), + acctest.AvailableEC2InstanceTypeForRegion("t3.micro", "t2.micro", "t1.micro", "m1.small"), + fmt.Sprintf(` +resource "aws_instance" "test" { + ami = data.aws_ami.amzn-ami-minimal-hvm-ebs.id + instance_type = data.aws_ec2_instance_type_offering.available.instance_type +} + +resource "aws_instance_state" "test" { + instance_id = aws_instance.test.id + state = %[1]q + force = %[2]s +} +`, state, force)) +} From b5601eb514628142a52d0e4ef493585a92c3d7d4 Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 3 Jan 2023 11:00:31 -0500 Subject: [PATCH 04/18] ec2: Amend instance_state_tests, resolve failing tests --- internal/service/ec2/instance_state.go | 36 +++++++++++++++++++++----- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/internal/service/ec2/instance_state.go b/internal/service/ec2/instance_state.go index 79ff4a2fc19..ac267715f68 100644 --- a/internal/service/ec2/instance_state.go +++ b/internal/service/ec2/instance_state.go @@ -24,7 +24,7 @@ func ResourceInstanceState() *schema.Resource { DeleteWithoutTimeout: resourceInstanceStateDelete, Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, + StateContext: schema.ImportStatePassthroughContext, }, Schema: map[string]*schema.Schema{ @@ -50,7 +50,8 @@ func ResourceInstanceState() *schema.Resource { func resourceInstanceStateCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.AWSClient).EC2Conn() instanceId := d.Get("instance_id").(string) - instance, instanceErr := FindInstanceByID(conn, instanceId) + + instance, instanceErr := WaitInstanceReadyWithContext(ctx, conn, instanceId, InstanceReadyTimeout) if instanceErr != nil { return create.DiagError(names.EC2, create.ErrActionReading, ResInstance, instanceId, instanceErr) @@ -93,6 +94,12 @@ func resourceInstanceStateRead(ctx context.Context, d *schema.ResourceData, meta func resourceInstanceStateUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.AWSClient).EC2Conn() + instance, instanceErr := WaitInstanceReadyWithContext(ctx, conn, d.Id(), InstanceReadyTimeout) + + if instanceErr != nil { + return create.DiagError(names.EC2, create.ErrActionReading, ResInstance, aws.StringValue(instance.InstanceId), instanceErr) + } + if d.HasChange("state") { o, n := d.GetChange("state") err := UpdateInstanceState(ctx, conn, d.Id(), o.(string), n.(string), d.Get("force").(bool)) @@ -116,15 +123,15 @@ func UpdateInstanceState(ctx context.Context, conn *ec2.EC2, id string, currentS return nil } - if configuredState == "running" { + if configuredState == "stopped" { if err := StopInstanceWithContext(ctx, conn, id, force, InstanceStopTimeout); err != nil { return err } } - if configuredState == "stopped" { - if _, err := WaitInstanceStartedWithContext(ctx, conn, id, InstanceStartTimeout); err != nil { - return create.DiagError(names.EC2, "starting Instance", ResInstance, id, err) + if configuredState == "running" { + if err := StartInstanceWithContext(ctx, conn, id, InstanceStartTimeout); err != nil { + return err } } @@ -148,3 +155,20 @@ func StopInstanceWithContext(ctx context.Context, conn *ec2.EC2, id string, forc return nil } + +func StartInstanceWithContext(ctx context.Context, conn *ec2.EC2, id string, timeout time.Duration) diag.Diagnostics { + log.Printf("[INFO] Starting EC2 Instance: %s", id) + _, err := conn.StartInstancesWithContext(ctx, &ec2.StartInstancesInput{ + InstanceIds: aws.StringSlice([]string{id}), + }) + + if err != nil { + return create.DiagError(names.EC2, "starting Instance", ResInstance, id, err) + } + + if _, err := WaitInstanceStartedWithContext(ctx, conn, id, timeout); err != nil { + return create.DiagError(names.EC2, "waiting for instance to start", ResInstance, id, err) + } + + return nil +} From 378b773108ede0accca38cc036218b1852054190 Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 3 Jan 2023 11:00:48 -0500 Subject: [PATCH 05/18] ec2: Amend wait, add WaitInstanceReadyWithContext --- internal/service/ec2/wait.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/internal/service/ec2/wait.go b/internal/service/ec2/wait.go index 4f7ba63f0cf..0b73281e617 100644 --- a/internal/service/ec2/wait.go +++ b/internal/service/ec2/wait.go @@ -3030,3 +3030,26 @@ func WaitInstanceStartedWithContext(ctx context.Context, conn *ec2.EC2, id strin return nil, err } + +func WaitInstanceReadyWithContext(ctx context.Context, conn *ec2.EC2, id string, timeout time.Duration) (*ec2.Instance, error) { + stateConf := &resource.StateChangeConf{ + Pending: []string{ec2.InstanceStateNamePending, ec2.InstanceStateNameStopping}, + Target: []string{ec2.InstanceStateNameRunning, ec2.InstanceStateNameStopped}, + Refresh: StatusInstanceState(conn, id), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 3 * time.Second, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*ec2.Instance); ok { + if stateReason := output.StateReason; stateReason != nil { + tfresource.SetLastError(err, errors.New(aws.StringValue(stateReason.Message))) + } + + return output, err + } + + return nil, err +} From dd49081d9540df4469d3b4d08092bda287436be1 Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 3 Jan 2023 11:37:31 -0500 Subject: [PATCH 06/18] website: Add ec2_instance_state --- internal/service/ec2/instance_state_test.go | 6 +- .../docs/r/ec2_instance_state.html.markdown | 67 +++++++++++++++++++ 2 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 website/docs/r/ec2_instance_state.html.markdown diff --git a/internal/service/ec2/instance_state_test.go b/internal/service/ec2/instance_state_test.go index ef18e88bceb..e9b9359b366 100644 --- a/internal/service/ec2/instance_state_test.go +++ b/internal/service/ec2/instance_state_test.go @@ -162,9 +162,9 @@ resource "aws_instance" "test" { } resource "aws_instance_state" "test" { - instance_id = aws_instance.test.id - state = %[1]q - force = %[2]s + instance_id = aws_instance.test.id + state = %[1]q + force = %[2]s } `, state, force)) } diff --git a/website/docs/r/ec2_instance_state.html.markdown b/website/docs/r/ec2_instance_state.html.markdown new file mode 100644 index 00000000000..31db6412f1e --- /dev/null +++ b/website/docs/r/ec2_instance_state.html.markdown @@ -0,0 +1,67 @@ +--- +subcategory: "EC2 (Elastic Compute Cloud)" +layout: "aws" +page_title: "AWS: aws_instance" +description: |- + Provides an EC2 instance state resource. This allows managing an instance power state. +--- + +# Resource: aws_instance_state + +Provides an EC2 instance state resource. This allows managing an instance power state. + +## Example Usage + +```terraform +data "aws_ami" "ubuntu" { + most_recent = true + + filter { + name = "name" + values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"] + } + + filter { + name = "virtualization-type" + values = ["hvm"] + } + + owners = ["099720109477"] # Canonical +} + +resource "aws_instance" "test" { + ami = data.aws_ami.ubuntu.id + instance_type = "t3.micro" + + tags = { + Name = "HelloWorld" + } +} + +resource "aws_instance_state" "test" { + instance_id = aws_instance.test.id + state = "stopped" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `instance_id` - (Required) The ID of the instance. +* `state` - (Required) - The state of the instance. Valid Options: `stopped`, `running`. +* `force` - (Optional) Forces the instances to stop. The instances do not have an opportunity to flush file system caches or file system metadata. If you use this option, you must perform file system check and repair procedures. This option is not recommended for Windows instances. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The ID of the instance. (matches `instance_id`). + +## Import + +`aws_instance_state` can be imported by using the `instance_id` attribute, e.g., + +``` +$ terraform import aws_instance_state.test i-02cae6557dfcf2f96 +``` From 40c1119df555961891cfe9aeb26a8131e9624512 Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 3 Jan 2023 11:52:22 -0500 Subject: [PATCH 07/18] website: Amend ec2_instance_state, fix page_title --- website/docs/r/ec2_instance_state.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/ec2_instance_state.html.markdown b/website/docs/r/ec2_instance_state.html.markdown index 31db6412f1e..969781a7827 100644 --- a/website/docs/r/ec2_instance_state.html.markdown +++ b/website/docs/r/ec2_instance_state.html.markdown @@ -1,7 +1,7 @@ --- subcategory: "EC2 (Elastic Compute Cloud)" layout: "aws" -page_title: "AWS: aws_instance" +page_title: "AWS: aws_instance_state" description: |- Provides an EC2 instance state resource. This allows managing an instance power state. --- From 757267f31acb44de27367a2b0d3d354c3dd18020 Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 3 Jan 2023 12:03:32 -0500 Subject: [PATCH 08/18] ec2: Amend instance_state, golang-ci --- internal/service/ec2/instance_state.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/service/ec2/instance_state.go b/internal/service/ec2/instance_state.go index ac267715f68..41dddc7e263 100644 --- a/internal/service/ec2/instance_state.go +++ b/internal/service/ec2/instance_state.go @@ -66,7 +66,6 @@ func resourceInstanceStateCreate(ctx context.Context, d *schema.ResourceData, me d.SetId(d.Get("instance_id").(string)) return resourceInstanceStateRead(ctx, d, meta) - } func resourceInstanceStateRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { From 768780f5c85f52e596883d33d7672a3ff388f30e Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 3 Jan 2023 12:04:46 -0500 Subject: [PATCH 09/18] changelog: Add 28639, change log --- .changelog/28639.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/28639.txt diff --git a/.changelog/28639.txt b/.changelog/28639.txt new file mode 100644 index 00000000000..89fccade98c --- /dev/null +++ b/.changelog/28639.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_instance_state +``` \ No newline at end of file From 3a8a24a0f3b4e07a2c5b34e81692230cf6b36b41 Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 3 Jan 2023 12:32:03 -0500 Subject: [PATCH 10/18] website: Rename instance_state docs --- internal/service/ec2/instance_state_test.go | 27 ------------------- ....markdown => instance_state.html.markdown} | 0 2 files changed, 27 deletions(-) rename website/docs/r/{ec2_instance_state.html.markdown => instance_state.html.markdown} (100%) diff --git a/internal/service/ec2/instance_state_test.go b/internal/service/ec2/instance_state_test.go index e9b9359b366..59db8276548 100644 --- a/internal/service/ec2/instance_state_test.go +++ b/internal/service/ec2/instance_state_test.go @@ -11,10 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" - "github.com/hashicorp/terraform-provider-aws/internal/create" tfec2 "github.com/hashicorp/terraform-provider-aws/internal/service/ec2" - "github.com/hashicorp/terraform-provider-aws/internal/tfresource" - "github.com/hashicorp/terraform-provider-aws/names" ) func TestAccEC2InstanceState_basic(t *testing.T) { @@ -127,30 +124,6 @@ func testAccCheckInstanceStateExists(n string) resource.TestCheckFunc { } } -func testAccCheckInstanceStateDestroy(s *terraform.State) error { - for _, rs := range s.RootModule().Resources { - if rs.Type != "aws_instance_state" { - continue - } - - conn := acctest.Provider.Meta().(*conns.AWSClient).EC2Conn() - - _, err := tfec2.FindInstanceStateById(context.Background(), conn, rs.Primary.ID) - - if tfresource.NotFound(err) { - continue - } - - if err != nil { - return err - } - - return create.Error(names.EC2, create.ErrActionCheckingDestroyed, tfec2.ResInstanceState, rs.Primary.ID, errors.New("still exists")) - } - - return nil -} - func testAccInstanceStateConfig_basic(state string, force string) string { return acctest.ConfigCompose( acctest.ConfigLatestAmazonLinuxHVMEBSAMI(), diff --git a/website/docs/r/ec2_instance_state.html.markdown b/website/docs/r/instance_state.html.markdown similarity index 100% rename from website/docs/r/ec2_instance_state.html.markdown rename to website/docs/r/instance_state.html.markdown From 3be544cafee91ed43ab4706e8321faa6f3a02822 Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 3 Jan 2023 14:20:29 -0500 Subject: [PATCH 11/18] ec2: Amend Find, update FindInstanceStateById to use status api --- internal/service/ec2/find.go | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/internal/service/ec2/find.go b/internal/service/ec2/find.go index da83c6936a9..5cf18492fc7 100644 --- a/internal/service/ec2/find.go +++ b/internal/service/ec2/find.go @@ -10,7 +10,6 @@ import ( "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/lightsail" "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" @@ -6542,13 +6541,14 @@ func FindNetworkPerformanceMetricSubscriptionByFourPartKey(ctx context.Context, } func FindInstanceStateById(ctx context.Context, conn *ec2.EC2, id string) (*ec2.InstanceState, error) { - in := &ec2.DescribeInstancesInput{ - InstanceIds: aws.StringSlice([]string{id}), + in := &ec2.DescribeInstanceStatusInput{ + InstanceIds: aws.StringSlice([]string{id}), + IncludeAllInstances: aws.Bool(true), } - out, err := conn.DescribeInstancesWithContext(ctx, in) + out, err := conn.DescribeInstanceStatusWithContext(ctx, in) - if tfawserr.ErrCodeEquals(err, lightsail.ErrCodeNotFoundException) { + if tfawserr.ErrCodeEquals(err, errCodeInvalidInstanceIDNotFound) { return nil, &resource.NotFoundError{ LastError: err, LastRequest: in, @@ -6559,9 +6559,22 @@ func FindInstanceStateById(ctx context.Context, conn *ec2.EC2, id string) (*ec2. return nil, err } - if out == nil || len(out.Reservations) == 0 || len(out.Reservations[0].Instances) == 0 || out.Reservations[0].Instances[0].State == nil { + if out == nil || len(out.InstanceStatuses) == 0 { + return nil, tfresource.NewEmptyResultError(in) + } + + instanceState := out.InstanceStatuses[0].InstanceState + + if instanceState == nil || aws.StringValue(instanceState.Name) == ec2.InstanceStateNameTerminated { return nil, tfresource.NewEmptyResultError(in) } - return out.Reservations[0].Instances[0].State, nil + // Eventual consistency check. + if aws.StringValue(out.InstanceStatuses[0].InstanceId) != id { + return nil, &resource.NotFoundError{ + LastRequest: in, + } + } + + return instanceState, nil } From 122e819edb3b1991897ee77c083e59fa7d28f7c4 Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 3 Jan 2023 15:39:02 -0500 Subject: [PATCH 12/18] website: Amend instance_sate, add warning about instance user data --- website/docs/r/instance_state.html.markdown | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/website/docs/r/instance_state.html.markdown b/website/docs/r/instance_state.html.markdown index 969781a7827..f904cc189f8 100644 --- a/website/docs/r/instance_state.html.markdown +++ b/website/docs/r/instance_state.html.markdown @@ -10,6 +10,8 @@ description: |- Provides an EC2 instance state resource. This allows managing an instance power state. +~> **NOTE on Instance State Management:** As terraform currently does not support any method to validate that instance user data has completed applying. Use caution to ensure your instance user data applies successfully on creation before using the `aws_instance_state` resource to stop the instance. + ## Example Usage ```terraform @@ -50,7 +52,7 @@ The following arguments are supported: * `instance_id` - (Required) The ID of the instance. * `state` - (Required) - The state of the instance. Valid Options: `stopped`, `running`. -* `force` - (Optional) Forces the instances to stop. The instances do not have an opportunity to flush file system caches or file system metadata. If you use this option, you must perform file system check and repair procedures. This option is not recommended for Windows instances. +* `force` - (Optional) When `true`, forces the instances to stop. The instances do not have an opportunity to flush file system caches or file system metadata. If you use this option, you must perform file system check and repair procedures. This option is not recommended for Windows instances. Defaults to `false`. ## Attributes Reference From 3a95d40e232bfd2383270ef6e291a5ce610c8d9a Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 3 Jan 2023 15:45:49 -0500 Subject: [PATCH 13/18] website: lint fix instance_state --- website/docs/r/instance_state.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/instance_state.html.markdown b/website/docs/r/instance_state.html.markdown index f904cc189f8..d95e32d8e4b 100644 --- a/website/docs/r/instance_state.html.markdown +++ b/website/docs/r/instance_state.html.markdown @@ -10,7 +10,7 @@ description: |- Provides an EC2 instance state resource. This allows managing an instance power state. -~> **NOTE on Instance State Management:** As terraform currently does not support any method to validate that instance user data has completed applying. Use caution to ensure your instance user data applies successfully on creation before using the `aws_instance_state` resource to stop the instance. +~> **NOTE on Instance State Management:** As terraform currently does not support any method to validate that instance user data has completed applying. Use caution to ensure your instance user data applies successfully on creation before using the `aws_instance_state` resource to stop the instance. ## Example Usage From 5eb17c520698d81fe6bc88405510227b558c6bad Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Tue, 3 Jan 2023 23:34:25 -0500 Subject: [PATCH 14/18] Add timeouts, rename resource --- .../ec2/{instance_state.go => ec2_instance_state.go} | 12 +++++++++--- ...ance_state_test.go => ec2_instance_state_test.go} | 8 ++++---- 2 files changed, 13 insertions(+), 7 deletions(-) rename internal/service/ec2/{instance_state.go => ec2_instance_state.go} (91%) rename internal/service/ec2/{instance_state_test.go => ec2_instance_state_test.go} (95%) diff --git a/internal/service/ec2/instance_state.go b/internal/service/ec2/ec2_instance_state.go similarity index 91% rename from internal/service/ec2/instance_state.go rename to internal/service/ec2/ec2_instance_state.go index 41dddc7e263..16e1472c99c 100644 --- a/internal/service/ec2/instance_state.go +++ b/internal/service/ec2/ec2_instance_state.go @@ -27,6 +27,12 @@ func ResourceInstanceState() *schema.Resource { StateContext: schema.ImportStatePassthroughContext, }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(10 * time.Minute), + Update: schema.DefaultTimeout(10 * time.Minute), + Delete: schema.DefaultTimeout(1 * time.Minute), + }, + Schema: map[string]*schema.Schema{ "instance_id": { Type: schema.TypeString, @@ -51,7 +57,7 @@ func resourceInstanceStateCreate(ctx context.Context, d *schema.ResourceData, me conn := meta.(*conns.AWSClient).EC2Conn() instanceId := d.Get("instance_id").(string) - instance, instanceErr := WaitInstanceReadyWithContext(ctx, conn, instanceId, InstanceReadyTimeout) + instance, instanceErr := WaitInstanceReadyWithContext(ctx, conn, instanceId, d.Timeout(schema.TimeoutCreate)) if instanceErr != nil { return create.DiagError(names.EC2, create.ErrActionReading, ResInstance, instanceId, instanceErr) @@ -93,7 +99,7 @@ func resourceInstanceStateRead(ctx context.Context, d *schema.ResourceData, meta func resourceInstanceStateUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.AWSClient).EC2Conn() - instance, instanceErr := WaitInstanceReadyWithContext(ctx, conn, d.Id(), InstanceReadyTimeout) + instance, instanceErr := WaitInstanceReadyWithContext(ctx, conn, d.Id(), d.Timeout(schema.TimeoutUpdate)) if instanceErr != nil { return create.DiagError(names.EC2, create.ErrActionReading, ResInstance, aws.StringValue(instance.InstanceId), instanceErr) @@ -112,7 +118,7 @@ func resourceInstanceStateUpdate(ctx context.Context, d *schema.ResourceData, me } func resourceInstanceStateDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - log.Printf("[DEBUG] %s %s deleting an aws_instance_state resource only stops managing instance state, The Instance is left in its current state.: %s", names.EC2, ResInstanceState, d.Id()) + log.Printf("[DEBUG] %s %s deleting an aws_ec2_instance_state resource only stops managing instance state, The Instance is left in its current state.: %s", names.EC2, ResInstanceState, d.Id()) return nil } diff --git a/internal/service/ec2/instance_state_test.go b/internal/service/ec2/ec2_instance_state_test.go similarity index 95% rename from internal/service/ec2/instance_state_test.go rename to internal/service/ec2/ec2_instance_state_test.go index 59db8276548..229e6bb0f4a 100644 --- a/internal/service/ec2/instance_state_test.go +++ b/internal/service/ec2/ec2_instance_state_test.go @@ -15,7 +15,7 @@ import ( ) func TestAccEC2InstanceState_basic(t *testing.T) { - resourceName := "aws_instance_state.test" + resourceName := "aws_ec2_instance_state.test" state := "stopped" force := "false" @@ -38,7 +38,7 @@ func TestAccEC2InstanceState_basic(t *testing.T) { } func TestAccEC2InstanceState_state(t *testing.T) { - resourceName := "aws_instance_state.test" + resourceName := "aws_ec2_instance_state.test" stateStopped := "stopped" stateRunning := "running" force := "false" @@ -74,7 +74,7 @@ func TestAccEC2InstanceState_state(t *testing.T) { }) } func TestAccEC2InstanceState_disappears_Instance(t *testing.T) { - resourceName := "aws_instance_state.test" + resourceName := "aws_ec2_instance_state.test" parentResourceName := "aws_instance.test" state := "stopped" force := "false" @@ -134,7 +134,7 @@ resource "aws_instance" "test" { instance_type = data.aws_ec2_instance_type_offering.available.instance_type } -resource "aws_instance_state" "test" { +resource "aws_ec2_instance_state" "test" { instance_id = aws_instance.test.id state = %[1]q force = %[2]s From c4a006e28c5c282730e056cfcb3e34cbc29ba11b Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Tue, 3 Jan 2023 23:34:53 -0500 Subject: [PATCH 15/18] docs: Rename resource --- .../docs/r/ec2_instance_state.html.markdown | 77 +++++++++++++++++++ website/docs/r/instance_state.html.markdown | 69 ----------------- 2 files changed, 77 insertions(+), 69 deletions(-) create mode 100644 website/docs/r/ec2_instance_state.html.markdown delete mode 100644 website/docs/r/instance_state.html.markdown diff --git a/website/docs/r/ec2_instance_state.html.markdown b/website/docs/r/ec2_instance_state.html.markdown new file mode 100644 index 00000000000..35ef0b574c9 --- /dev/null +++ b/website/docs/r/ec2_instance_state.html.markdown @@ -0,0 +1,77 @@ +--- +subcategory: "EC2 (Elastic Compute Cloud)" +layout: "aws" +page_title: "AWS: aws_ec2_instance_state" +description: |- + Provides an EC2 instance state resource. This allows managing an instance power state. +--- + +# Resource: aws_ec2_instance_state + +Provides an EC2 instance state resource. This allows managing an instance power state. + +~> **NOTE on Instance State Management:** AWS does not currently have an EC2 API operation to determine an instance has finished processing user data. As a result, this resource can interfere with user data processing. For example, this resource may stop an instance while the user data script is in mid run. + +## Example Usage + +```terraform +data "aws_ami" "ubuntu" { + most_recent = true + + filter { + name = "name" + values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"] + } + + filter { + name = "virtualization-type" + values = ["hvm"] + } + + owners = ["099720109477"] # Canonical +} + +resource "aws_instance" "test" { + ami = data.aws_ami.ubuntu.id + instance_type = "t3.micro" + + tags = { + Name = "HelloWorld" + } +} + +resource "aws_ec2_instance_state" "test" { + instance_id = aws_instance.test.id + state = "stopped" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `instance_id` - (Required) ID of the instance. +* `state` - (Required) - State of the instance. Valid values are `stopped`, `running`. +* `force` - (Optional) Whether to request a forced stop when `state` is `stopped`. Otherwise (_i.e._, `state` is `running`), ignored. When an instance is forced to stop, it does not flush file system caches or file system metadata, and you must subsequently perform file system check and repair. Not recommended for Windows instances. Defaults to `false`. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The ID of the instance. (matches `instance_id`). + +## Timeouts + +[Configuration options](https://developer.hashicorp.com/terraform/language/resources/syntax#operation-timeouts): + +* `create` - (Default `10m`) +* `update` - (Default `10m`) +* `delete` - (Default `1m`) + +## Import + +`aws_ec2_instance_state` can be imported by using the `instance_id` attribute, e.g., + +``` +$ terraform import aws_ec2_instance_state.test i-02cae6557dfcf2f96 +``` diff --git a/website/docs/r/instance_state.html.markdown b/website/docs/r/instance_state.html.markdown deleted file mode 100644 index d95e32d8e4b..00000000000 --- a/website/docs/r/instance_state.html.markdown +++ /dev/null @@ -1,69 +0,0 @@ ---- -subcategory: "EC2 (Elastic Compute Cloud)" -layout: "aws" -page_title: "AWS: aws_instance_state" -description: |- - Provides an EC2 instance state resource. This allows managing an instance power state. ---- - -# Resource: aws_instance_state - -Provides an EC2 instance state resource. This allows managing an instance power state. - -~> **NOTE on Instance State Management:** As terraform currently does not support any method to validate that instance user data has completed applying. Use caution to ensure your instance user data applies successfully on creation before using the `aws_instance_state` resource to stop the instance. - -## Example Usage - -```terraform -data "aws_ami" "ubuntu" { - most_recent = true - - filter { - name = "name" - values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"] - } - - filter { - name = "virtualization-type" - values = ["hvm"] - } - - owners = ["099720109477"] # Canonical -} - -resource "aws_instance" "test" { - ami = data.aws_ami.ubuntu.id - instance_type = "t3.micro" - - tags = { - Name = "HelloWorld" - } -} - -resource "aws_instance_state" "test" { - instance_id = aws_instance.test.id - state = "stopped" -} -``` - -## Argument Reference - -The following arguments are supported: - -* `instance_id` - (Required) The ID of the instance. -* `state` - (Required) - The state of the instance. Valid Options: `stopped`, `running`. -* `force` - (Optional) When `true`, forces the instances to stop. The instances do not have an opportunity to flush file system caches or file system metadata. If you use this option, you must perform file system check and repair procedures. This option is not recommended for Windows instances. Defaults to `false`. - -## Attributes Reference - -In addition to all arguments above, the following attributes are exported: - -* `id` - The ID of the instance. (matches `instance_id`). - -## Import - -`aws_instance_state` can be imported by using the `instance_id` attribute, e.g., - -``` -$ terraform import aws_instance_state.test i-02cae6557dfcf2f96 -``` From f86564e252e6ff111b67dea9e60827f8b207e58b Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Tue, 3 Jan 2023 23:35:21 -0500 Subject: [PATCH 16/18] Rename resource to include ec2 service --- .changelog/28639.txt | 2 +- internal/provider/provider.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.changelog/28639.txt b/.changelog/28639.txt index 89fccade98c..e1aadae23a5 100644 --- a/.changelog/28639.txt +++ b/.changelog/28639.txt @@ -1,3 +1,3 @@ ```release-note:new-resource -aws_instance_state +aws_ec2_instance_state ``` \ No newline at end of file diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 279bcfe6882..cf30b3fee5e 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -1383,7 +1383,7 @@ func New(ctx context.Context) (*schema.Provider, error) { "aws_eip_association": ec2.ResourceEIPAssociation(), "aws_flow_log": ec2.ResourceFlowLog(), "aws_instance": ec2.ResourceInstance(), - "aws_instance_state": ec2.ResourceInstanceState(), + "aws_ec2_instance_state": ec2.ResourceInstanceState(), "aws_internet_gateway": ec2.ResourceInternetGateway(), "aws_internet_gateway_attachment": ec2.ResourceInternetGatewayAttachment(), "aws_key_pair": ec2.ResourceKeyPair(), From 568913930edc09ed34e4ef8e35cdb72455bd7132 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Tue, 3 Jan 2023 23:38:26 -0500 Subject: [PATCH 17/18] provider: Move order based on rename --- internal/provider/provider.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/provider/provider.go b/internal/provider/provider.go index cf30b3fee5e..56daffad10f 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -1347,6 +1347,7 @@ func New(ctx context.Context) (*schema.Provider, error) { "aws_ec2_client_vpn_route": ec2.ResourceClientVPNRoute(), "aws_ec2_fleet": ec2.ResourceFleet(), "aws_ec2_host": ec2.ResourceHost(), + "aws_ec2_instance_state": ec2.ResourceInstanceState(), "aws_ec2_local_gateway_route": ec2.ResourceLocalGatewayRoute(), "aws_ec2_local_gateway_route_table_vpc_association": ec2.ResourceLocalGatewayRouteTableVPCAssociation(), "aws_ec2_managed_prefix_list": ec2.ResourceManagedPrefixList(), @@ -1383,7 +1384,6 @@ func New(ctx context.Context) (*schema.Provider, error) { "aws_eip_association": ec2.ResourceEIPAssociation(), "aws_flow_log": ec2.ResourceFlowLog(), "aws_instance": ec2.ResourceInstance(), - "aws_ec2_instance_state": ec2.ResourceInstanceState(), "aws_internet_gateway": ec2.ResourceInternetGateway(), "aws_internet_gateway_attachment": ec2.ResourceInternetGatewayAttachment(), "aws_key_pair": ec2.ResourceKeyPair(), From 31f45268c2488ac4c9abc2529938ea4079237ba4 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Tue, 3 Jan 2023 23:40:40 -0500 Subject: [PATCH 18/18] Sort arguments --- internal/service/ec2/ec2_instance_state.go | 10 +++++----- website/docs/r/ec2_instance_state.html.markdown | 7 +++++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/internal/service/ec2/ec2_instance_state.go b/internal/service/ec2/ec2_instance_state.go index 16e1472c99c..e8d7819dc46 100644 --- a/internal/service/ec2/ec2_instance_state.go +++ b/internal/service/ec2/ec2_instance_state.go @@ -34,6 +34,11 @@ func ResourceInstanceState() *schema.Resource { }, Schema: map[string]*schema.Schema{ + "force": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, "instance_id": { Type: schema.TypeString, ForceNew: true, @@ -44,11 +49,6 @@ func ResourceInstanceState() *schema.Resource { Required: true, ValidateFunc: validation.StringInSlice([]string{ec2.InstanceStateNameRunning, ec2.InstanceStateNameStopped}, false), }, - "force": { - Type: schema.TypeBool, - Optional: true, - Default: false, - }, }, } } diff --git a/website/docs/r/ec2_instance_state.html.markdown b/website/docs/r/ec2_instance_state.html.markdown index 35ef0b574c9..92a5a6e8f0b 100644 --- a/website/docs/r/ec2_instance_state.html.markdown +++ b/website/docs/r/ec2_instance_state.html.markdown @@ -48,17 +48,20 @@ resource "aws_ec2_instance_state" "test" { ## Argument Reference -The following arguments are supported: +The following arguments are required: * `instance_id` - (Required) ID of the instance. * `state` - (Required) - State of the instance. Valid values are `stopped`, `running`. + +The following arguments are optional: + * `force` - (Optional) Whether to request a forced stop when `state` is `stopped`. Otherwise (_i.e._, `state` is `running`), ignored. When an instance is forced to stop, it does not flush file system caches or file system metadata, and you must subsequently perform file system check and repair. Not recommended for Windows instances. Defaults to `false`. ## Attributes Reference In addition to all arguments above, the following attributes are exported: -* `id` - The ID of the instance. (matches `instance_id`). +* `id` - ID of the instance (matches `instance_id`). ## Timeouts