Skip to content

Commit b8c4e1f

Browse files
author
Genevieve LEsperance
committed
Add polling to instance deletion.
1 parent 61714f3 commit b8c4e1f

File tree

4 files changed

+56
-5
lines changed

4 files changed

+56
-5
lines changed

aws/common/state.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func (s *State) Wait() (interface{}, error) {
3636
notFoundChecks := 20
3737
continuousTargetOccurence := 1
3838
minTimeout := 2 * time.Second
39-
delay := 10 * time.Second
39+
delay := 2 * time.Second
4040

4141
type Result struct {
4242
Result interface{}

aws/ec2/instance.go

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,25 @@ package ec2
22

33
import (
44
"fmt"
5+
"log"
56
"strings"
67

78
"github.com/aws/aws-sdk-go/aws"
9+
"github.com/aws/aws-sdk-go/aws/awserr"
810
awsec2 "github.com/aws/aws-sdk-go/service/ec2"
11+
"github.com/genevieve/leftovers/aws/common"
912
)
1013

1114
type Instance struct {
1215
client instancesClient
16+
logger logger
1317
resourceTags resourceTags
1418
id *string
1519
identifier string
1620
rtype string
1721
}
1822

19-
func NewInstance(client instancesClient, resourceTags resourceTags, id, keyName *string, tags []*awsec2.Tag) Instance {
23+
func NewInstance(client instancesClient, logger logger, resourceTags resourceTags, id, keyName *string, tags []*awsec2.Tag) Instance {
2024
identifier := *id
2125

2226
extra := []string{}
@@ -34,13 +38,17 @@ func NewInstance(client instancesClient, resourceTags resourceTags, id, keyName
3438

3539
return Instance{
3640
client: client,
41+
logger: logger,
3742
resourceTags: resourceTags,
3843
id: id,
3944
identifier: identifier,
4045
rtype: "EC2 Instance",
4146
}
4247
}
4348

49+
var pending = []string{"pending", "running", "shutting-down", "stopped", "stopping"}
50+
var target = []string{"terminated"}
51+
4452
func (i Instance) Delete() error {
4553
addresses, err := i.client.DescribeAddresses(&awsec2.DescribeAddressesInput{
4654
Filters: []*awsec2.Filter{{
@@ -57,6 +65,14 @@ func (i Instance) Delete() error {
5765
return fmt.Errorf("Terminate: %s", err)
5866
}
5967

68+
refresh := instanceRefresh(i.client, i.id)
69+
state := common.NewState(i.logger, refresh, pending, target)
70+
71+
_, err = state.Wait()
72+
if err != nil {
73+
return fmt.Errorf("Waiting for deletion: %s", err)
74+
}
75+
6076
err = i.resourceTags.Delete("instance", *i.id)
6177
if err != nil {
6278
return fmt.Errorf("Delete resource tags: %s", err)
@@ -79,3 +95,28 @@ func (i Instance) Name() string {
7995
func (i Instance) Type() string {
8096
return i.rtype
8197
}
98+
99+
func instanceRefresh(client instancesClient, id *string) common.StateRefreshFunc {
100+
return func() (interface{}, string, error) {
101+
resp, err := client.DescribeInstances(&awsec2.DescribeInstancesInput{
102+
InstanceIds: []*string{id},
103+
})
104+
if err != nil {
105+
if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidInstanceID.NotFound" {
106+
resp = nil
107+
} else {
108+
log.Printf("Error on InstanceStateRefresh: %s", err)
109+
return nil, "", err
110+
}
111+
}
112+
113+
if resp == nil || len(resp.Reservations) == 0 || len(resp.Reservations[0].Instances) == 0 {
114+
return nil, "", nil
115+
}
116+
117+
i := resp.Reservations[0].Instances[0]
118+
state := *i.State.Name
119+
120+
return i, state, nil
121+
}
122+
}

aws/ec2/instance_test.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,24 @@ import (
1414

1515
var _ = Describe("Instance", func() {
1616
var (
17-
instance ec2.Instance
1817
client *fakes.InstancesClient
18+
logger *fakes.Logger
1919
resourceTags *fakes.ResourceTags
2020
id *string
2121
keyName *string
22+
23+
instance ec2.Instance
2224
)
2325

2426
BeforeEach(func() {
2527
client = &fakes.InstancesClient{}
28+
logger = &fakes.Logger{}
2629
resourceTags = &fakes.ResourceTags{}
2730
id = aws.String("the-id")
2831
keyName = aws.String("the-key-name")
2932
tags := []*awsec2.Tag{}
3033

31-
instance = ec2.NewInstance(client, resourceTags, id, keyName, tags)
34+
instance = ec2.NewInstance(client, logger, resourceTags, id, keyName, tags)
3235
})
3336

3437
Describe("Delete", func() {
@@ -38,6 +41,13 @@ var _ = Describe("Instance", func() {
3841
AllocationId: aws.String("the-allocation-id"),
3942
}},
4043
}
44+
client.DescribeInstancesCall.Returns.Output = &awsec2.DescribeInstancesOutput{
45+
Reservations: []*awsec2.Reservation{{
46+
Instances: []*awsec2.Instance{{
47+
State: &awsec2.InstanceState{Name: aws.String("terminated")},
48+
}},
49+
}},
50+
}
4151
})
4252

4353
It("terminates the instance, deletes it's tags, and releases the address", func() {

aws/ec2/instances.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func (i Instances) List(filter string) ([]common.Deletable, error) {
4545
var resources []common.Deletable
4646
for _, r := range instances.Reservations {
4747
for _, instance := range r.Instances {
48-
r := NewInstance(i.client, i.resourceTags, instance.InstanceId, instance.KeyName, instance.Tags)
48+
r := NewInstance(i.client, i.logger, i.resourceTags, instance.InstanceId, instance.KeyName, instance.Tags)
4949

5050
if !strings.Contains(r.Name(), filter) {
5151
continue

0 commit comments

Comments
 (0)