1// +build !providerless
2
3/*
4Copyright 2017 The Kubernetes Authors.
5
6Licensed under the Apache License, Version 2.0 (the "License");
7you may not use this file except in compliance with the License.
8You may obtain a copy of the License at
9
10    http://www.apache.org/licenses/LICENSE-2.0
11
12Unless required by applicable law or agreed to in writing, software
13distributed under the License is distributed on an "AS IS" BASIS,
14WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15See the License for the specific language governing permissions and
16limitations under the License.
17*/
18
19package aws
20
21import (
22	"fmt"
23	"sort"
24	"strings"
25
26	"github.com/aws/aws-sdk-go/aws"
27	"github.com/aws/aws-sdk-go/service/autoscaling"
28	"github.com/aws/aws-sdk-go/service/ec2"
29	"github.com/aws/aws-sdk-go/service/elb"
30	"github.com/aws/aws-sdk-go/service/elbv2"
31	"github.com/aws/aws-sdk-go/service/kms"
32	"k8s.io/klog/v2"
33)
34
35// FakeAWSServices is an fake AWS session used for testing
36type FakeAWSServices struct {
37	region                      string
38	instances                   []*ec2.Instance
39	selfInstance                *ec2.Instance
40	networkInterfacesMacs       []string
41	networkInterfacesPrivateIPs [][]string
42	networkInterfacesVpcIDs     []string
43
44	ec2      FakeEC2
45	elb      ELB
46	elbv2    ELBV2
47	asg      *FakeASG
48	metadata *FakeMetadata
49	kms      *FakeKMS
50}
51
52// NewFakeAWSServices creates a new FakeAWSServices
53func NewFakeAWSServices(clusterID string) *FakeAWSServices {
54	s := &FakeAWSServices{}
55	s.region = "us-east-1"
56	s.ec2 = &FakeEC2Impl{aws: s}
57	s.elb = &FakeELB{aws: s}
58	s.elbv2 = &FakeELBV2{aws: s}
59	s.asg = &FakeASG{aws: s}
60	s.metadata = &FakeMetadata{aws: s}
61	s.kms = &FakeKMS{aws: s}
62
63	s.networkInterfacesMacs = []string{"aa:bb:cc:dd:ee:00", "aa:bb:cc:dd:ee:01"}
64	s.networkInterfacesVpcIDs = []string{"vpc-mac0", "vpc-mac1"}
65
66	selfInstance := &ec2.Instance{}
67	selfInstance.InstanceId = aws.String("i-self")
68	selfInstance.Placement = &ec2.Placement{
69		AvailabilityZone: aws.String("us-east-1a"),
70	}
71	selfInstance.PrivateDnsName = aws.String("ip-172-20-0-100.ec2.internal")
72	selfInstance.PrivateIpAddress = aws.String("192.168.0.1")
73	selfInstance.PublicIpAddress = aws.String("1.2.3.4")
74	s.selfInstance = selfInstance
75	s.instances = []*ec2.Instance{selfInstance}
76
77	var tag ec2.Tag
78	tag.Key = aws.String(TagNameKubernetesClusterLegacy)
79	tag.Value = aws.String(clusterID)
80	selfInstance.Tags = []*ec2.Tag{&tag}
81
82	return s
83}
84
85// WithAz sets the ec2 placement availability zone
86func (s *FakeAWSServices) WithAz(az string) *FakeAWSServices {
87	if s.selfInstance.Placement == nil {
88		s.selfInstance.Placement = &ec2.Placement{}
89	}
90	s.selfInstance.Placement.AvailabilityZone = aws.String(az)
91	return s
92}
93
94// Compute returns a fake EC2 client
95func (s *FakeAWSServices) Compute(region string) (EC2, error) {
96	return s.ec2, nil
97}
98
99// LoadBalancing returns a fake ELB client
100func (s *FakeAWSServices) LoadBalancing(region string) (ELB, error) {
101	return s.elb, nil
102}
103
104// LoadBalancingV2 returns a fake ELBV2 client
105func (s *FakeAWSServices) LoadBalancingV2(region string) (ELBV2, error) {
106	return s.elbv2, nil
107}
108
109// Autoscaling returns a fake ASG client
110func (s *FakeAWSServices) Autoscaling(region string) (ASG, error) {
111	return s.asg, nil
112}
113
114// Metadata returns a fake EC2Metadata client
115func (s *FakeAWSServices) Metadata() (EC2Metadata, error) {
116	return s.metadata, nil
117}
118
119// KeyManagement returns a fake KMS client
120func (s *FakeAWSServices) KeyManagement(region string) (KMS, error) {
121	return s.kms, nil
122}
123
124// FakeEC2 is a fake EC2 client used for testing
125type FakeEC2 interface {
126	EC2
127	CreateSubnet(*ec2.Subnet) (*ec2.CreateSubnetOutput, error)
128	RemoveSubnets()
129	CreateRouteTable(*ec2.RouteTable) (*ec2.CreateRouteTableOutput, error)
130	RemoveRouteTables()
131}
132
133// FakeEC2Impl is an implementation of the FakeEC2 interface used for testing
134type FakeEC2Impl struct {
135	aws                      *FakeAWSServices
136	Subnets                  []*ec2.Subnet
137	DescribeSubnetsInput     *ec2.DescribeSubnetsInput
138	RouteTables              []*ec2.RouteTable
139	DescribeRouteTablesInput *ec2.DescribeRouteTablesInput
140}
141
142// DescribeInstances returns fake instance descriptions
143func (ec2i *FakeEC2Impl) DescribeInstances(request *ec2.DescribeInstancesInput) ([]*ec2.Instance, error) {
144	matches := []*ec2.Instance{}
145	for _, instance := range ec2i.aws.instances {
146		if request.InstanceIds != nil {
147			if instance.InstanceId == nil {
148				klog.Warning("Instance with no instance id: ", instance)
149				continue
150			}
151
152			found := false
153			for _, instanceID := range request.InstanceIds {
154				if *instanceID == *instance.InstanceId {
155					found = true
156					break
157				}
158			}
159			if !found {
160				continue
161			}
162		}
163		if request.Filters != nil {
164			allMatch := true
165			for _, filter := range request.Filters {
166				if !instanceMatchesFilter(instance, filter) {
167					allMatch = false
168					break
169				}
170			}
171			if !allMatch {
172				continue
173			}
174		}
175		matches = append(matches, instance)
176	}
177
178	return matches, nil
179}
180
181// AttachVolume is not implemented but is required for interface conformance
182func (ec2i *FakeEC2Impl) AttachVolume(request *ec2.AttachVolumeInput) (resp *ec2.VolumeAttachment, err error) {
183	panic("Not implemented")
184}
185
186// DetachVolume is not implemented but is required for interface conformance
187func (ec2i *FakeEC2Impl) DetachVolume(request *ec2.DetachVolumeInput) (resp *ec2.VolumeAttachment, err error) {
188	panic("Not implemented")
189}
190
191// DescribeVolumes is not implemented but is required for interface conformance
192func (ec2i *FakeEC2Impl) DescribeVolumes(request *ec2.DescribeVolumesInput) ([]*ec2.Volume, error) {
193	panic("Not implemented")
194}
195
196// CreateVolume is not implemented but is required for interface conformance
197func (ec2i *FakeEC2Impl) CreateVolume(request *ec2.CreateVolumeInput) (resp *ec2.Volume, err error) {
198	panic("Not implemented")
199}
200
201// DeleteVolume is not implemented but is required for interface conformance
202func (ec2i *FakeEC2Impl) DeleteVolume(request *ec2.DeleteVolumeInput) (resp *ec2.DeleteVolumeOutput, err error) {
203	panic("Not implemented")
204}
205
206// DescribeSecurityGroups is not implemented but is required for interface
207// conformance
208func (ec2i *FakeEC2Impl) DescribeSecurityGroups(request *ec2.DescribeSecurityGroupsInput) ([]*ec2.SecurityGroup, error) {
209	panic("Not implemented")
210}
211
212// CreateSecurityGroup is not implemented but is required for interface
213// conformance
214func (ec2i *FakeEC2Impl) CreateSecurityGroup(*ec2.CreateSecurityGroupInput) (*ec2.CreateSecurityGroupOutput, error) {
215	panic("Not implemented")
216}
217
218// DeleteSecurityGroup is not implemented but is required for interface
219// conformance
220func (ec2i *FakeEC2Impl) DeleteSecurityGroup(*ec2.DeleteSecurityGroupInput) (*ec2.DeleteSecurityGroupOutput, error) {
221	panic("Not implemented")
222}
223
224// AuthorizeSecurityGroupIngress is not implemented but is required for
225// interface conformance
226func (ec2i *FakeEC2Impl) AuthorizeSecurityGroupIngress(*ec2.AuthorizeSecurityGroupIngressInput) (*ec2.AuthorizeSecurityGroupIngressOutput, error) {
227	panic("Not implemented")
228}
229
230// RevokeSecurityGroupIngress is not implemented but is required for interface
231// conformance
232func (ec2i *FakeEC2Impl) RevokeSecurityGroupIngress(*ec2.RevokeSecurityGroupIngressInput) (*ec2.RevokeSecurityGroupIngressOutput, error) {
233	panic("Not implemented")
234}
235
236// DescribeVolumeModifications is not implemented but is required for interface
237// conformance
238func (ec2i *FakeEC2Impl) DescribeVolumeModifications(*ec2.DescribeVolumesModificationsInput) ([]*ec2.VolumeModification, error) {
239	panic("Not implemented")
240}
241
242// ModifyVolume is not implemented but is required for interface conformance
243func (ec2i *FakeEC2Impl) ModifyVolume(*ec2.ModifyVolumeInput) (*ec2.ModifyVolumeOutput, error) {
244	panic("Not implemented")
245}
246
247// CreateSubnet creates fake subnets
248func (ec2i *FakeEC2Impl) CreateSubnet(request *ec2.Subnet) (*ec2.CreateSubnetOutput, error) {
249	ec2i.Subnets = append(ec2i.Subnets, request)
250	response := &ec2.CreateSubnetOutput{
251		Subnet: request,
252	}
253	return response, nil
254}
255
256// DescribeSubnets returns fake subnet descriptions
257func (ec2i *FakeEC2Impl) DescribeSubnets(request *ec2.DescribeSubnetsInput) ([]*ec2.Subnet, error) {
258	ec2i.DescribeSubnetsInput = request
259	return ec2i.Subnets, nil
260}
261
262// RemoveSubnets clears subnets on client
263func (ec2i *FakeEC2Impl) RemoveSubnets() {
264	ec2i.Subnets = ec2i.Subnets[:0]
265}
266
267// CreateTags is not implemented but is required for interface conformance
268func (ec2i *FakeEC2Impl) CreateTags(*ec2.CreateTagsInput) (*ec2.CreateTagsOutput, error) {
269	panic("Not implemented")
270}
271
272// DescribeRouteTables returns fake route table descriptions
273func (ec2i *FakeEC2Impl) DescribeRouteTables(request *ec2.DescribeRouteTablesInput) ([]*ec2.RouteTable, error) {
274	ec2i.DescribeRouteTablesInput = request
275	return ec2i.RouteTables, nil
276}
277
278// CreateRouteTable creates fake route tables
279func (ec2i *FakeEC2Impl) CreateRouteTable(request *ec2.RouteTable) (*ec2.CreateRouteTableOutput, error) {
280	ec2i.RouteTables = append(ec2i.RouteTables, request)
281	response := &ec2.CreateRouteTableOutput{
282		RouteTable: request,
283	}
284	return response, nil
285}
286
287// RemoveRouteTables clears route tables on client
288func (ec2i *FakeEC2Impl) RemoveRouteTables() {
289	ec2i.RouteTables = ec2i.RouteTables[:0]
290}
291
292// CreateRoute is not implemented but is required for interface conformance
293func (ec2i *FakeEC2Impl) CreateRoute(request *ec2.CreateRouteInput) (*ec2.CreateRouteOutput, error) {
294	panic("Not implemented")
295}
296
297// DeleteRoute is not implemented but is required for interface conformance
298func (ec2i *FakeEC2Impl) DeleteRoute(request *ec2.DeleteRouteInput) (*ec2.DeleteRouteOutput, error) {
299	panic("Not implemented")
300}
301
302// ModifyInstanceAttribute is not implemented but is required for interface
303// conformance
304func (ec2i *FakeEC2Impl) ModifyInstanceAttribute(request *ec2.ModifyInstanceAttributeInput) (*ec2.ModifyInstanceAttributeOutput, error) {
305	panic("Not implemented")
306}
307
308// DescribeVpcs returns fake VPC descriptions
309func (ec2i *FakeEC2Impl) DescribeVpcs(request *ec2.DescribeVpcsInput) (*ec2.DescribeVpcsOutput, error) {
310	return &ec2.DescribeVpcsOutput{Vpcs: []*ec2.Vpc{{CidrBlock: aws.String("172.20.0.0/16")}}}, nil
311}
312
313// FakeMetadata is a fake EC2 metadata service client used for testing
314type FakeMetadata struct {
315	aws *FakeAWSServices
316}
317
318// GetMetadata returns fake EC2 metadata for testing
319func (m *FakeMetadata) GetMetadata(key string) (string, error) {
320	networkInterfacesPrefix := "network/interfaces/macs/"
321	i := m.aws.selfInstance
322	if key == "placement/availability-zone" {
323		az := ""
324		if i.Placement != nil {
325			az = aws.StringValue(i.Placement.AvailabilityZone)
326		}
327		return az, nil
328	} else if key == "instance-id" {
329		return aws.StringValue(i.InstanceId), nil
330	} else if key == "local-hostname" {
331		return aws.StringValue(i.PrivateDnsName), nil
332	} else if key == "public-hostname" {
333		return aws.StringValue(i.PublicDnsName), nil
334	} else if key == "local-ipv4" {
335		return aws.StringValue(i.PrivateIpAddress), nil
336	} else if key == "public-ipv4" {
337		return aws.StringValue(i.PublicIpAddress), nil
338	} else if strings.HasPrefix(key, networkInterfacesPrefix) {
339		if key == networkInterfacesPrefix {
340			// Return the MACs sorted lexically rather than in device-number
341			// order; this matches AWS's observed behavior and lets us test
342			// that we fix up the ordering correctly in NodeAddresses().
343			macs := make([]string, len(m.aws.networkInterfacesMacs))
344			copy(macs, m.aws.networkInterfacesMacs)
345			sort.Strings(macs)
346			return strings.Join(macs, "/\n") + "/\n", nil
347		}
348
349		keySplit := strings.Split(key, "/")
350		macParam := keySplit[3]
351		if len(keySplit) == 5 && keySplit[4] == "vpc-id" {
352			for i, macElem := range m.aws.networkInterfacesMacs {
353				if macParam == macElem {
354					return m.aws.networkInterfacesVpcIDs[i], nil
355				}
356			}
357		}
358		if len(keySplit) == 5 && keySplit[4] == "device-number" {
359			for i, macElem := range m.aws.networkInterfacesMacs {
360				if macParam == macElem {
361					n := i
362					if n > 0 {
363						// Introduce an artificial gap, just to test eg: [eth0, eth2]
364						n++
365					}
366					return fmt.Sprintf("%d\n", n), nil
367				}
368			}
369		}
370		if len(keySplit) == 5 && keySplit[4] == "local-ipv4s" {
371			for i, macElem := range m.aws.networkInterfacesMacs {
372				if macParam == macElem {
373					return strings.Join(m.aws.networkInterfacesPrivateIPs[i], "/\n"), nil
374				}
375			}
376		}
377
378		return "", nil
379	}
380
381	return "", nil
382}
383
384// FakeELB is a fake ELB client used for testing
385type FakeELB struct {
386	aws *FakeAWSServices
387}
388
389// CreateLoadBalancer is not implemented but is required for interface
390// conformance
391func (elb *FakeELB) CreateLoadBalancer(*elb.CreateLoadBalancerInput) (*elb.CreateLoadBalancerOutput, error) {
392	panic("Not implemented")
393}
394
395// DeleteLoadBalancer is not implemented but is required for interface
396// conformance
397func (elb *FakeELB) DeleteLoadBalancer(input *elb.DeleteLoadBalancerInput) (*elb.DeleteLoadBalancerOutput, error) {
398	panic("Not implemented")
399}
400
401// DescribeLoadBalancers is not implemented but is required for interface
402// conformance
403func (elb *FakeELB) DescribeLoadBalancers(input *elb.DescribeLoadBalancersInput) (*elb.DescribeLoadBalancersOutput, error) {
404	panic("Not implemented")
405}
406
407// AddTags is not implemented but is required for interface conformance
408func (elb *FakeELB) AddTags(input *elb.AddTagsInput) (*elb.AddTagsOutput, error) {
409	panic("Not implemented")
410}
411
412// RegisterInstancesWithLoadBalancer is not implemented but is required for
413// interface conformance
414func (elb *FakeELB) RegisterInstancesWithLoadBalancer(*elb.RegisterInstancesWithLoadBalancerInput) (*elb.RegisterInstancesWithLoadBalancerOutput, error) {
415	panic("Not implemented")
416}
417
418// DeregisterInstancesFromLoadBalancer is not implemented but is required for
419// interface conformance
420func (elb *FakeELB) DeregisterInstancesFromLoadBalancer(*elb.DeregisterInstancesFromLoadBalancerInput) (*elb.DeregisterInstancesFromLoadBalancerOutput, error) {
421	panic("Not implemented")
422}
423
424// DetachLoadBalancerFromSubnets is not implemented but is required for
425// interface conformance
426func (elb *FakeELB) DetachLoadBalancerFromSubnets(*elb.DetachLoadBalancerFromSubnetsInput) (*elb.DetachLoadBalancerFromSubnetsOutput, error) {
427	panic("Not implemented")
428}
429
430// AttachLoadBalancerToSubnets is not implemented but is required for interface
431// conformance
432func (elb *FakeELB) AttachLoadBalancerToSubnets(*elb.AttachLoadBalancerToSubnetsInput) (*elb.AttachLoadBalancerToSubnetsOutput, error) {
433	panic("Not implemented")
434}
435
436// CreateLoadBalancerListeners is not implemented but is required for interface
437// conformance
438func (elb *FakeELB) CreateLoadBalancerListeners(*elb.CreateLoadBalancerListenersInput) (*elb.CreateLoadBalancerListenersOutput, error) {
439	panic("Not implemented")
440}
441
442// DeleteLoadBalancerListeners is not implemented but is required for interface
443// conformance
444func (elb *FakeELB) DeleteLoadBalancerListeners(*elb.DeleteLoadBalancerListenersInput) (*elb.DeleteLoadBalancerListenersOutput, error) {
445	panic("Not implemented")
446}
447
448// ApplySecurityGroupsToLoadBalancer is not implemented but is required for
449// interface conformance
450func (elb *FakeELB) ApplySecurityGroupsToLoadBalancer(*elb.ApplySecurityGroupsToLoadBalancerInput) (*elb.ApplySecurityGroupsToLoadBalancerOutput, error) {
451	panic("Not implemented")
452}
453
454// ConfigureHealthCheck is not implemented but is required for interface
455// conformance
456func (elb *FakeELB) ConfigureHealthCheck(*elb.ConfigureHealthCheckInput) (*elb.ConfigureHealthCheckOutput, error) {
457	panic("Not implemented")
458}
459
460// CreateLoadBalancerPolicy is not implemented but is required for interface
461// conformance
462func (elb *FakeELB) CreateLoadBalancerPolicy(*elb.CreateLoadBalancerPolicyInput) (*elb.CreateLoadBalancerPolicyOutput, error) {
463	panic("Not implemented")
464}
465
466// SetLoadBalancerPoliciesForBackendServer is not implemented but is required
467// for interface conformance
468func (elb *FakeELB) SetLoadBalancerPoliciesForBackendServer(*elb.SetLoadBalancerPoliciesForBackendServerInput) (*elb.SetLoadBalancerPoliciesForBackendServerOutput, error) {
469	panic("Not implemented")
470}
471
472// SetLoadBalancerPoliciesOfListener is not implemented but is required for
473// interface conformance
474func (elb *FakeELB) SetLoadBalancerPoliciesOfListener(input *elb.SetLoadBalancerPoliciesOfListenerInput) (*elb.SetLoadBalancerPoliciesOfListenerOutput, error) {
475	panic("Not implemented")
476}
477
478// DescribeLoadBalancerPolicies is not implemented but is required for
479// interface conformance
480func (elb *FakeELB) DescribeLoadBalancerPolicies(input *elb.DescribeLoadBalancerPoliciesInput) (*elb.DescribeLoadBalancerPoliciesOutput, error) {
481	panic("Not implemented")
482}
483
484// DescribeLoadBalancerAttributes is not implemented but is required for
485// interface conformance
486func (elb *FakeELB) DescribeLoadBalancerAttributes(*elb.DescribeLoadBalancerAttributesInput) (*elb.DescribeLoadBalancerAttributesOutput, error) {
487	panic("Not implemented")
488}
489
490// ModifyLoadBalancerAttributes is not implemented but is required for
491// interface conformance
492func (elb *FakeELB) ModifyLoadBalancerAttributes(*elb.ModifyLoadBalancerAttributesInput) (*elb.ModifyLoadBalancerAttributesOutput, error) {
493	panic("Not implemented")
494}
495
496// FakeELBV2 is a fake ELBV2 client used for testing
497type FakeELBV2 struct {
498	aws *FakeAWSServices
499}
500
501// AddTags is not implemented but is required for interface conformance
502func (elb *FakeELBV2) AddTags(input *elbv2.AddTagsInput) (*elbv2.AddTagsOutput, error) {
503	panic("Not implemented")
504}
505
506// CreateLoadBalancer is not implemented but is required for interface
507// conformance
508func (elb *FakeELBV2) CreateLoadBalancer(*elbv2.CreateLoadBalancerInput) (*elbv2.CreateLoadBalancerOutput, error) {
509	panic("Not implemented")
510}
511
512// DescribeLoadBalancers is not implemented but is required for interface
513// conformance
514func (elb *FakeELBV2) DescribeLoadBalancers(*elbv2.DescribeLoadBalancersInput) (*elbv2.DescribeLoadBalancersOutput, error) {
515	panic("Not implemented")
516}
517
518// DeleteLoadBalancer is not implemented but is required for interface
519// conformance
520func (elb *FakeELBV2) DeleteLoadBalancer(*elbv2.DeleteLoadBalancerInput) (*elbv2.DeleteLoadBalancerOutput, error) {
521	panic("Not implemented")
522}
523
524// ModifyLoadBalancerAttributes is not implemented but is required for
525// interface conformance
526func (elb *FakeELBV2) ModifyLoadBalancerAttributes(*elbv2.ModifyLoadBalancerAttributesInput) (*elbv2.ModifyLoadBalancerAttributesOutput, error) {
527	panic("Not implemented")
528}
529
530// DescribeLoadBalancerAttributes is not implemented but is required for
531// interface conformance
532func (elb *FakeELBV2) DescribeLoadBalancerAttributes(*elbv2.DescribeLoadBalancerAttributesInput) (*elbv2.DescribeLoadBalancerAttributesOutput, error) {
533	panic("Not implemented")
534}
535
536// CreateTargetGroup is not implemented but is required for interface
537// conformance
538func (elb *FakeELBV2) CreateTargetGroup(*elbv2.CreateTargetGroupInput) (*elbv2.CreateTargetGroupOutput, error) {
539	panic("Not implemented")
540}
541
542// DescribeTargetGroups is not implemented but is required for interface
543// conformance
544func (elb *FakeELBV2) DescribeTargetGroups(*elbv2.DescribeTargetGroupsInput) (*elbv2.DescribeTargetGroupsOutput, error) {
545	panic("Not implemented")
546}
547
548// ModifyTargetGroup is not implemented but is required for interface
549// conformance
550func (elb *FakeELBV2) ModifyTargetGroup(*elbv2.ModifyTargetGroupInput) (*elbv2.ModifyTargetGroupOutput, error) {
551	panic("Not implemented")
552}
553
554// DeleteTargetGroup is not implemented but is required for interface
555// conformance
556func (elb *FakeELBV2) DeleteTargetGroup(*elbv2.DeleteTargetGroupInput) (*elbv2.DeleteTargetGroupOutput, error) {
557	panic("Not implemented")
558}
559
560// DescribeTargetHealth is not implemented but is required for interface
561// conformance
562func (elb *FakeELBV2) DescribeTargetHealth(input *elbv2.DescribeTargetHealthInput) (*elbv2.DescribeTargetHealthOutput, error) {
563	panic("Not implemented")
564}
565
566// DescribeTargetGroupAttributes is not implemented but is required for
567// interface conformance
568func (elb *FakeELBV2) DescribeTargetGroupAttributes(*elbv2.DescribeTargetGroupAttributesInput) (*elbv2.DescribeTargetGroupAttributesOutput, error) {
569	panic("Not implemented")
570}
571
572// ModifyTargetGroupAttributes is not implemented but is required for interface
573// conformance
574func (elb *FakeELBV2) ModifyTargetGroupAttributes(*elbv2.ModifyTargetGroupAttributesInput) (*elbv2.ModifyTargetGroupAttributesOutput, error) {
575	panic("Not implemented")
576}
577
578// RegisterTargets is not implemented but is required for interface conformance
579func (elb *FakeELBV2) RegisterTargets(*elbv2.RegisterTargetsInput) (*elbv2.RegisterTargetsOutput, error) {
580	panic("Not implemented")
581}
582
583// DeregisterTargets is not implemented but is required for interface
584// conformance
585func (elb *FakeELBV2) DeregisterTargets(*elbv2.DeregisterTargetsInput) (*elbv2.DeregisterTargetsOutput, error) {
586	panic("Not implemented")
587}
588
589// CreateListener is not implemented but is required for interface conformance
590func (elb *FakeELBV2) CreateListener(*elbv2.CreateListenerInput) (*elbv2.CreateListenerOutput, error) {
591	panic("Not implemented")
592}
593
594// DescribeListeners is not implemented but is required for interface
595// conformance
596func (elb *FakeELBV2) DescribeListeners(*elbv2.DescribeListenersInput) (*elbv2.DescribeListenersOutput, error) {
597	panic("Not implemented")
598}
599
600// DeleteListener is not implemented but is required for interface conformance
601func (elb *FakeELBV2) DeleteListener(*elbv2.DeleteListenerInput) (*elbv2.DeleteListenerOutput, error) {
602	panic("Not implemented")
603}
604
605// ModifyListener is not implemented but is required for interface conformance
606func (elb *FakeELBV2) ModifyListener(*elbv2.ModifyListenerInput) (*elbv2.ModifyListenerOutput, error) {
607	panic("Not implemented")
608}
609
610// WaitUntilLoadBalancersDeleted is not implemented but is required for
611// interface conformance
612func (elb *FakeELBV2) WaitUntilLoadBalancersDeleted(*elbv2.DescribeLoadBalancersInput) error {
613	panic("Not implemented")
614}
615
616// FakeASG is a fake Autoscaling client used for testing
617type FakeASG struct {
618	aws *FakeAWSServices
619}
620
621// UpdateAutoScalingGroup is not implemented but is required for interface
622// conformance
623func (a *FakeASG) UpdateAutoScalingGroup(*autoscaling.UpdateAutoScalingGroupInput) (*autoscaling.UpdateAutoScalingGroupOutput, error) {
624	panic("Not implemented")
625}
626
627// DescribeAutoScalingGroups is not implemented but is required for interface
628// conformance
629func (a *FakeASG) DescribeAutoScalingGroups(*autoscaling.DescribeAutoScalingGroupsInput) (*autoscaling.DescribeAutoScalingGroupsOutput, error) {
630	panic("Not implemented")
631}
632
633// FakeKMS is a fake KMS client used for testing
634type FakeKMS struct {
635	aws *FakeAWSServices
636}
637
638// DescribeKey is not implemented but is required for interface conformance
639func (kms *FakeKMS) DescribeKey(*kms.DescribeKeyInput) (*kms.DescribeKeyOutput, error) {
640	panic("Not implemented")
641}
642
643func instanceMatchesFilter(instance *ec2.Instance, filter *ec2.Filter) bool {
644	name := *filter.Name
645	if name == "private-dns-name" {
646		if instance.PrivateDnsName == nil {
647			return false
648		}
649		return contains(filter.Values, *instance.PrivateDnsName)
650	}
651
652	if name == "instance-state-name" {
653		return contains(filter.Values, *instance.State.Name)
654	}
655
656	if name == "tag-key" {
657		for _, instanceTag := range instance.Tags {
658			if contains(filter.Values, aws.StringValue(instanceTag.Key)) {
659				return true
660			}
661		}
662		return false
663	}
664
665	if strings.HasPrefix(name, "tag:") {
666		tagName := name[4:]
667		for _, instanceTag := range instance.Tags {
668			if aws.StringValue(instanceTag.Key) == tagName && contains(filter.Values, aws.StringValue(instanceTag.Value)) {
669				return true
670			}
671		}
672		return false
673	}
674
675	panic("Unknown filter name: " + name)
676}
677
678func contains(haystack []*string, needle string) bool {
679	for _, s := range haystack {
680		// (deliberately panic if s == nil)
681		if needle == *s {
682			return true
683		}
684	}
685	return false
686}
687