1package ec2_test
2
3import (
4	"errors"
5
6	"github.com/aws/aws-sdk-go/aws"
7	awsec2 "github.com/aws/aws-sdk-go/service/ec2"
8	"github.com/genevieve/leftovers/aws/ec2"
9	"github.com/genevieve/leftovers/aws/ec2/fakes"
10	. "github.com/onsi/ginkgo"
11	. "github.com/onsi/gomega"
12)
13
14var _ = Describe("Instances", func() {
15	var (
16		client       *fakes.InstancesClient
17		logger       *fakes.Logger
18		resourceTags *fakes.ResourceTags
19
20		instances ec2.Instances
21	)
22
23	BeforeEach(func() {
24		client = &fakes.InstancesClient{}
25		logger = &fakes.Logger{}
26		logger.PromptWithDetailsCall.Returns.Proceed = true
27		resourceTags = &fakes.ResourceTags{}
28
29		instances = ec2.NewInstances(client, logger, resourceTags)
30	})
31
32	Describe("List", func() {
33		var filter string
34
35		BeforeEach(func() {
36			client.DescribeInstancesCall.Returns.Output = &awsec2.DescribeInstancesOutput{
37				Reservations: []*awsec2.Reservation{{
38					Instances: []*awsec2.Instance{{
39						State: &awsec2.InstanceState{Name: aws.String("available")},
40						Tags: []*awsec2.Tag{{
41							Key:   aws.String("Name"),
42							Value: aws.String("banana-instance"),
43						}},
44						InstanceId: aws.String("the-instance-id"),
45						KeyName:    aws.String(""),
46					}},
47				}},
48			}
49		})
50
51		It("returns a list of ec2 instances to delete", func() {
52			items, err := instances.List(filter)
53			Expect(err).NotTo(HaveOccurred())
54
55			Expect(client.DescribeInstancesCall.CallCount).To(Equal(1))
56			Expect(client.DescribeInstancesCall.Receives.Input.Filters[0].Name).To(Equal(aws.String("instance-state-name")))
57
58			Expect(logger.PromptWithDetailsCall.CallCount).To(Equal(1))
59			Expect(logger.PromptWithDetailsCall.Receives.Type).To(Equal("EC2 Instance"))
60			Expect(logger.PromptWithDetailsCall.Receives.Name).To(Equal("the-instance-id (Name:banana-instance)"))
61
62			Expect(items).To(HaveLen(1))
63		})
64
65		Context("when the instance name does not contain the filter", func() {
66			It("does not try to delete it", func() {
67				items, err := instances.List("kiwi")
68				Expect(err).NotTo(HaveOccurred())
69
70				Expect(client.DescribeInstancesCall.CallCount).To(Equal(1))
71				Expect(logger.PromptWithDetailsCall.CallCount).To(Equal(0))
72
73				Expect(items).To(HaveLen(0))
74			})
75		})
76
77		Context("when there is no tag name", func() {
78			BeforeEach(func() {
79				client.DescribeInstancesCall.Returns.Output = &awsec2.DescribeInstancesOutput{
80					Reservations: []*awsec2.Reservation{{
81						Instances: []*awsec2.Instance{{
82							State:      &awsec2.InstanceState{Name: aws.String("available")},
83							InstanceId: aws.String("the-instance-id"),
84							KeyName:    aws.String(""),
85						}},
86					}},
87				}
88			})
89
90			It("uses just the instance id in the prompt", func() {
91				items, err := instances.List(filter)
92				Expect(err).NotTo(HaveOccurred())
93
94				Expect(logger.PromptWithDetailsCall.Receives.Name).To(Equal("the-instance-id"))
95
96				Expect(items).To(HaveLen(1))
97			})
98		})
99
100		Context("when there is a key name", func() {
101			BeforeEach(func() {
102				client.DescribeInstancesCall.Returns.Output = &awsec2.DescribeInstancesOutput{
103					Reservations: []*awsec2.Reservation{{
104						Instances: []*awsec2.Instance{{
105							State:      &awsec2.InstanceState{Name: aws.String("available")},
106							InstanceId: aws.String("the-instance-id"),
107							KeyName:    aws.String("the-key-pair"),
108						}},
109					}},
110				}
111			})
112
113			It("uses it in the prompt", func() {
114				items, err := instances.List(filter)
115				Expect(err).NotTo(HaveOccurred())
116
117				Expect(logger.PromptWithDetailsCall.Receives.Name).To(Equal("the-instance-id (KeyPairName:the-key-pair)"))
118
119				Expect(items).To(HaveLen(1))
120			})
121		})
122
123		Context("when the client fails to list instances", func() {
124			BeforeEach(func() {
125				client.DescribeInstancesCall.Returns.Error = errors.New("some error")
126			})
127
128			It("returns the error", func() {
129				_, err := instances.List(filter)
130				Expect(err).To(MatchError("Describing EC2 Instances: some error"))
131			})
132		})
133
134		Context("when the user responds no to the prompt", func() {
135			BeforeEach(func() {
136				logger.PromptWithDetailsCall.Returns.Proceed = false
137			})
138
139			It("does not return it to the list", func() {
140				items, err := instances.List(filter)
141				Expect(err).NotTo(HaveOccurred())
142
143				Expect(logger.PromptWithDetailsCall.CallCount).To(Equal(1))
144				Expect(items).To(HaveLen(0))
145			})
146		})
147	})
148})
149