From 1edd7d49fa1908b7ec8b32486b5632b561caaca2 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Sat, 24 Mar 2018 16:30:40 -0400 Subject: [PATCH] Add deletion to lifecycle test --- cloudmock/aws/mockautoscaling/BUILD.bazel | 1 + cloudmock/aws/mockautoscaling/group.go | 31 +++++ .../mockautoscaling/launchconfigurations.go | 26 ++++ cloudmock/aws/mockautoscaling/tags.go | 90 +++++++++++++ .../aws/mockautoscaling/unimplemented.go | 48 ------- cloudmock/aws/mockec2/BUILD.bazel | 1 + cloudmock/aws/mockec2/address.go | 23 +++- cloudmock/aws/mockec2/api.go | 48 ++++++- cloudmock/aws/mockec2/dhcpoptions.go | 18 ++- cloudmock/aws/mockec2/instances.go | 54 ++++++++ cloudmock/aws/mockec2/internetgateways.go | 120 ++++++++++++++--- cloudmock/aws/mockec2/keypairs.go | 36 ++++- cloudmock/aws/mockec2/natgateway.go | 25 ++++ cloudmock/aws/mockec2/routetable.go | 24 ++++ cloudmock/aws/mockec2/securitygroups.go | 54 ++++++-- cloudmock/aws/mockec2/subnets.go | 25 ++++ cloudmock/aws/mockec2/unimplemented.go | 127 ------------------ cloudmock/aws/mockec2/volumes.go | 37 ++++- cloudmock/aws/mockec2/vpcs.go | 25 ++++ cloudmock/aws/mockelb/api.go | 17 +++ cloudmock/aws/mockiam/iaminstanceprofile.go | 119 ++++++++++++++++ cloudmock/aws/mockiam/iamrole.go | 79 +++++++++++ cloudmock/aws/mockiam/iamrolepolicy.go | 88 ++++++++++++ cloudmock/aws/mockiam/unimplemented.go | 109 +-------------- cloudmock/aws/mockroute53/api.go | 5 + cloudmock/aws/mockroute53/records.go | 14 ++ cloudmock/aws/mockroute53/zones.go | 9 ++ cmd/kops/lifecycle_integration_test.go | 44 +++++- .../fi/cloudup/awstasks/elastic_ip_test.go | 2 +- 29 files changed, 970 insertions(+), 329 deletions(-) create mode 100644 cloudmock/aws/mockautoscaling/tags.go create mode 100644 cloudmock/aws/mockec2/instances.go diff --git a/cloudmock/aws/mockautoscaling/BUILD.bazel b/cloudmock/aws/mockautoscaling/BUILD.bazel index 8f85afc904..6da340908f 100644 --- a/cloudmock/aws/mockautoscaling/BUILD.bazel +++ b/cloudmock/aws/mockautoscaling/BUILD.bazel @@ -7,6 +7,7 @@ go_library( "attach.go", "group.go", "launchconfigurations.go", + "tags.go", "unimplemented.go", ], importpath = "k8s.io/kops/cloudmock/aws/mockautoscaling", diff --git a/cloudmock/aws/mockautoscaling/group.go b/cloudmock/aws/mockautoscaling/group.go index e9b65b9d95..a013ff43fe 100644 --- a/cloudmock/aws/mockautoscaling/group.go +++ b/cloudmock/aws/mockautoscaling/group.go @@ -126,6 +126,9 @@ func (m *MockAutoscaling) EnableMetricsCollection(request *autoscaling.EnableMet } func (m *MockAutoscaling) DescribeAutoScalingGroups(input *autoscaling.DescribeAutoScalingGroupsInput) (*autoscaling.DescribeAutoScalingGroupsOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + groups := []*autoscaling.Group{} for _, group := range m.Groups { match := false @@ -149,6 +152,9 @@ func (m *MockAutoscaling) DescribeAutoScalingGroups(input *autoscaling.DescribeA } func (m *MockAutoscaling) TerminateInstanceInAutoScalingGroup(input *autoscaling.TerminateInstanceInAutoScalingGroupInput) (*autoscaling.TerminateInstanceInAutoScalingGroupOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + for _, group := range m.Groups { for i := range group.Instances { if aws.StringValue(group.Instances[i].InstanceId) == aws.StringValue(input.InstanceId) { @@ -195,3 +201,28 @@ func (m *MockAutoscaling) DescribeAutoScalingGroupsPagesWithContext(aws.Context, glog.Fatalf("Not implemented") return nil } + +func (m *MockAutoscaling) DeleteAutoScalingGroup(request *autoscaling.DeleteAutoScalingGroupInput) (*autoscaling.DeleteAutoScalingGroupOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + + glog.Infof("DeleteAutoScalingGroup: %v", request) + + id := aws.StringValue(request.AutoScalingGroupName) + o := m.Groups[id] + if o == nil { + return nil, fmt.Errorf("AutoScalingGroup %q not found", id) + } + delete(m.Groups, id) + + return &autoscaling.DeleteAutoScalingGroupOutput{}, nil +} + +func (m *MockAutoscaling) DeleteAutoScalingGroupWithContext(aws.Context, *autoscaling.DeleteAutoScalingGroupInput, ...request.Option) (*autoscaling.DeleteAutoScalingGroupOutput, error) { + glog.Fatalf("Not implemented") + return nil, nil +} +func (m *MockAutoscaling) DeleteAutoScalingGroupRequest(*autoscaling.DeleteAutoScalingGroupInput) (*request.Request, *autoscaling.DeleteAutoScalingGroupOutput) { + glog.Fatalf("Not implemented") + return nil, nil +} diff --git a/cloudmock/aws/mockautoscaling/launchconfigurations.go b/cloudmock/aws/mockautoscaling/launchconfigurations.go index 6f7e398bb6..8f4476523f 100644 --- a/cloudmock/aws/mockautoscaling/launchconfigurations.go +++ b/cloudmock/aws/mockautoscaling/launchconfigurations.go @@ -17,6 +17,7 @@ limitations under the License. package mockautoscaling import ( + "fmt" "time" "github.com/aws/aws-sdk-go/aws" @@ -106,3 +107,28 @@ func (m *MockAutoscaling) CreateLaunchConfigurationRequest(*autoscaling.CreateLa glog.Fatalf("Not implemented") return nil, nil } + +func (m *MockAutoscaling) DeleteLaunchConfiguration(request *autoscaling.DeleteLaunchConfigurationInput) (*autoscaling.DeleteLaunchConfigurationOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + + glog.Infof("DeleteLaunchConfiguration: %v", request) + + id := aws.StringValue(request.LaunchConfigurationName) + o := m.LaunchConfigurations[id] + if o == nil { + return nil, fmt.Errorf("LaunchConfiguration %q not found", id) + } + delete(m.LaunchConfigurations, id) + + return &autoscaling.DeleteLaunchConfigurationOutput{}, nil +} + +func (m *MockAutoscaling) DeleteLaunchConfigurationWithContext(aws.Context, *autoscaling.DeleteLaunchConfigurationInput, ...request.Option) (*autoscaling.DeleteLaunchConfigurationOutput, error) { + glog.Fatalf("Not implemented") + return nil, nil +} +func (m *MockAutoscaling) DeleteLaunchConfigurationRequest(*autoscaling.DeleteLaunchConfigurationInput) (*request.Request, *autoscaling.DeleteLaunchConfigurationOutput) { + glog.Fatalf("Not implemented") + return nil, nil +} diff --git a/cloudmock/aws/mockautoscaling/tags.go b/cloudmock/aws/mockautoscaling/tags.go new file mode 100644 index 0000000000..5dd1a1420a --- /dev/null +++ b/cloudmock/aws/mockautoscaling/tags.go @@ -0,0 +1,90 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package mockautoscaling + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/service/autoscaling" + "github.com/golang/glog" +) + +func (m *MockAutoscaling) DescribeTags(request *autoscaling.DescribeTagsInput) (*autoscaling.DescribeTagsOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + + response := &autoscaling.DescribeTagsOutput{} + for _, g := range m.Groups { + for _, tag := range g.Tags { + allFiltersMatch := true + for _, filter := range request.Filters { + match := false + switch aws.StringValue(filter.Name) { + case "value": + for _, v := range filter.Values { + if aws.StringValue(tag.Value) == aws.StringValue(v) { + match = true + } + } + + default: + glog.Fatalf("Unsupported filter: %v", filter) + } + + if !match { + allFiltersMatch = false + break + } + } + + if !allFiltersMatch { + continue + } + + response.Tags = append(response.Tags, tag) + } + } + + return response, nil +} + +func (m *MockAutoscaling) DescribeTagsWithContext(aws.Context, *autoscaling.DescribeTagsInput, ...request.Option) (*autoscaling.DescribeTagsOutput, error) { + glog.Fatalf("Not implemented") + return nil, nil +} + +func (m *MockAutoscaling) DescribeTagsRequest(*autoscaling.DescribeTagsInput) (*request.Request, *autoscaling.DescribeTagsOutput) { + glog.Fatalf("Not implemented") + return nil, nil +} + +func (m *MockAutoscaling) DescribeTagsPages(request *autoscaling.DescribeTagsInput, callback func(*autoscaling.DescribeTagsOutput, bool) bool) error { + // For the mock, we just send everything in one page + page, err := m.DescribeTags(request) + if err != nil { + return err + } + + callback(page, false) + + return nil +} + +func (m *MockAutoscaling) DescribeTagsPagesWithContext(aws.Context, *autoscaling.DescribeTagsInput, func(*autoscaling.DescribeTagsOutput, bool) bool, ...request.Option) error { + glog.Fatalf("Not implemented") + return nil +} diff --git a/cloudmock/aws/mockautoscaling/unimplemented.go b/cloudmock/aws/mockautoscaling/unimplemented.go index 9c54b9bb1f..99e9e3ca5b 100644 --- a/cloudmock/aws/mockautoscaling/unimplemented.go +++ b/cloudmock/aws/mockautoscaling/unimplemented.go @@ -80,32 +80,6 @@ func (m *MockAutoscaling) CreateOrUpdateTagsRequest(*autoscaling.CreateOrUpdateT return nil, nil } -func (m *MockAutoscaling) DeleteAutoScalingGroup(*autoscaling.DeleteAutoScalingGroupInput) (*autoscaling.DeleteAutoScalingGroupOutput, error) { - glog.Fatalf("Not implemented") - return nil, nil -} -func (m *MockAutoscaling) DeleteAutoScalingGroupWithContext(aws.Context, *autoscaling.DeleteAutoScalingGroupInput, ...request.Option) (*autoscaling.DeleteAutoScalingGroupOutput, error) { - glog.Fatalf("Not implemented") - return nil, nil -} -func (m *MockAutoscaling) DeleteAutoScalingGroupRequest(*autoscaling.DeleteAutoScalingGroupInput) (*request.Request, *autoscaling.DeleteAutoScalingGroupOutput) { - glog.Fatalf("Not implemented") - return nil, nil -} - -func (m *MockAutoscaling) DeleteLaunchConfiguration(*autoscaling.DeleteLaunchConfigurationInput) (*autoscaling.DeleteLaunchConfigurationOutput, error) { - glog.Fatalf("Not implemented") - return nil, nil -} -func (m *MockAutoscaling) DeleteLaunchConfigurationWithContext(aws.Context, *autoscaling.DeleteLaunchConfigurationInput, ...request.Option) (*autoscaling.DeleteLaunchConfigurationOutput, error) { - glog.Fatalf("Not implemented") - return nil, nil -} -func (m *MockAutoscaling) DeleteLaunchConfigurationRequest(*autoscaling.DeleteLaunchConfigurationInput) (*request.Request, *autoscaling.DeleteLaunchConfigurationOutput) { - glog.Fatalf("Not implemented") - return nil, nil -} - func (m *MockAutoscaling) DeleteLifecycleHook(*autoscaling.DeleteLifecycleHookInput) (*autoscaling.DeleteLifecycleHookOutput, error) { glog.Fatalf("Not implemented") return nil, nil @@ -398,28 +372,6 @@ func (m *MockAutoscaling) DescribeScheduledActionsPagesWithContext(aws.Context, return nil } -func (m *MockAutoscaling) DescribeTags(*autoscaling.DescribeTagsInput) (*autoscaling.DescribeTagsOutput, error) { - glog.Fatalf("Not implemented") - return nil, nil -} -func (m *MockAutoscaling) DescribeTagsWithContext(aws.Context, *autoscaling.DescribeTagsInput, ...request.Option) (*autoscaling.DescribeTagsOutput, error) { - glog.Fatalf("Not implemented") - return nil, nil -} -func (m *MockAutoscaling) DescribeTagsRequest(*autoscaling.DescribeTagsInput) (*request.Request, *autoscaling.DescribeTagsOutput) { - glog.Fatalf("Not implemented") - return nil, nil -} - -func (m *MockAutoscaling) DescribeTagsPages(*autoscaling.DescribeTagsInput, func(*autoscaling.DescribeTagsOutput, bool) bool) error { - glog.Fatalf("Not implemented") - return nil -} -func (m *MockAutoscaling) DescribeTagsPagesWithContext(aws.Context, *autoscaling.DescribeTagsInput, func(*autoscaling.DescribeTagsOutput, bool) bool, ...request.Option) error { - glog.Fatalf("Not implemented") - return nil -} - func (m *MockAutoscaling) DescribeTerminationPolicyTypes(*autoscaling.DescribeTerminationPolicyTypesInput) (*autoscaling.DescribeTerminationPolicyTypesOutput, error) { glog.Fatalf("Not implemented") return nil, nil diff --git a/cloudmock/aws/mockec2/BUILD.bazel b/cloudmock/aws/mockec2/BUILD.bazel index e2d0e2a8e2..13489e4860 100644 --- a/cloudmock/aws/mockec2/BUILD.bazel +++ b/cloudmock/aws/mockec2/BUILD.bazel @@ -8,6 +8,7 @@ go_library( "convenience.go", "dhcpoptions.go", "images.go", + "instances.go", "internetgateways.go", "keypairs.go", "natgateway.go", diff --git a/cloudmock/aws/mockec2/address.go b/cloudmock/aws/mockec2/address.go index 166ff2bbe8..79a97c926c 100644 --- a/cloudmock/aws/mockec2/address.go +++ b/cloudmock/aws/mockec2/address.go @@ -57,7 +57,10 @@ func (m *MockEC2) AllocateAddressWithId(request *ec2.AllocateAddressInput, id st Domain: s("vpc"), PublicIp: s(publicIP.String()), } - m.Addresses = append(m.Addresses, address) + if m.Addresses == nil { + m.Addresses = make(map[string]*ec2.Address) + } + m.Addresses[id] = address response := &ec2.AllocateAddressOutput{ AllocationId: address.AllocationId, Domain: address.Domain, @@ -167,6 +170,7 @@ func (m *MockEC2) DescribeAddresses(request *ec2.DescribeAddressesInput) (*ec2.D return response, nil } + func (m *MockEC2) ReleaseAddressRequest(*ec2.ReleaseAddressInput) (*request.Request, *ec2.ReleaseAddressOutput) { panic("Not implemented") return nil, nil @@ -175,7 +179,18 @@ func (m *MockEC2) ReleaseAddressWithContext(aws.Context, *ec2.ReleaseAddressInpu panic("Not implemented") return nil, nil } -func (m *MockEC2) ReleaseAddress(*ec2.ReleaseAddressInput) (*ec2.ReleaseAddressOutput, error) { - panic("Not implemented") - return nil, nil +func (m *MockEC2) ReleaseAddress(request *ec2.ReleaseAddressInput) (*ec2.ReleaseAddressOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + + glog.Infof("ReleaseAddress: %v", request) + + id := aws.StringValue(request.AllocationId) + o := m.Addresses[id] + if o == nil { + return nil, fmt.Errorf("Address %q not found", id) + } + delete(m.Addresses, id) + + return &ec2.ReleaseAddressOutput{}, nil } diff --git a/cloudmock/aws/mockec2/api.go b/cloudmock/aws/mockec2/api.go index 4a60a79438..234c026d6a 100644 --- a/cloudmock/aws/mockec2/api.go +++ b/cloudmock/aws/mockec2/api.go @@ -20,6 +20,7 @@ import ( "fmt" "sync" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ec2/ec2iface" ) @@ -28,7 +29,7 @@ type MockEC2 struct { mutex sync.Mutex addressNumber int - Addresses []*ec2.Address + Addresses map[string]*ec2.Address RouteTables map[string]*ec2.RouteTable @@ -43,14 +44,13 @@ type MockEC2 struct { Volumes map[string]*ec2.Volume - KeyPairs []*ec2.KeyPairInfo + KeyPairs map[string]*ec2.KeyPairInfo Tags []*ec2.TagDescription Vpcs map[string]*vpcInfo - internetGatewayNumber int - InternetGateways map[string]*internetGatewayInfo + InternetGateways map[string]*ec2.InternetGateway NatGateways map[string]*ec2.NatGateway @@ -60,6 +60,46 @@ type MockEC2 struct { var _ ec2iface.EC2API = &MockEC2{} +func (m *MockEC2) All() map[string]interface{} { + all := make(map[string]interface{}) + + for _, o := range m.Addresses { + all[aws.StringValue(o.AllocationId)] = o + } + for id, o := range m.RouteTables { + all[id] = o + } + for id, o := range m.DhcpOptions { + all[id] = o + } + for _, o := range m.Images { + all[aws.StringValue(o.ImageId)] = o + } + for id, o := range m.SecurityGroups { + all[id] = o + } + for id, o := range m.subnets { + all[id] = &o.main + } + for id, o := range m.Volumes { + all[id] = o + } + for id, o := range m.KeyPairs { + all[id] = o + } + for id, o := range m.Vpcs { + all[id] = o + } + for id, o := range m.InternetGateways { + all[id] = o + } + for id, o := range m.NatGateways { + all[id] = o + } + + return all +} + type idAllocator struct { NextId int } diff --git a/cloudmock/aws/mockec2/dhcpoptions.go b/cloudmock/aws/mockec2/dhcpoptions.go index 22ebf5b718..705b8ecc38 100644 --- a/cloudmock/aws/mockec2/dhcpoptions.go +++ b/cloudmock/aws/mockec2/dhcpoptions.go @@ -164,10 +164,22 @@ func (m *MockEC2) CreateDhcpOptionsRequest(*ec2.CreateDhcpOptionsInput) (*reques return nil, nil } -func (m *MockEC2) DeleteDhcpOptions(*ec2.DeleteDhcpOptionsInput) (*ec2.DeleteDhcpOptionsOutput, error) { - panic("Not implemented") - return nil, nil +func (m *MockEC2) DeleteDhcpOptions(request *ec2.DeleteDhcpOptionsInput) (*ec2.DeleteDhcpOptionsOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + + glog.Infof("DeleteDhcpOptions: %v", request) + + id := aws.StringValue(request.DhcpOptionsId) + o := m.DhcpOptions[id] + if o == nil { + return nil, fmt.Errorf("DhcpOptions %q not found", id) + } + delete(m.DhcpOptions, id) + + return &ec2.DeleteDhcpOptionsOutput{}, nil } + func (m *MockEC2) DeleteDhcpOptionsWithContext(aws.Context, *ec2.DeleteDhcpOptionsInput, ...request.Option) (*ec2.DeleteDhcpOptionsOutput, error) { panic("Not implemented") return nil, nil diff --git a/cloudmock/aws/mockec2/instances.go b/cloudmock/aws/mockec2/instances.go new file mode 100644 index 0000000000..266404823b --- /dev/null +++ b/cloudmock/aws/mockec2/instances.go @@ -0,0 +1,54 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package mockec2 + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/service/ec2" + "github.com/golang/glog" +) + +func (m *MockEC2) DescribeInstances(*ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error) { + glog.Warningf("MockEc2::DescribeInstances is stub-implemented") + return &ec2.DescribeInstancesOutput{}, nil +} + +func (m *MockEC2) DescribeInstancesWithContext(aws.Context, *ec2.DescribeInstancesInput, ...request.Option) (*ec2.DescribeInstancesOutput, error) { + panic("Not implemented") + return nil, nil +} +func (m *MockEC2) DescribeInstancesRequest(*ec2.DescribeInstancesInput) (*request.Request, *ec2.DescribeInstancesOutput) { + panic("Not implemented") + return nil, nil +} + +func (m *MockEC2) DescribeInstancesPages(request *ec2.DescribeInstancesInput, callback func(*ec2.DescribeInstancesOutput, bool) bool) error { + // For the mock, we just send everything in one page + page, err := m.DescribeInstances(request) + if err != nil { + return err + } + + callback(page, false) + + return nil +} +func (m *MockEC2) DescribeInstancesPagesWithContext(aws.Context, *ec2.DescribeInstancesInput, func(*ec2.DescribeInstancesOutput, bool) bool, ...request.Option) error { + panic("Not implemented") + return nil +} diff --git a/cloudmock/aws/mockec2/internetgateways.go b/cloudmock/aws/mockec2/internetgateways.go index 000c4e8718..f709893ad0 100644 --- a/cloudmock/aws/mockec2/internetgateways.go +++ b/cloudmock/aws/mockec2/internetgateways.go @@ -26,22 +26,24 @@ import ( "github.com/golang/glog" ) -type internetGatewayInfo struct { - main ec2.InternetGateway -} - func (m *MockEC2) FindInternetGateway(id string) *ec2.InternetGateway { + m.mutex.Lock() + defer m.mutex.Unlock() + internetGateway := m.InternetGateways[id] if internetGateway == nil { return nil } - copy := internetGateway.main + copy := *internetGateway copy.Tags = m.getTags(ec2.ResourceTypeInternetGateway, id) return © } func (m *MockEC2) InternetGatewayIds() []string { + m.mutex.Lock() + defer m.mutex.Unlock() + var ids []string for id := range m.InternetGateways { ids = append(ids, id) @@ -60,24 +62,24 @@ func (m *MockEC2) CreateInternetGatewayWithContext(aws.Context, *ec2.CreateInter } func (m *MockEC2) CreateInternetGateway(request *ec2.CreateInternetGatewayInput) (*ec2.CreateInternetGatewayOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + glog.Infof("CreateInternetGateway: %v", request) - m.internetGatewayNumber++ - n := m.internetGatewayNumber + id := m.allocateId("igw") - internetGateway := &ec2.InternetGateway{ - InternetGatewayId: s(fmt.Sprintf("igw-%d", n)), + igw := &ec2.InternetGateway{ + InternetGatewayId: s(id), } if m.InternetGateways == nil { - m.InternetGateways = make(map[string]*internetGatewayInfo) - } - m.InternetGateways[*internetGateway.InternetGatewayId] = &internetGatewayInfo{ - main: *internetGateway, + m.InternetGateways = make(map[string]*ec2.InternetGateway) } + m.InternetGateways[id] = igw response := &ec2.CreateInternetGatewayOutput{ - InternetGateway: internetGateway, + InternetGateway: igw, } return response, nil } @@ -100,16 +102,26 @@ func (m *MockEC2) DescribeInternetGateways(request *ec2.DescribeInternetGateways var internetGateways []*ec2.InternetGateway + if len(request.InternetGatewayIds) != 0 { + request.Filters = append(request.Filters, &ec2.Filter{Name: s("internet-gateway-id"), Values: request.InternetGatewayIds}) + } + for id, internetGateway := range m.InternetGateways { allFiltersMatch := true for _, filter := range request.Filters { match := false switch *filter.Name { + case "internet-gateway-id": + for _, v := range filter.Values { + if id == aws.StringValue(v) { + match = true + } + } case "attachment.vpc-id": for _, v := range filter.Values { - if internetGateway.main.Attachments != nil { - for _, attachment := range internetGateway.main.Attachments { + if internetGateway.Attachments != nil { + for _, attachment := range internetGateway.Attachments { if *attachment.VpcId == *v { match = true } @@ -119,7 +131,7 @@ func (m *MockEC2) DescribeInternetGateways(request *ec2.DescribeInternetGateways default: if strings.HasPrefix(*filter.Name, "tag:") { - match = m.hasTag(ec2.ResourceTypeInternetGateway, *internetGateway.main.InternetGatewayId, filter) + match = m.hasTag(ec2.ResourceTypeInternetGateway, id, filter) } else { return nil, fmt.Errorf("unknown filter name: %q", *filter.Name) } @@ -135,7 +147,7 @@ func (m *MockEC2) DescribeInternetGateways(request *ec2.DescribeInternetGateways continue } - copy := internetGateway.main + copy := *internetGateway copy.Tags = m.getTags(ec2.ResourceTypeInternetGateway, id) internetGateways = append(internetGateways, ©) } @@ -148,15 +160,21 @@ func (m *MockEC2) DescribeInternetGateways(request *ec2.DescribeInternetGateways } func (m *MockEC2) AttachInternetGateway(request *ec2.AttachInternetGatewayInput) (*ec2.AttachInternetGatewayOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + for id, internetGateway := range m.InternetGateways { if id == *request.InternetGatewayId { - internetGateway.main.Attachments = append(internetGateway.main.Attachments, + internetGateway.Attachments = append(internetGateway.Attachments, &ec2.InternetGatewayAttachment{ VpcId: request.VpcId, }) + return &ec2.AttachInternetGatewayOutput{}, nil } } - return &ec2.AttachInternetGatewayOutput{}, nil + + return nil, fmt.Errorf("InternetGateway not found") + } func (m *MockEC2) AttachInternetGatewayWithContext(aws.Context, *ec2.AttachInternetGatewayInput, ...request.Option) (*ec2.AttachInternetGatewayOutput, error) { @@ -167,3 +185,65 @@ func (m *MockEC2) AttachInternetGatewayRequest(*ec2.AttachInternetGatewayInput) panic("Not implemented") return nil, nil } + +func (m *MockEC2) DetachInternetGateway(request *ec2.DetachInternetGatewayInput) (*ec2.DetachInternetGatewayOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + + for id, igw := range m.InternetGateways { + if id == *request.InternetGatewayId { + found := false + var newAttachments []*ec2.InternetGatewayAttachment + for _, a := range igw.Attachments { + if aws.StringValue(a.VpcId) == aws.StringValue(request.VpcId) { + found = true + continue + } + newAttachments = append(newAttachments, a) + } + + if !found { + return nil, fmt.Errorf("Attachment to VPC not found") + } + igw.Attachments = newAttachments + + return &ec2.DetachInternetGatewayOutput{}, nil + } + } + + return nil, fmt.Errorf("InternetGateway not found") +} + +func (m *MockEC2) DetachInternetGatewayWithContext(aws.Context, *ec2.DetachInternetGatewayInput, ...request.Option) (*ec2.DetachInternetGatewayOutput, error) { + panic("Not implemented") + return nil, nil +} +func (m *MockEC2) DetachInternetGatewayRequest(*ec2.DetachInternetGatewayInput) (*request.Request, *ec2.DetachInternetGatewayOutput) { + panic("Not implemented") + return nil, nil +} + +func (m *MockEC2) DeleteInternetGateway(request *ec2.DeleteInternetGatewayInput) (*ec2.DeleteInternetGatewayOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + + glog.Infof("DeleteInternetGateway: %v", request) + + id := aws.StringValue(request.InternetGatewayId) + o := m.InternetGateways[id] + if o == nil { + return nil, fmt.Errorf("InternetGateway %q not found", id) + } + delete(m.InternetGateways, id) + + return &ec2.DeleteInternetGatewayOutput{}, nil +} + +func (m *MockEC2) DeleteInternetGatewayWithContext(aws.Context, *ec2.DeleteInternetGatewayInput, ...request.Option) (*ec2.DeleteInternetGatewayOutput, error) { + panic("Not implemented") + return nil, nil +} +func (m *MockEC2) DeleteInternetGatewayRequest(*ec2.DeleteInternetGatewayInput) (*request.Request, *ec2.DeleteInternetGatewayOutput) { + panic("Not implemented") + return nil, nil +} diff --git a/cloudmock/aws/mockec2/keypairs.go b/cloudmock/aws/mockec2/keypairs.go index 6af00bcfdf..5e687d216a 100644 --- a/cloudmock/aws/mockec2/keypairs.go +++ b/cloudmock/aws/mockec2/keypairs.go @@ -42,6 +42,9 @@ func (m *MockEC2) ImportKeyPairWithContext(aws.Context, *ec2.ImportKeyPairInput, return nil, nil } func (m *MockEC2) ImportKeyPair(request *ec2.ImportKeyPairInput) (*ec2.ImportKeyPairOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + glog.Infof("ImportKeyPair: %v", request) fp, err := pki.ComputeAWSKeyFingerprint(string(request.PublicKeyMaterial)) @@ -53,7 +56,10 @@ func (m *MockEC2) ImportKeyPair(request *ec2.ImportKeyPairInput) (*ec2.ImportKey KeyFingerprint: aws.String(fp), KeyName: request.KeyName, } - m.KeyPairs = append(m.KeyPairs, kp) + if m.KeyPairs == nil { + m.KeyPairs = make(map[string]*ec2.KeyPairInfo) + } + m.KeyPairs[aws.StringValue(request.KeyName)] = kp response := &ec2.ImportKeyPairOutput{ KeyFingerprint: kp.KeyFingerprint, KeyName: kp.KeyName, @@ -72,6 +78,9 @@ func (m *MockEC2) CreateKeyPair(*ec2.CreateKeyPairInput) (*ec2.CreateKeyPairOutp } func (m *MockEC2) DescribeKeyPairs(request *ec2.DescribeKeyPairsInput) (*ec2.DescribeKeyPairsOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + glog.Infof("DescribeKeyPairs: %v", request) var keypairs []*ec2.KeyPairInfo @@ -118,3 +127,28 @@ func (m *MockEC2) DescribeKeyPairs(request *ec2.DescribeKeyPairsInput) (*ec2.Des return response, nil } + +func (m *MockEC2) DeleteKeyPair(request *ec2.DeleteKeyPairInput) (*ec2.DeleteKeyPairOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + + glog.Infof("DeleteKeyPair: %v", request) + + id := aws.StringValue(request.KeyName) + o := m.KeyPairs[id] + if o == nil { + return nil, fmt.Errorf("KeyPairs %q not found", id) + } + delete(m.KeyPairs, id) + + return &ec2.DeleteKeyPairOutput{}, nil +} + +func (m *MockEC2) DeleteKeyPairWithContext(aws.Context, *ec2.DeleteKeyPairInput, ...request.Option) (*ec2.DeleteKeyPairOutput, error) { + panic("Not implemented") + return nil, nil +} +func (m *MockEC2) DeleteKeyPairRequest(*ec2.DeleteKeyPairInput) (*request.Request, *ec2.DeleteKeyPairOutput) { + panic("Not implemented") + return nil, nil +} diff --git a/cloudmock/aws/mockec2/natgateway.go b/cloudmock/aws/mockec2/natgateway.go index c52533855d..8bf9fb0e41 100644 --- a/cloudmock/aws/mockec2/natgateway.go +++ b/cloudmock/aws/mockec2/natgateway.go @@ -175,3 +175,28 @@ func (m *MockEC2) DescribeNatGatewaysPagesWithContext(aws.Context, *ec2.Describe panic("Not implemented") return nil } + +func (m *MockEC2) DeleteNatGateway(request *ec2.DeleteNatGatewayInput) (*ec2.DeleteNatGatewayOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + + glog.Infof("DeleteNatGateway: %v", request) + + id := aws.StringValue(request.NatGatewayId) + o := m.NatGateways[id] + if o == nil { + return nil, fmt.Errorf("NatGateway %q not found", id) + } + delete(m.NatGateways, id) + + return &ec2.DeleteNatGatewayOutput{}, nil +} + +func (m *MockEC2) DeleteNatGatewayWithContext(aws.Context, *ec2.DeleteNatGatewayInput, ...request.Option) (*ec2.DeleteNatGatewayOutput, error) { + panic("Not implemented") + return nil, nil +} +func (m *MockEC2) DeleteNatGatewayRequest(*ec2.DeleteNatGatewayInput) (*request.Request, *ec2.DeleteNatGatewayOutput) { + panic("Not implemented") + return nil, nil +} diff --git a/cloudmock/aws/mockec2/routetable.go b/cloudmock/aws/mockec2/routetable.go index 8ec7fa59f1..75cf1f1263 100644 --- a/cloudmock/aws/mockec2/routetable.go +++ b/cloudmock/aws/mockec2/routetable.go @@ -180,3 +180,27 @@ func (m *MockEC2) CreateRouteRequest(*ec2.CreateRouteInput) (*request.Request, * panic("Not implemented") return nil, nil } + +func (m *MockEC2) DeleteRouteTable(request *ec2.DeleteRouteTableInput) (*ec2.DeleteRouteTableOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + + glog.Infof("DeleteRouteTable: %v", request) + + id := aws.StringValue(request.RouteTableId) + o := m.RouteTables[id] + if o == nil { + return nil, fmt.Errorf("RouteTable %q not found", id) + } + delete(m.RouteTables, id) + + return &ec2.DeleteRouteTableOutput{}, nil +} +func (m *MockEC2) DeleteRouteTableWithContext(aws.Context, *ec2.DeleteRouteTableInput, ...request.Option) (*ec2.DeleteRouteTableOutput, error) { + panic("Not implemented") + return nil, nil +} +func (m *MockEC2) DeleteRouteTableRequest(*ec2.DeleteRouteTableInput) (*request.Request, *ec2.DeleteRouteTableOutput) { + panic("Not implemented") + return nil, nil +} diff --git a/cloudmock/aws/mockec2/securitygroups.go b/cloudmock/aws/mockec2/securitygroups.go index 0fec4aaf2b..565ee3223f 100644 --- a/cloudmock/aws/mockec2/securitygroups.go +++ b/cloudmock/aws/mockec2/securitygroups.go @@ -62,17 +62,30 @@ func (m *MockEC2) CreateSecurityGroup(request *ec2.CreateSecurityGroupInput) (*e return response, nil } -func (m *MockEC2) DeleteSecurityGroupRequest(*ec2.DeleteSecurityGroupInput) (*request.Request, *ec2.DeleteSecurityGroupOutput) { - panic("MockEC2 DeleteSecurityGroupRequest not implemented") +func (m *MockEC2) DeleteSecurityGroupRequest(request *ec2.DeleteSecurityGroupInput) (*request.Request, *ec2.DeleteSecurityGroupOutput) { + panic("Not implemented") return nil, nil } + func (m *MockEC2) DeleteSecurityGroupWithContext(aws.Context, *ec2.DeleteSecurityGroupInput, ...request.Option) (*ec2.DeleteSecurityGroupOutput, error) { panic("Not implemented") return nil, nil } -func (m *MockEC2) DeleteSecurityGroup(*ec2.DeleteSecurityGroupInput) (*ec2.DeleteSecurityGroupOutput, error) { - panic("MockEC2 DeleteSecurityGroup not implemented") - return nil, nil + +func (m *MockEC2) DeleteSecurityGroup(request *ec2.DeleteSecurityGroupInput) (*ec2.DeleteSecurityGroupOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + + glog.Infof("DeleteSecurityGroup: %v", request) + + id := aws.StringValue(request.GroupId) + o := m.SecurityGroups[id] + if o == nil { + return nil, fmt.Errorf("SecurityGroup %q not found", id) + } + delete(m.SecurityGroups, id) + + return &ec2.DeleteSecurityGroupOutput{}, nil } func (m *MockEC2) DescribeSecurityGroupReferencesRequest(*ec2.DescribeSecurityGroupReferencesInput) (*request.Request, *ec2.DescribeSecurityGroupReferencesOutput) { @@ -194,10 +207,35 @@ func (m *MockEC2) RevokeSecurityGroupIngressWithContext(aws.Context, *ec2.Revoke panic("Not implemented") return nil, nil } -func (m *MockEC2) RevokeSecurityGroupIngress(*ec2.RevokeSecurityGroupIngressInput) (*ec2.RevokeSecurityGroupIngressOutput, error) { - panic("Not implemented") - return nil, nil + +func (m *MockEC2) RevokeSecurityGroupIngress(request *ec2.RevokeSecurityGroupIngressInput) (*ec2.RevokeSecurityGroupIngressOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + + glog.Infof("RevokeSecurityGroupIngress: %v", request) + + if aws.StringValue(request.GroupId) == "" { + return nil, fmt.Errorf("GroupId not specified") + } + + if request.DryRun != nil { + glog.Fatalf("DryRun") + } + + if request.GroupName != nil { + glog.Fatalf("GroupName not implemented") + } + sg := m.SecurityGroups[*request.GroupId] + if sg == nil { + return nil, fmt.Errorf("SecurityGroup not found") + } + + glog.Warningf("RevokeSecurityGroupIngress not implemented - does not actually revoke permissions") + + response := &ec2.RevokeSecurityGroupIngressOutput{} + return response, nil } + func (m *MockEC2) AuthorizeSecurityGroupEgressRequest(*ec2.AuthorizeSecurityGroupEgressInput) (*request.Request, *ec2.AuthorizeSecurityGroupEgressOutput) { panic("Not implemented") return nil, nil diff --git a/cloudmock/aws/mockec2/subnets.go b/cloudmock/aws/mockec2/subnets.go index 2007659782..8f0d941c34 100644 --- a/cloudmock/aws/mockec2/subnets.go +++ b/cloudmock/aws/mockec2/subnets.go @@ -215,3 +215,28 @@ func (m *MockEC2) AssociateRouteTableRequest(*ec2.AssociateRouteTableInput) (*re panic("Not implemented") return nil, nil } + +func (m *MockEC2) DeleteSubnet(request *ec2.DeleteSubnetInput) (*ec2.DeleteSubnetOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + + glog.Infof("DeleteSubnet: %v", request) + + id := aws.StringValue(request.SubnetId) + o := m.subnets[id] + if o == nil { + return nil, fmt.Errorf("Subnet %q not found", id) + } + delete(m.subnets, id) + + return &ec2.DeleteSubnetOutput{}, nil +} + +func (m *MockEC2) DeleteSubnetWithContext(aws.Context, *ec2.DeleteSubnetInput, ...request.Option) (*ec2.DeleteSubnetOutput, error) { + panic("Not implemented") + return nil, nil +} +func (m *MockEC2) DeleteSubnetRequest(*ec2.DeleteSubnetInput) (*request.Request, *ec2.DeleteSubnetOutput) { + panic("Not implemented") + return nil, nil +} diff --git a/cloudmock/aws/mockec2/unimplemented.go b/cloudmock/aws/mockec2/unimplemented.go index 002ebf9c62..747b3b1873 100644 --- a/cloudmock/aws/mockec2/unimplemented.go +++ b/cloudmock/aws/mockec2/unimplemented.go @@ -606,46 +606,6 @@ func (m *MockEC2) DeleteFlowLogsRequest(*ec2.DeleteFlowLogsInput) (*request.Requ panic("Not implemented") return nil, nil } - -func (m *MockEC2) DeleteInternetGateway(*ec2.DeleteInternetGatewayInput) (*ec2.DeleteInternetGatewayOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockEC2) DeleteInternetGatewayWithContext(aws.Context, *ec2.DeleteInternetGatewayInput, ...request.Option) (*ec2.DeleteInternetGatewayOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockEC2) DeleteInternetGatewayRequest(*ec2.DeleteInternetGatewayInput) (*request.Request, *ec2.DeleteInternetGatewayOutput) { - panic("Not implemented") - return nil, nil -} - -func (m *MockEC2) DeleteKeyPair(*ec2.DeleteKeyPairInput) (*ec2.DeleteKeyPairOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockEC2) DeleteKeyPairWithContext(aws.Context, *ec2.DeleteKeyPairInput, ...request.Option) (*ec2.DeleteKeyPairOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockEC2) DeleteKeyPairRequest(*ec2.DeleteKeyPairInput) (*request.Request, *ec2.DeleteKeyPairOutput) { - panic("Not implemented") - return nil, nil -} - -func (m *MockEC2) DeleteNatGateway(*ec2.DeleteNatGatewayInput) (*ec2.DeleteNatGatewayOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockEC2) DeleteNatGatewayWithContext(aws.Context, *ec2.DeleteNatGatewayInput, ...request.Option) (*ec2.DeleteNatGatewayOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockEC2) DeleteNatGatewayRequest(*ec2.DeleteNatGatewayInput) (*request.Request, *ec2.DeleteNatGatewayOutput) { - panic("Not implemented") - return nil, nil -} - func (m *MockEC2) DeleteNetworkAcl(*ec2.DeleteNetworkAclInput) (*ec2.DeleteNetworkAclOutput, error) { panic("Not implemented") return nil, nil @@ -724,19 +684,6 @@ func (m *MockEC2) DeleteRouteRequest(*ec2.DeleteRouteInput) (*request.Request, * return nil, nil } -func (m *MockEC2) DeleteRouteTable(*ec2.DeleteRouteTableInput) (*ec2.DeleteRouteTableOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockEC2) DeleteRouteTableWithContext(aws.Context, *ec2.DeleteRouteTableInput, ...request.Option) (*ec2.DeleteRouteTableOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockEC2) DeleteRouteTableRequest(*ec2.DeleteRouteTableInput) (*request.Request, *ec2.DeleteRouteTableOutput) { - panic("Not implemented") - return nil, nil -} - func (m *MockEC2) DeleteSnapshot(*ec2.DeleteSnapshotInput) (*ec2.DeleteSnapshotOutput, error) { panic("Not implemented") return nil, nil @@ -763,19 +710,6 @@ func (m *MockEC2) DeleteSpotDatafeedSubscriptionRequest(*ec2.DeleteSpotDatafeedS return nil, nil } -func (m *MockEC2) DeleteSubnet(*ec2.DeleteSubnetInput) (*ec2.DeleteSubnetOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockEC2) DeleteSubnetWithContext(aws.Context, *ec2.DeleteSubnetInput, ...request.Option) (*ec2.DeleteSubnetOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockEC2) DeleteSubnetRequest(*ec2.DeleteSubnetInput) (*request.Request, *ec2.DeleteSubnetOutput) { - panic("Not implemented") - return nil, nil -} - func (m *MockEC2) DeleteTags(*ec2.DeleteTagsInput) (*ec2.DeleteTagsOutput, error) { panic("Not implemented") return nil, nil @@ -789,32 +723,6 @@ func (m *MockEC2) DeleteTagsRequest(*ec2.DeleteTagsInput) (*request.Request, *ec return nil, nil } -func (m *MockEC2) DeleteVolume(*ec2.DeleteVolumeInput) (*ec2.DeleteVolumeOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockEC2) DeleteVolumeWithContext(aws.Context, *ec2.DeleteVolumeInput, ...request.Option) (*ec2.DeleteVolumeOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockEC2) DeleteVolumeRequest(*ec2.DeleteVolumeInput) (*request.Request, *ec2.DeleteVolumeOutput) { - panic("Not implemented") - return nil, nil -} - -func (m *MockEC2) DeleteVpc(*ec2.DeleteVpcInput) (*ec2.DeleteVpcOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockEC2) DeleteVpcWithContext(aws.Context, *ec2.DeleteVpcInput, ...request.Option) (*ec2.DeleteVpcOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockEC2) DeleteVpcRequest(*ec2.DeleteVpcInput) (*request.Request, *ec2.DeleteVpcOutput) { - panic("Not implemented") - return nil, nil -} - func (m *MockEC2) DeleteVpcEndpoints(*ec2.DeleteVpcEndpointsInput) (*ec2.DeleteVpcEndpointsOutput, error) { panic("Not implemented") return nil, nil @@ -1175,28 +1083,6 @@ func (m *MockEC2) DescribeInstanceStatusPagesWithContext(aws.Context, *ec2.Descr return nil } -func (m *MockEC2) DescribeInstances(*ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockEC2) DescribeInstancesWithContext(aws.Context, *ec2.DescribeInstancesInput, ...request.Option) (*ec2.DescribeInstancesOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockEC2) DescribeInstancesRequest(*ec2.DescribeInstancesInput) (*request.Request, *ec2.DescribeInstancesOutput) { - panic("Not implemented") - return nil, nil -} - -func (m *MockEC2) DescribeInstancesPages(*ec2.DescribeInstancesInput, func(*ec2.DescribeInstancesOutput, bool) bool) error { - panic("Not implemented") - return nil -} -func (m *MockEC2) DescribeInstancesPagesWithContext(aws.Context, *ec2.DescribeInstancesInput, func(*ec2.DescribeInstancesOutput, bool) bool, ...request.Option) error { - panic("Not implemented") - return nil -} - func (m *MockEC2) DescribeMovingAddresses(*ec2.DescribeMovingAddressesInput) (*ec2.DescribeMovingAddressesOutput, error) { panic("Not implemented") return nil, nil @@ -1645,19 +1531,6 @@ func (m *MockEC2) DetachClassicLinkVpcRequest(*ec2.DetachClassicLinkVpcInput) (* return nil, nil } -func (m *MockEC2) DetachInternetGateway(*ec2.DetachInternetGatewayInput) (*ec2.DetachInternetGatewayOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockEC2) DetachInternetGatewayWithContext(aws.Context, *ec2.DetachInternetGatewayInput, ...request.Option) (*ec2.DetachInternetGatewayOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockEC2) DetachInternetGatewayRequest(*ec2.DetachInternetGatewayInput) (*request.Request, *ec2.DetachInternetGatewayOutput) { - panic("Not implemented") - return nil, nil -} - func (m *MockEC2) DetachNetworkInterface(*ec2.DetachNetworkInterfaceInput) (*ec2.DetachNetworkInterfaceOutput, error) { panic("Not implemented") return nil, nil diff --git a/cloudmock/aws/mockec2/volumes.go b/cloudmock/aws/mockec2/volumes.go index 5f803c2da6..17a4da3e0e 100644 --- a/cloudmock/aws/mockec2/volumes.go +++ b/cloudmock/aws/mockec2/volumes.go @@ -172,10 +172,18 @@ func (m *MockEC2) DescribeVolumes(request *ec2.DescribeVolumesInput) (*ec2.Descr return response, nil } -func (m *MockEC2) DescribeVolumesPages(*ec2.DescribeVolumesInput, func(*ec2.DescribeVolumesOutput, bool) bool) error { - panic("MockEC2 DescribeVolumesPages not implemented") +func (m *MockEC2) DescribeVolumesPages(request *ec2.DescribeVolumesInput, callback func(*ec2.DescribeVolumesOutput, bool) bool) error { + // For the mock, we just send everything in one page + page, err := m.DescribeVolumes(request) + if err != nil { + return err + } + + callback(page, false) + return nil } + func (m *MockEC2) DescribeVolumesPagesWithContext(aws.Context, *ec2.DescribeVolumesInput, func(*ec2.DescribeVolumesOutput, bool) bool, ...request.Option) error { panic("Not implemented") return nil @@ -193,3 +201,28 @@ func (m *MockEC2) DescribeVolumesModificationsRequest(*ec2.DescribeVolumesModifi panic("Not implemented") return nil, nil } + +func (m *MockEC2) DeleteVolume(request *ec2.DeleteVolumeInput) (*ec2.DeleteVolumeOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + + glog.Infof("DeleteVolume: %v", request) + + id := aws.StringValue(request.VolumeId) + o := m.Volumes[id] + if o == nil { + return nil, fmt.Errorf("Volume %q not found", id) + } + delete(m.Volumes, id) + + return &ec2.DeleteVolumeOutput{}, nil +} + +func (m *MockEC2) DeleteVolumeWithContext(aws.Context, *ec2.DeleteVolumeInput, ...request.Option) (*ec2.DeleteVolumeOutput, error) { + panic("Not implemented") + return nil, nil +} +func (m *MockEC2) DeleteVolumeRequest(*ec2.DeleteVolumeInput) (*request.Request, *ec2.DeleteVolumeOutput) { + panic("Not implemented") + return nil, nil +} diff --git a/cloudmock/aws/mockec2/vpcs.go b/cloudmock/aws/mockec2/vpcs.go index 3c5baef09a..ac031630f7 100644 --- a/cloudmock/aws/mockec2/vpcs.go +++ b/cloudmock/aws/mockec2/vpcs.go @@ -211,3 +211,28 @@ func (m *MockEC2) ModifyVpcAttributeRequest(*ec2.ModifyVpcAttributeInput) (*requ panic("Not implemented") return nil, nil } + +func (m *MockEC2) DeleteVpc(request *ec2.DeleteVpcInput) (*ec2.DeleteVpcOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + + glog.Infof("DeleteVpc: %v", request) + + id := aws.StringValue(request.VpcId) + o := m.Vpcs[id] + if o == nil { + return nil, fmt.Errorf("VPC %q not found", id) + } + delete(m.Vpcs, id) + + return &ec2.DeleteVpcOutput{}, nil +} + +func (m *MockEC2) DeleteVpcWithContext(aws.Context, *ec2.DeleteVpcInput, ...request.Option) (*ec2.DeleteVpcOutput, error) { + panic("Not implemented") + return nil, nil +} +func (m *MockEC2) DeleteVpcRequest(*ec2.DeleteVpcInput) (*request.Request, *ec2.DeleteVpcOutput) { + panic("Not implemented") + return nil, nil +} diff --git a/cloudmock/aws/mockelb/api.go b/cloudmock/aws/mockelb/api.go index abb210a2db..77d6e06aba 100644 --- a/cloudmock/aws/mockelb/api.go +++ b/cloudmock/aws/mockelb/api.go @@ -17,6 +17,7 @@ limitations under the License. package mockelb import ( + "fmt" "sync" "time" @@ -140,3 +141,19 @@ func (m *MockELB) CreateLoadBalancer(request *elb.CreateLoadBalancerInput) (*elb DNSName: aws.String(dnsName), }, nil } + +func (m *MockELB) DeleteLoadBalancer(request *elb.DeleteLoadBalancerInput) (*elb.DeleteLoadBalancerOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + + glog.Infof("DeleteLoadBalancer: %v", request) + + id := aws.StringValue(request.LoadBalancerName) + o := m.LoadBalancers[id] + if o == nil { + return nil, fmt.Errorf("LoadBalancer %q not found", id) + } + delete(m.LoadBalancers, id) + + return &elb.DeleteLoadBalancerOutput{}, nil +} diff --git a/cloudmock/aws/mockiam/iaminstanceprofile.go b/cloudmock/aws/mockiam/iaminstanceprofile.go index 19611a733b..4f35eca1aa 100644 --- a/cloudmock/aws/mockiam/iaminstanceprofile.go +++ b/cloudmock/aws/mockiam/iaminstanceprofile.go @@ -27,6 +27,9 @@ import ( ) func (m *MockIAM) GetInstanceProfile(request *iam.GetInstanceProfileInput) (*iam.GetInstanceProfileOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + ip := m.InstanceProfiles[aws.StringValue(request.InstanceProfileName)] if ip == nil { return nil, awserr.New("NoSuchEntity", "No such entity", nil) @@ -106,11 +109,127 @@ func (m *MockIAM) AddRoleToInstanceProfile(request *iam.AddRoleToInstanceProfile return &iam.AddRoleToInstanceProfileOutput{}, nil } + func (m *MockIAM) AddRoleToInstanceProfileWithContext(aws.Context, *iam.AddRoleToInstanceProfileInput, ...request.Option) (*iam.AddRoleToInstanceProfileOutput, error) { panic("Not implemented") return nil, nil } + func (m *MockIAM) AddRoleToInstanceProfileRequest(*iam.AddRoleToInstanceProfileInput) (*request.Request, *iam.AddRoleToInstanceProfileOutput) { panic("Not implemented") return nil, nil } + +func (m *MockIAM) RemoveRoleFromInstanceProfile(request *iam.RemoveRoleFromInstanceProfileInput) (*iam.RemoveRoleFromInstanceProfileOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + + glog.Infof("RemoveRoleFromInstanceProfile: %v", request) + + ip := m.InstanceProfiles[aws.StringValue(request.InstanceProfileName)] + if ip == nil { + return nil, fmt.Errorf("InstanceProfile not found") + } + + found := false + var newRoles []*iam.Role + for _, role := range ip.Roles { + if aws.StringValue(role.RoleName) == aws.StringValue(request.RoleName) { + found = true + continue + } + newRoles = append(newRoles, role) + } + + if !found { + return nil, fmt.Errorf("Role not found") + } + ip.Roles = newRoles + + return &iam.RemoveRoleFromInstanceProfileOutput{}, nil +} + +func (m *MockIAM) RemoveRoleFromInstanceProfileWithContext(aws.Context, *iam.RemoveRoleFromInstanceProfileInput, ...request.Option) (*iam.RemoveRoleFromInstanceProfileOutput, error) { + panic("Not implemented") + return nil, nil +} +func (m *MockIAM) RemoveRoleFromInstanceProfileRequest(*iam.RemoveRoleFromInstanceProfileInput) (*request.Request, *iam.RemoveRoleFromInstanceProfileOutput) { + panic("Not implemented") + return nil, nil +} + +func (m *MockIAM) ListInstanceProfiles(request *iam.ListInstanceProfilesInput) (*iam.ListInstanceProfilesOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + + glog.Infof("ListInstanceProfiles: %v", request) + + if request.PathPrefix != nil { + glog.Fatalf("MockIAM ListInstanceProfiles PathPrefix not implemented") + } + + var instanceProfiles []*iam.InstanceProfile + + for _, ip := range m.InstanceProfiles { + copy := *ip + instanceProfiles = append(instanceProfiles, ©) + } + + response := &iam.ListInstanceProfilesOutput{ + InstanceProfiles: instanceProfiles, + } + + return response, nil +} + +func (m *MockIAM) ListInstanceProfilesWithContext(aws.Context, *iam.ListInstanceProfilesInput, ...request.Option) (*iam.ListInstanceProfilesOutput, error) { + panic("Not implemented") + return nil, nil +} + +func (m *MockIAM) ListInstanceProfilesRequest(*iam.ListInstanceProfilesInput) (*request.Request, *iam.ListInstanceProfilesOutput) { + panic("Not implemented") + return nil, nil +} + +func (m *MockIAM) ListInstanceProfilesPages(request *iam.ListInstanceProfilesInput, callback func(*iam.ListInstanceProfilesOutput, bool) bool) error { + // For the mock, we just send everything in one page + page, err := m.ListInstanceProfiles(request) + if err != nil { + return err + } + + callback(page, false) + + return nil +} + +func (m *MockIAM) ListInstanceProfilesPagesWithContext(aws.Context, *iam.ListInstanceProfilesInput, func(*iam.ListInstanceProfilesOutput, bool) bool, ...request.Option) error { + panic("Not implemented") + return nil +} + +func (m *MockIAM) DeleteInstanceProfile(request *iam.DeleteInstanceProfileInput) (*iam.DeleteInstanceProfileOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + + glog.Infof("DeleteInstanceProfile: %v", request) + + id := aws.StringValue(request.InstanceProfileName) + o := m.InstanceProfiles[id] + if o == nil { + return nil, fmt.Errorf("InstanceProfile %q not found", id) + } + delete(m.InstanceProfiles, id) + + return &iam.DeleteInstanceProfileOutput{}, nil +} + +func (m *MockIAM) DeleteInstanceProfileWithContext(aws.Context, *iam.DeleteInstanceProfileInput, ...request.Option) (*iam.DeleteInstanceProfileOutput, error) { + panic("Not implemented") + return nil, nil +} +func (m *MockIAM) DeleteInstanceProfileRequest(*iam.DeleteInstanceProfileInput) (*request.Request, *iam.DeleteInstanceProfileOutput) { + panic("Not implemented") + return nil, nil +} diff --git a/cloudmock/aws/mockiam/iamrole.go b/cloudmock/aws/mockiam/iamrole.go index 93784c9afb..4b74794540 100644 --- a/cloudmock/aws/mockiam/iamrole.go +++ b/cloudmock/aws/mockiam/iamrole.go @@ -17,6 +17,8 @@ limitations under the License. package mockiam import ( + "fmt" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/request" @@ -25,6 +27,9 @@ import ( ) func (m *MockIAM) GetRole(request *iam.GetRoleInput) (*iam.GetRoleOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + role := m.Roles[aws.StringValue(request.RoleName)] if role == nil { return nil, awserr.New("NoSuchEntity", "No such entity", nil) @@ -77,3 +82,77 @@ func (m *MockIAM) CreateRoleRequest(*iam.CreateRoleInput) (*request.Request, *ia panic("Not implemented") return nil, nil } + +func (m *MockIAM) ListRoles(request *iam.ListRolesInput) (*iam.ListRolesOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + + glog.Infof("ListRoles: %v", request) + + if request.PathPrefix != nil { + glog.Fatalf("MockIAM ListRoles PathPrefix not implemented") + } + + var roles []*iam.Role + + for _, r := range m.Roles { + copy := *r + roles = append(roles, ©) + } + + response := &iam.ListRolesOutput{ + Roles: roles, + } + + return response, nil +} + +func (m *MockIAM) ListRolesWithContext(aws.Context, *iam.ListRolesInput, ...request.Option) (*iam.ListRolesOutput, error) { + panic("Not implemented") + return nil, nil +} +func (m *MockIAM) ListRolesRequest(*iam.ListRolesInput) (*request.Request, *iam.ListRolesOutput) { + panic("Not implemented") + return nil, nil +} + +func (m *MockIAM) ListRolesPages(request *iam.ListRolesInput, callback func(*iam.ListRolesOutput, bool) bool) error { + // For the mock, we just send everything in one page + page, err := m.ListRoles(request) + if err != nil { + return err + } + + callback(page, false) + + return nil +} + +func (m *MockIAM) ListRolesPagesWithContext(aws.Context, *iam.ListRolesInput, func(*iam.ListRolesOutput, bool) bool, ...request.Option) error { + panic("Not implemented") + return nil +} + +func (m *MockIAM) DeleteRole(request *iam.DeleteRoleInput) (*iam.DeleteRoleOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + + glog.Infof("DeleteRole: %v", request) + + id := aws.StringValue(request.RoleName) + o := m.Roles[id] + if o == nil { + return nil, fmt.Errorf("Role %q not found", id) + } + delete(m.Roles, id) + + return &iam.DeleteRoleOutput{}, nil +} +func (m *MockIAM) DeleteRoleWithContext(aws.Context, *iam.DeleteRoleInput, ...request.Option) (*iam.DeleteRoleOutput, error) { + panic("Not implemented") + return nil, nil +} +func (m *MockIAM) DeleteRoleRequest(*iam.DeleteRoleInput) (*request.Request, *iam.DeleteRoleOutput) { + panic("Not implemented") + return nil, nil +} diff --git a/cloudmock/aws/mockiam/iamrolepolicy.go b/cloudmock/aws/mockiam/iamrolepolicy.go index 3e71122343..58bbe9d73e 100644 --- a/cloudmock/aws/mockiam/iamrolepolicy.go +++ b/cloudmock/aws/mockiam/iamrolepolicy.go @@ -17,6 +17,8 @@ limitations under the License. package mockiam import ( + "fmt" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/request" @@ -31,6 +33,9 @@ type rolePolicy struct { } func (m *MockIAM) GetRolePolicy(request *iam.GetRolePolicyInput) (*iam.GetRolePolicyOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + for _, rp := range m.RolePolicies { if rp.PolicyName != aws.StringValue(request.PolicyName) { // TODO: check regex? @@ -95,3 +100,86 @@ func (m *MockIAM) PutRolePolicyRequest(*iam.PutRolePolicyInput) (*request.Reques panic("Not implemented") return nil, nil } + +func (m *MockIAM) ListRolePolicies(request *iam.ListRolePoliciesInput) (*iam.ListRolePoliciesOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + + glog.Infof("ListRolePolicies: %v", request) + + var policyNames []string + + for _, r := range m.RolePolicies { + if request.RoleName != nil { + if r.RoleName != aws.StringValue(request.RoleName) { + continue + } + } + policyNames = append(policyNames, r.PolicyName) + } + + response := &iam.ListRolePoliciesOutput{ + PolicyNames: aws.StringSlice(policyNames), + } + + return response, nil +} + +func (m *MockIAM) ListRolePoliciesWithContext(aws.Context, *iam.ListRolePoliciesInput, ...request.Option) (*iam.ListRolePoliciesOutput, error) { + panic("Not implemented") + return nil, nil +} + +func (m *MockIAM) ListRolePoliciesRequest(*iam.ListRolePoliciesInput) (*request.Request, *iam.ListRolePoliciesOutput) { + panic("Not implemented") + return nil, nil +} + +func (m *MockIAM) ListRolePoliciesPages(request *iam.ListRolePoliciesInput, callback func(*iam.ListRolePoliciesOutput, bool) bool) error { + // For the mock, we just send everything in one page + page, err := m.ListRolePolicies(request) + if err != nil { + return err + } + + callback(page, false) + + return nil +} + +func (m *MockIAM) ListRolePoliciesPagesWithContext(aws.Context, *iam.ListRolePoliciesInput, func(*iam.ListRolePoliciesOutput, bool) bool, ...request.Option) error { + panic("Not implemented") + return nil +} + +func (m *MockIAM) DeleteRolePolicy(request *iam.DeleteRolePolicyInput) (*iam.DeleteRolePolicyOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + + glog.Infof("DeleteRolePolicy: %v", request) + + found := false + var newRolePolicies []*rolePolicy + for _, rp := range m.RolePolicies { + if rp.PolicyName == aws.StringValue(request.PolicyName) && rp.RoleName == aws.StringValue(request.RoleName) { + found = true + continue + } + newRolePolicies = append(newRolePolicies, rp) + } + if !found { + return nil, fmt.Errorf("RolePolicy not found") + } + m.RolePolicies = newRolePolicies + + return &iam.DeleteRolePolicyOutput{}, nil +} + +func (m *MockIAM) DeleteRolePolicyWithContext(aws.Context, *iam.DeleteRolePolicyInput, ...request.Option) (*iam.DeleteRolePolicyOutput, error) { + panic("Not implemented") + return nil, nil +} +func (m *MockIAM) DeleteRolePolicyRequest(*iam.DeleteRolePolicyInput) (*request.Request, *iam.DeleteRolePolicyOutput) { + panic("Not implemented") + return nil, nil +} diff --git a/cloudmock/aws/mockiam/unimplemented.go b/cloudmock/aws/mockiam/unimplemented.go index 89be7a3e35..a4ca1aa04a 100644 --- a/cloudmock/aws/mockiam/unimplemented.go +++ b/cloudmock/aws/mockiam/unimplemented.go @@ -310,18 +310,7 @@ func (m *MockIAM) DeleteGroupPolicyRequest(*iam.DeleteGroupPolicyInput) (*reques panic("Not implemented") return nil, nil } -func (m *MockIAM) DeleteInstanceProfile(*iam.DeleteInstanceProfileInput) (*iam.DeleteInstanceProfileOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockIAM) DeleteInstanceProfileWithContext(aws.Context, *iam.DeleteInstanceProfileInput, ...request.Option) (*iam.DeleteInstanceProfileOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockIAM) DeleteInstanceProfileRequest(*iam.DeleteInstanceProfileInput) (*request.Request, *iam.DeleteInstanceProfileOutput) { - panic("Not implemented") - return nil, nil -} + func (m *MockIAM) DeleteLoginProfile(*iam.DeleteLoginProfileInput) (*iam.DeleteLoginProfileOutput, error) { panic("Not implemented") return nil, nil @@ -370,30 +359,6 @@ func (m *MockIAM) DeletePolicyVersionRequest(*iam.DeletePolicyVersionInput) (*re panic("Not implemented") return nil, nil } -func (m *MockIAM) DeleteRole(*iam.DeleteRoleInput) (*iam.DeleteRoleOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockIAM) DeleteRoleWithContext(aws.Context, *iam.DeleteRoleInput, ...request.Option) (*iam.DeleteRoleOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockIAM) DeleteRoleRequest(*iam.DeleteRoleInput) (*request.Request, *iam.DeleteRoleOutput) { - panic("Not implemented") - return nil, nil -} -func (m *MockIAM) DeleteRolePolicy(*iam.DeleteRolePolicyInput) (*iam.DeleteRolePolicyOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockIAM) DeleteRolePolicyWithContext(aws.Context, *iam.DeleteRolePolicyInput, ...request.Option) (*iam.DeleteRolePolicyOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockIAM) DeleteRolePolicyRequest(*iam.DeleteRolePolicyInput) (*request.Request, *iam.DeleteRolePolicyOutput) { - panic("Not implemented") - return nil, nil -} func (m *MockIAM) DeleteSAMLProvider(*iam.DeleteSAMLProviderInput) (*iam.DeleteSAMLProviderOutput, error) { panic("Not implemented") return nil, nil @@ -987,26 +952,6 @@ func (m *MockIAM) ListGroupsForUserPagesWithContext(aws.Context, *iam.ListGroups panic("Not implemented") return nil } -func (m *MockIAM) ListInstanceProfiles(*iam.ListInstanceProfilesInput) (*iam.ListInstanceProfilesOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockIAM) ListInstanceProfilesWithContext(aws.Context, *iam.ListInstanceProfilesInput, ...request.Option) (*iam.ListInstanceProfilesOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockIAM) ListInstanceProfilesRequest(*iam.ListInstanceProfilesInput) (*request.Request, *iam.ListInstanceProfilesOutput) { - panic("Not implemented") - return nil, nil -} -func (m *MockIAM) ListInstanceProfilesPages(*iam.ListInstanceProfilesInput, func(*iam.ListInstanceProfilesOutput, bool) bool) error { - panic("Not implemented") - return nil -} -func (m *MockIAM) ListInstanceProfilesPagesWithContext(aws.Context, *iam.ListInstanceProfilesInput, func(*iam.ListInstanceProfilesOutput, bool) bool, ...request.Option) error { - panic("Not implemented") - return nil -} func (m *MockIAM) ListInstanceProfilesForRole(*iam.ListInstanceProfilesForRoleInput) (*iam.ListInstanceProfilesForRoleOutput, error) { panic("Not implemented") return nil, nil @@ -1099,46 +1044,6 @@ func (m *MockIAM) ListPolicyVersionsPagesWithContext(aws.Context, *iam.ListPolic panic("Not implemented") return nil } -func (m *MockIAM) ListRolePolicies(*iam.ListRolePoliciesInput) (*iam.ListRolePoliciesOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockIAM) ListRolePoliciesWithContext(aws.Context, *iam.ListRolePoliciesInput, ...request.Option) (*iam.ListRolePoliciesOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockIAM) ListRolePoliciesRequest(*iam.ListRolePoliciesInput) (*request.Request, *iam.ListRolePoliciesOutput) { - panic("Not implemented") - return nil, nil -} -func (m *MockIAM) ListRolePoliciesPages(*iam.ListRolePoliciesInput, func(*iam.ListRolePoliciesOutput, bool) bool) error { - panic("Not implemented") - return nil -} -func (m *MockIAM) ListRolePoliciesPagesWithContext(aws.Context, *iam.ListRolePoliciesInput, func(*iam.ListRolePoliciesOutput, bool) bool, ...request.Option) error { - panic("Not implemented") - return nil -} -func (m *MockIAM) ListRoles(*iam.ListRolesInput) (*iam.ListRolesOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockIAM) ListRolesWithContext(aws.Context, *iam.ListRolesInput, ...request.Option) (*iam.ListRolesOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockIAM) ListRolesRequest(*iam.ListRolesInput) (*request.Request, *iam.ListRolesOutput) { - panic("Not implemented") - return nil, nil -} -func (m *MockIAM) ListRolesPages(*iam.ListRolesInput, func(*iam.ListRolesOutput, bool) bool) error { - panic("Not implemented") - return nil -} -func (m *MockIAM) ListRolesPagesWithContext(aws.Context, *iam.ListRolesInput, func(*iam.ListRolesOutput, bool) bool, ...request.Option) error { - panic("Not implemented") - return nil -} func (m *MockIAM) ListSAMLProviders(*iam.ListSAMLProvidersInput) (*iam.ListSAMLProvidersOutput, error) { panic("Not implemented") return nil, nil @@ -1319,18 +1224,6 @@ func (m *MockIAM) RemoveClientIDFromOpenIDConnectProviderRequest(*iam.RemoveClie panic("Not implemented") return nil, nil } -func (m *MockIAM) RemoveRoleFromInstanceProfile(*iam.RemoveRoleFromInstanceProfileInput) (*iam.RemoveRoleFromInstanceProfileOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockIAM) RemoveRoleFromInstanceProfileWithContext(aws.Context, *iam.RemoveRoleFromInstanceProfileInput, ...request.Option) (*iam.RemoveRoleFromInstanceProfileOutput, error) { - panic("Not implemented") - return nil, nil -} -func (m *MockIAM) RemoveRoleFromInstanceProfileRequest(*iam.RemoveRoleFromInstanceProfileInput) (*request.Request, *iam.RemoveRoleFromInstanceProfileOutput) { - panic("Not implemented") - return nil, nil -} func (m *MockIAM) RemoveUserFromGroup(*iam.RemoveUserFromGroupInput) (*iam.RemoveUserFromGroupOutput, error) { panic("Not implemented") return nil, nil diff --git a/cloudmock/aws/mockroute53/api.go b/cloudmock/aws/mockroute53/api.go index a2a51da7ce..906ded635f 100644 --- a/cloudmock/aws/mockroute53/api.go +++ b/cloudmock/aws/mockroute53/api.go @@ -18,6 +18,7 @@ package mockroute53 import ( "strings" + "sync" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/route53" @@ -32,6 +33,7 @@ type zoneInfo struct { } type MockRoute53 struct { + mutex sync.Mutex Zones []*zoneInfo } @@ -51,6 +53,9 @@ func (m *MockRoute53) findZone(hostedZoneId string) *zoneInfo { } func (m *MockRoute53) MockCreateZone(z *route53.HostedZone, vpcs []*route53.VPC) { + m.mutex.Lock() + defer m.mutex.Unlock() + zi := &zoneInfo{ ID: aws.StringValue(z.Id), hostedZone: z, diff --git a/cloudmock/aws/mockroute53/records.go b/cloudmock/aws/mockroute53/records.go index 0ea7eca3fb..b60453276a 100644 --- a/cloudmock/aws/mockroute53/records.go +++ b/cloudmock/aws/mockroute53/records.go @@ -46,6 +46,9 @@ func (m *MockRoute53) ListResourceRecordSetsPagesWithContext(aws.Context, *route } func (m *MockRoute53) ListResourceRecordSetsPages(request *route53.ListResourceRecordSetsInput, callback func(*route53.ListResourceRecordSetsOutput, bool) bool) error { + m.mutex.Lock() + defer m.mutex.Unlock() + glog.Infof("ListResourceRecordSetsPages %v", request) if request.HostedZoneId == nil { @@ -86,6 +89,9 @@ func (m *MockRoute53) ChangeResourceRecordSetsWithContext(aws.Context, *route53. } func (m *MockRoute53) ChangeResourceRecordSets(request *route53.ChangeResourceRecordSetsInput) (*route53.ChangeResourceRecordSetsOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + glog.Infof("ChangeResourceRecordSets %v", request) if request.HostedZoneId == nil { @@ -133,6 +139,14 @@ func (m *MockRoute53) ChangeResourceRecordSets(request *route53.ChangeResourceRe return nil, fmt.Errorf("duplicate record %s %q", changeType, changeName) } + case "DELETE": + if foundIndex == -1 { + // TODO: Use correct error + return nil, fmt.Errorf("record not found %s %q", changeType, changeName) + } else { + zone.records = append(zone.records[:foundIndex], zone.records[foundIndex+1:]...) + } + default: // TODO: Use correct error return nil, fmt.Errorf("Unsupported action: %q", aws.StringValue(change.Action)) diff --git a/cloudmock/aws/mockroute53/zones.go b/cloudmock/aws/mockroute53/zones.go index 52bb6b3d76..67dfb1555a 100644 --- a/cloudmock/aws/mockroute53/zones.go +++ b/cloudmock/aws/mockroute53/zones.go @@ -36,6 +36,9 @@ func (m *MockRoute53) GetHostedZoneWithContext(aws.Context, *route53.GetHostedZo } func (m *MockRoute53) GetHostedZone(request *route53.GetHostedZoneInput) (*route53.GetHostedZoneOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + glog.Infof("GetHostedZone %v", request) if request.Id == nil { @@ -91,6 +94,9 @@ func (m *MockRoute53) ListHostedZonesPagesWithContext(aws.Context, *route53.List } func (m *MockRoute53) ListHostedZonesPages(request *route53.ListHostedZonesInput, callback func(*route53.ListHostedZonesOutput, bool) bool) error { + m.mutex.Lock() + defer m.mutex.Unlock() + glog.Infof("ListHostedZonesPages %v", request) page := &route53.ListHostedZonesOutput{} @@ -115,6 +121,9 @@ func (m *MockRoute53) ListHostedZonesByNameWithContext(aws.Context, *route53.Lis } func (m *MockRoute53) ListHostedZonesByName(*route53.ListHostedZonesByNameInput) (*route53.ListHostedZonesByNameOutput, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + var zones []*route53.HostedZone for _, z := range m.Zones { diff --git a/cmd/kops/lifecycle_integration_test.go b/cmd/kops/lifecycle_integration_test.go index 1cef0cb951..5bd1f89a99 100644 --- a/cmd/kops/lifecycle_integration_test.go +++ b/cmd/kops/lifecycle_integration_test.go @@ -19,15 +19,18 @@ package main import ( "bytes" "path" + "reflect" + "sort" "strings" "testing" "time" - "k8s.io/kops/upup/pkg/fi" - + "k8s.io/kops/cloudmock/aws/mockec2" "k8s.io/kops/cmd/kops/util" "k8s.io/kops/pkg/testutils" + "k8s.io/kops/upup/pkg/fi" "k8s.io/kops/upup/pkg/fi/cloudup" + "k8s.io/kops/upup/pkg/fi/cloudup/awsup" ) type LifecycleTestOptions struct { @@ -168,6 +171,25 @@ func runLifecycleTest(h *testutils.IntegrationTestHarness, o *LifecycleTestOptio t.Fatalf("Target had changes after executing: %v", b.String()) } } + + { + options := &DeleteClusterOptions{} + options.Yes = true + options.ClusterName = o.ClusterName + + if err := RunDeleteCluster(factory, &stdout, options); err != nil { + t.Fatalf("error running delete cluster %q: %v", o.ClusterName, err) + } + } +} + +// AllResources returns all resources +func AllResources(c *awsup.MockAWSCloud) map[string]interface{} { + all := make(map[string]interface{}) + for k, v := range c.MockEC2.(*mockec2.MockEC2).All() { + all[k] = v + } + return all } func runLifecycleTestAWS(o *LifecycleTestOptions) { @@ -177,7 +199,23 @@ func runLifecycleTestAWS(o *LifecycleTestOptions) { defer h.Close() h.MockKopsVersion("1.8.1") - h.SetupMockAWS() + cloud := h.SetupMockAWS() + + var beforeIds []string + for id := range AllResources(cloud) { + beforeIds = append(beforeIds, id) + } + sort.Strings(beforeIds) runLifecycleTest(h, o) + + var afterIds []string + for id := range AllResources(cloud) { + afterIds = append(afterIds, id) + } + sort.Strings(afterIds) + + if !reflect.DeepEqual(beforeIds, afterIds) { + h.T.Fatalf("resources changed by cluster create / destroy: %v -> %v", beforeIds, afterIds) + } } diff --git a/upup/pkg/fi/cloudup/awstasks/elastic_ip_test.go b/upup/pkg/fi/cloudup/awstasks/elastic_ip_test.go index d55df47bf4..c5e1278efe 100644 --- a/upup/pkg/fi/cloudup/awstasks/elastic_ip_test.go +++ b/upup/pkg/fi/cloudup/awstasks/elastic_ip_test.go @@ -94,7 +94,7 @@ func TestElasticIPCreate(t *testing.T) { Domain: s("vpc"), PublicIp: s("192.0.2.1"), } - actual := c.Addresses[0] + actual := c.Addresses[*eip1.ID] if !reflect.DeepEqual(actual, expected) { t.Fatalf("Unexpected ElasticIP: expected=%v actual=%v", expected, actual) }