diff --git a/cloudmock/aws/mockautoscaling/ec2shim.go b/cloudmock/aws/mockautoscaling/ec2shim.go index 09d8630431..71f67568f5 100644 --- a/cloudmock/aws/mockautoscaling/ec2shim.go +++ b/cloudmock/aws/mockautoscaling/ec2shim.go @@ -21,30 +21,29 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/autoscaling" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/ec2/ec2iface" + "github.com/aws/aws-sdk-go-v2/service/ec2" + "k8s.io/kops/util/pkg/awsinterfaces" ) type ec2Shim struct { - ec2iface.EC2API + awsinterfaces.EC2API mockAutoscaling *MockAutoscaling } -func (m *MockAutoscaling) GetEC2Shim(e ec2iface.EC2API) ec2iface.EC2API { +func (m *MockAutoscaling) GetEC2Shim(e awsinterfaces.EC2API) awsinterfaces.EC2API { return &ec2Shim{ EC2API: e, mockAutoscaling: m, } } -func (e *ec2Shim) TerminateInstances(input *ec2.TerminateInstancesInput) (*ec2.TerminateInstancesOutput, error) { - ctx := context.TODO() +func (e *ec2Shim) TerminateInstances(ctx context.Context, input *ec2.TerminateInstancesInput, optFns ...func(*ec2.Options)) (*ec2.TerminateInstancesOutput, error) { if input.DryRun != nil && *input.DryRun { return &ec2.TerminateInstancesOutput{}, nil } for _, id := range input.InstanceIds { request := &autoscaling.TerminateInstanceInAutoScalingGroupInput{ - InstanceId: id, + InstanceId: aws.String(id), ShouldDecrementDesiredCapacity: aws.Bool(false), } if _, err := e.mockAutoscaling.TerminateInstanceInAutoScalingGroup(ctx, request); err != nil { diff --git a/cloudmock/aws/mockec2/api.go b/cloudmock/aws/mockec2/api.go index d562a6d9ec..a6bc83a544 100644 --- a/cloudmock/aws/mockec2/api.go +++ b/cloudmock/aws/mockec2/api.go @@ -20,15 +20,14 @@ 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" + "github.com/aws/aws-sdk-go-v2/aws" ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "k8s.io/kops/util/pkg/awsinterfaces" ) type MockEC2 struct { // Stub out interface - ec2iface.EC2API + awsinterfaces.EC2API mutex sync.Mutex @@ -39,7 +38,7 @@ type MockEC2 struct { DhcpOptions map[string]*ec2types.DhcpOptions - Images []*ec2.Image + Images []*ec2types.Image securityGroupNumber int SecurityGroups map[string]*ec2types.SecurityGroup @@ -47,11 +46,11 @@ type MockEC2 struct { subnets map[string]*subnetInfo - Volumes map[string]*ec2.Volume + Volumes map[string]*ec2types.Volume - KeyPairs map[string]*ec2.KeyPairInfo + KeyPairs map[string]*ec2types.KeyPairInfo - Tags []*ec2.TagDescription + Tags []*ec2types.TagDescription Vpcs map[string]*vpcInfo @@ -67,13 +66,13 @@ type MockEC2 struct { ids map[string]*idAllocator } -var _ ec2iface.EC2API = &MockEC2{} +var _ awsinterfaces.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 + all[aws.ToString(o.AllocationId)] = o } for id, o := range m.RouteTables { all[id] = o @@ -82,7 +81,7 @@ func (m *MockEC2) All() map[string]interface{} { all[id] = o } for _, o := range m.Images { - all[aws.StringValue(o.ImageId)] = o + all[aws.ToString(o.ImageId)] = o } for id, o := range m.SecurityGroups { all[id] = o diff --git a/cloudmock/aws/mockec2/convenience.go b/cloudmock/aws/mockec2/convenience.go index 78465eaa74..eadf15c28d 100644 --- a/cloudmock/aws/mockec2/convenience.go +++ b/cloudmock/aws/mockec2/convenience.go @@ -16,7 +16,7 @@ limitations under the License. package mockec2 -import "github.com/aws/aws-sdk-go/aws" +import "github.com/aws/aws-sdk-go-v2/aws" // s is a helper that builds a *string from a string value func s(v string) *string { diff --git a/cloudmock/aws/mockec2/images.go b/cloudmock/aws/mockec2/images.go index ae3054af9d..c1814bf19f 100644 --- a/cloudmock/aws/mockec2/images.go +++ b/cloudmock/aws/mockec2/images.go @@ -17,79 +17,45 @@ limitations under the License. package mockec2 import ( + "context" "fmt" "strings" - "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/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "k8s.io/klog/v2" ) -func (m *MockEC2) DescribeImageAttributeRequest(*ec2.DescribeImageAttributeInput) (*request.Request, *ec2.DescribeImageAttributeOutput) { - panic("Not implemented") -} - -func (m *MockEC2) DescribeImageAttributeWithContext(aws.Context, *ec2.DescribeImageAttributeInput, ...request.Option) (*ec2.DescribeImageAttributeOutput, error) { - panic("Not implemented") -} - -func (m *MockEC2) DescribeImageAttribute(*ec2.DescribeImageAttributeInput) (*ec2.DescribeImageAttributeOutput, error) { - panic("Not implemented") -} - -func (m *MockEC2) DescribeImagesRequest(*ec2.DescribeImagesInput) (*request.Request, *ec2.DescribeImagesOutput) { - panic("Not implemented") -} - -func (m *MockEC2) DescribeImagesWithContext(aws.Context, *ec2.DescribeImagesInput, ...request.Option) (*ec2.DescribeImagesOutput, error) { - panic("Not implemented") -} - -func (m *MockEC2) DescribeImagesPagesWithContext(ctx aws.Context, request *ec2.DescribeImagesInput, callback func(output *ec2.DescribeImagesOutput, b bool) bool, options ...request.Option) error { +func (m *MockEC2) DescribeImages(ctx context.Context, request *ec2.DescribeImagesInput, optFns ...func(*ec2.Options)) (*ec2.DescribeImagesOutput, error) { m.mutex.Lock() defer m.mutex.Unlock() klog.Infof("DescribeImagesPages: %v", request) - var images []*ec2.Image + var images []ec2types.Image for _, image := range m.Images { matches, err := m.imageMatchesFilter(image, request.Filters) if err != nil { - return err + return nil, err } if !matches { continue } copy := *image - copy.Tags = m.getTags(ec2.ResourceTypeImage, *image.ImageId) - images = append(images, ©) + copy.Tags = m.getTags(ec2types.ResourceTypeImage, *image.ImageId) + images = append(images, copy) } response := &ec2.DescribeImagesOutput{ Images: images, } - - callback(response, false) - - return nil + return response, nil } -func (m *MockEC2) DescribeImportImageTasksRequest(*ec2.DescribeImportImageTasksInput) (*request.Request, *ec2.DescribeImportImageTasksOutput) { - panic("Not implemented") -} - -func (m *MockEC2) DescribeImportImageTasksWithContext(aws.Context, *ec2.DescribeImportImageTasksInput, ...request.Option) (*ec2.DescribeImportImageTasksOutput, error) { - panic("Not implemented") -} - -func (m *MockEC2) DescribeImportImageTasks(*ec2.DescribeImportImageTasksInput) (*ec2.DescribeImportImageTasksOutput, error) { - panic("Not implemented") -} - -func (m *MockEC2) imageMatchesFilter(image *ec2.Image, filters []*ec2.Filter) (bool, error) { +func (m *MockEC2) imageMatchesFilter(image *ec2types.Image, filters []ec2types.Filter) (bool, error) { allFiltersMatch := true for _, filter := range filters { match := false @@ -97,14 +63,14 @@ func (m *MockEC2) imageMatchesFilter(image *ec2.Image, filters []*ec2.Filter) (b case "name": for _, v := range filter.Values { - if aws.StringValue(image.Name) == *v { + if aws.ToString(image.Name) == v { match = true } } default: if strings.HasPrefix(*filter.Name, "tag:") { - match = m.hasTag(ec2.ResourceTypeImage, *image.ImageId, filter) + match = m.hasTag(ec2types.ResourceTypeImage, *image.ImageId, filter) } else { return false, fmt.Errorf("unknown filter name: %q", *filter.Name) } diff --git a/cloudmock/aws/mockec2/instances.go b/cloudmock/aws/mockec2/instances.go index 8df203eac9..262596bee9 100644 --- a/cloudmock/aws/mockec2/instances.go +++ b/cloudmock/aws/mockec2/instances.go @@ -17,49 +17,27 @@ 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" + "context" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "k8s.io/klog/v2" ) -func (m *MockEC2) DescribeInstances(*ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error) { +func (m *MockEC2) DescribeInstances(ctx context.Context, request *ec2.DescribeInstancesInput, optFns ...func(*ec2.Options)) (*ec2.DescribeInstancesOutput, error) { klog.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") -} - -func (m *MockEC2) DescribeInstancesRequest(*ec2.DescribeInstancesInput) (*request.Request, *ec2.DescribeInstancesOutput) { - panic("Not implemented") -} - -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") -} - -func (m *MockEC2) DescribeInstanceTypes(*ec2.DescribeInstanceTypesInput) (*ec2.DescribeInstanceTypesOutput, error) { +func (m *MockEC2) DescribeInstanceTypes(ctx context.Context, request *ec2.DescribeInstanceTypesInput, optFns ...func(*ec2.Options)) (*ec2.DescribeInstanceTypesOutput, error) { klog.Warningf("MockEc2::DescribeInstanceTypes is stub-implemented") return &ec2.DescribeInstanceTypesOutput{}, nil } -func (m *MockEC2) GetInstanceTypesFromInstanceRequirements(input *ec2.GetInstanceTypesFromInstanceRequirementsInput) (*ec2.GetInstanceTypesFromInstanceRequirementsOutput, error) { +func (m *MockEC2) GetInstanceTypesFromInstanceRequirements(ctx context.Context, request *ec2.GetInstanceTypesFromInstanceRequirementsInput, optFns ...func(*ec2.Options)) (*ec2.GetInstanceTypesFromInstanceRequirementsOutput, error) { return &ec2.GetInstanceTypesFromInstanceRequirementsOutput{ - InstanceTypes: []*ec2.InstanceTypeInfoFromInstanceRequirements{ + InstanceTypes: []ec2types.InstanceTypeInfoFromInstanceRequirements{ { InstanceType: aws.String("c5.large"), }, diff --git a/cloudmock/aws/mockec2/keypairs.go b/cloudmock/aws/mockec2/keypairs.go index 3db54c7fc8..a0802c883b 100644 --- a/cloudmock/aws/mockec2/keypairs.go +++ b/cloudmock/aws/mockec2/keypairs.go @@ -17,33 +17,18 @@ limitations under the License. package mockec2 import ( + "context" "fmt" - "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/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "k8s.io/klog/v2" "k8s.io/kops/pkg/pki" ) -func (m *MockEC2) DescribeKeyPairsRequest(*ec2.DescribeKeyPairsInput) (*request.Request, *ec2.DescribeKeyPairsOutput) { - panic("MockEC2 DescribeKeyPairsRequest not implemented") -} - -func (m *MockEC2) DescribeKeyPairsWithContext(aws.Context, *ec2.DescribeKeyPairsInput, ...request.Option) (*ec2.DescribeKeyPairsOutput, error) { - panic("Not implemented") -} - -func (m *MockEC2) ImportKeyPairRequest(*ec2.ImportKeyPairInput) (*request.Request, *ec2.ImportKeyPairOutput) { - panic("MockEC2 ImportKeyPairRequest not implemented") -} - -func (m *MockEC2) ImportKeyPairWithContext(aws.Context, *ec2.ImportKeyPairInput, ...request.Option) (*ec2.ImportKeyPairOutput, error) { - panic("Not implemented") -} - -func (m *MockEC2) ImportKeyPair(request *ec2.ImportKeyPairInput) (*ec2.ImportKeyPairOutput, error) { +func (m *MockEC2) ImportKeyPair(ctx context.Context, request *ec2.ImportKeyPairInput, optFns ...func(*ec2.Options)) (*ec2.ImportKeyPairOutput, error) { m.mutex.Lock() defer m.mutex.Unlock() @@ -57,13 +42,13 @@ func (m *MockEC2) ImportKeyPair(request *ec2.ImportKeyPairInput) (*ec2.ImportKey n := len(m.KeyPairs) + 1 id := fmt.Sprintf("key-%d", n) - kp := &ec2.KeyPairInfo{ + kp := &ec2types.KeyPairInfo{ KeyFingerprint: aws.String(fp), KeyName: request.KeyName, KeyPairId: aws.String(id), } if m.KeyPairs == nil { - m.KeyPairs = make(map[string]*ec2.KeyPairInfo) + m.KeyPairs = make(map[string]*ec2types.KeyPairInfo) } m.KeyPairs[id] = kp response := &ec2.ImportKeyPairOutput{ @@ -71,30 +56,18 @@ func (m *MockEC2) ImportKeyPair(request *ec2.ImportKeyPairInput) (*ec2.ImportKey KeyName: kp.KeyName, } - m.addTags(id, tagSpecificationsToTags(request.TagSpecifications, ec2.ResourceTypeKeyPair)...) + m.addTags(id, tagSpecificationsToTags(request.TagSpecifications, ec2types.ResourceTypeKeyPair)...) return response, nil } -func (m *MockEC2) CreateKeyPairRequest(*ec2.CreateKeyPairInput) (*request.Request, *ec2.CreateKeyPairOutput) { - panic("MockEC2 CreateKeyPairRequest not implemented") -} - -func (m *MockEC2) CreateKeyPairWithContext(aws.Context, *ec2.CreateKeyPairInput, ...request.Option) (*ec2.CreateKeyPairOutput, error) { - panic("Not implemented") -} - -func (m *MockEC2) CreateKeyPair(*ec2.CreateKeyPairInput) (*ec2.CreateKeyPairOutput, error) { - panic("MockEC2 CreateKeyPair not implemented") -} - -func (m *MockEC2) DescribeKeyPairs(request *ec2.DescribeKeyPairsInput) (*ec2.DescribeKeyPairsOutput, error) { +func (m *MockEC2) DescribeKeyPairs(ctx context.Context, request *ec2.DescribeKeyPairsInput, optFns ...func(*ec2.Options)) (*ec2.DescribeKeyPairsOutput, error) { m.mutex.Lock() defer m.mutex.Unlock() klog.Infof("DescribeKeyPairs: %v", request) - var keypairs []*ec2.KeyPairInfo + var keypairs []ec2types.KeyPairInfo for _, keypair := range m.KeyPairs { allFiltersMatch := true @@ -102,7 +75,7 @@ func (m *MockEC2) DescribeKeyPairs(request *ec2.DescribeKeyPairsInput) (*ec2.Des if len(request.KeyNames) != 0 { match := false for _, keyname := range request.KeyNames { - if aws.StringValue(keyname) == aws.StringValue(keypair.KeyName) { + if keyname == aws.ToString(keypair.KeyName) { match = true } } @@ -117,7 +90,7 @@ func (m *MockEC2) DescribeKeyPairs(request *ec2.DescribeKeyPairsInput) (*ec2.Des case "key-name": for _, v := range filter.Values { - if aws.StringValue(keypair.KeyName) == aws.StringValue(v) { + if aws.ToString(keypair.KeyName) == v { match = true } } @@ -136,8 +109,8 @@ func (m *MockEC2) DescribeKeyPairs(request *ec2.DescribeKeyPairsInput) (*ec2.Des } copy := *keypair - copy.Tags = m.getTags(ec2.ResourceTypeKeyPair, *copy.KeyPairId) - keypairs = append(keypairs, ©) + copy.Tags = m.getTags(ec2types.ResourceTypeKeyPair, *copy.KeyPairId) + keypairs = append(keypairs, copy) } response := &ec2.DescribeKeyPairsOutput{ @@ -147,16 +120,16 @@ func (m *MockEC2) DescribeKeyPairs(request *ec2.DescribeKeyPairsInput) (*ec2.Des return response, nil } -func (m *MockEC2) DeleteKeyPair(request *ec2.DeleteKeyPairInput) (*ec2.DeleteKeyPairOutput, error) { +func (m *MockEC2) DeleteKeyPair(ctx context.Context, request *ec2.DeleteKeyPairInput, optFns ...func(*ec2.Options)) (*ec2.DeleteKeyPairOutput, error) { m.mutex.Lock() defer m.mutex.Unlock() klog.Infof("DeleteKeyPair: %v", request) - keyID := aws.StringValue(request.KeyPairId) + keyID := aws.ToString(request.KeyPairId) found := false for id, kp := range m.KeyPairs { - if aws.StringValue(kp.KeyPairId) == keyID { + if aws.ToString(kp.KeyPairId) == keyID { found = true delete(m.KeyPairs, id) } @@ -167,11 +140,3 @@ func (m *MockEC2) DeleteKeyPair(request *ec2.DeleteKeyPairInput) (*ec2.DeleteKey return &ec2.DeleteKeyPairOutput{}, nil } - -func (m *MockEC2) DeleteKeyPairWithContext(aws.Context, *ec2.DeleteKeyPairInput, ...request.Option) (*ec2.DeleteKeyPairOutput, error) { - panic("Not implemented") -} - -func (m *MockEC2) DeleteKeyPairRequest(*ec2.DeleteKeyPairInput) (*request.Request, *ec2.DeleteKeyPairOutput) { - panic("Not implemented") -} diff --git a/cloudmock/aws/mockec2/launch_templates.go b/cloudmock/aws/mockec2/launch_templates.go index 4a24c3e1ab..f09538dbb9 100644 --- a/cloudmock/aws/mockec2/launch_templates.go +++ b/cloudmock/aws/mockec2/launch_templates.go @@ -21,37 +21,20 @@ import ( "fmt" "strings" - "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/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "k8s.io/klog/v2" ) type launchTemplateInfo struct { - data *ec2.ResponseLaunchTemplateData + data *ec2types.ResponseLaunchTemplateData name *string version int } -// DescribeLaunchTemplatesPages mocks the describing the launch templates -func (m *MockEC2) DescribeLaunchTemplatesPages(request *ec2.DescribeLaunchTemplatesInput, callback func(*ec2.DescribeLaunchTemplatesOutput, bool) bool) error { - page, err := m.DescribeLaunchTemplates(request) - if err != nil { - return err - } - - callback(page, false) - - return nil -} - -// DescribeLaunchTemplatesPagesWithContext mocks the describing the launch templates -func (m *MockEC2) DescribeLaunchTemplatesPagesWithContext(ctx context.Context, request *ec2.DescribeLaunchTemplatesInput, callback func(*ec2.DescribeLaunchTemplatesOutput, bool) bool, option ...request.Option) error { - return m.DescribeLaunchTemplatesPages(request, callback) -} - // DescribeLaunchTemplates mocks the describing the launch templates -func (m *MockEC2) DescribeLaunchTemplates(request *ec2.DescribeLaunchTemplatesInput) (*ec2.DescribeLaunchTemplatesOutput, error) { +func (m *MockEC2) DescribeLaunchTemplates(ctx context.Context, request *ec2.DescribeLaunchTemplatesInput, optFns ...func(*ec2.Options)) (*ec2.DescribeLaunchTemplatesOutput, error) { m.mutex.Lock() defer m.mutex.Unlock() @@ -64,12 +47,12 @@ func (m *MockEC2) DescribeLaunchTemplates(request *ec2.DescribeLaunchTemplatesIn } for id, ltInfo := range m.LaunchTemplates { - launchTemplatetName := aws.StringValue(ltInfo.name) + launchTemplatetName := aws.ToString(ltInfo.name) allFiltersMatch := true for _, filter := range request.Filters { - filterName := aws.StringValue(filter.Name) - filterValue := aws.StringValue(filter.Values[0]) + filterName := aws.ToString(filter.Name) + filterValue := filter.Values[0] filterMatches := false if filterName == "tag:Name" && filterValue == launchTemplatetName { @@ -86,7 +69,7 @@ func (m *MockEC2) DescribeLaunchTemplates(request *ec2.DescribeLaunchTemplatesIn } if allFiltersMatch { - o.LaunchTemplates = append(o.LaunchTemplates, &ec2.LaunchTemplate{ + o.LaunchTemplates = append(o.LaunchTemplates, ec2types.LaunchTemplate{ LaunchTemplateName: aws.String(launchTemplatetName), LaunchTemplateId: aws.String(id), }) @@ -97,7 +80,7 @@ func (m *MockEC2) DescribeLaunchTemplates(request *ec2.DescribeLaunchTemplatesIn } // DescribeLaunchTemplateVersions mocks the retrieval of launch template versions - we don't use this at the moment so we can just return the template -func (m *MockEC2) DescribeLaunchTemplateVersions(request *ec2.DescribeLaunchTemplateVersionsInput) (*ec2.DescribeLaunchTemplateVersionsOutput, error) { +func (m *MockEC2) DescribeLaunchTemplateVersions(ctx context.Context, request *ec2.DescribeLaunchTemplateVersionsInput, optFns ...func(*ec2.Options)) (*ec2.DescribeLaunchTemplateVersionsOutput, error) { m.mutex.Lock() defer m.mutex.Unlock() @@ -110,10 +93,10 @@ func (m *MockEC2) DescribeLaunchTemplateVersions(request *ec2.DescribeLaunchTemp } for id, ltInfo := range m.LaunchTemplates { - if aws.StringValue(ltInfo.name) != aws.StringValue(request.LaunchTemplateName) { + if aws.ToString(ltInfo.name) != aws.ToString(request.LaunchTemplateName) { continue } - o.LaunchTemplateVersions = append(o.LaunchTemplateVersions, &ec2.LaunchTemplateVersion{ + o.LaunchTemplateVersions = append(o.LaunchTemplateVersions, ec2types.LaunchTemplateVersion{ DefaultVersion: aws.Bool(true), LaunchTemplateId: aws.String(id), LaunchTemplateData: ltInfo.data, @@ -123,13 +106,8 @@ func (m *MockEC2) DescribeLaunchTemplateVersions(request *ec2.DescribeLaunchTemp return o, nil } -// DescribeLaunchTemplateVersionsWithContext mocks the retrieval of launch template versions - we don't use this at the moment so we can just return the template -func (m *MockEC2) DescribeLaunchTemplateVersionsWithContext(ctx context.Context, request *ec2.DescribeLaunchTemplateVersionsInput, option ...request.Option) (*ec2.DescribeLaunchTemplateVersionsOutput, error) { - return m.DescribeLaunchTemplateVersions(request) -} - // CreateLaunchTemplate mocks the ec2 create launch template -func (m *MockEC2) CreateLaunchTemplate(request *ec2.CreateLaunchTemplateInput) (*ec2.CreateLaunchTemplateOutput, error) { +func (m *MockEC2) CreateLaunchTemplate(ctx context.Context, request *ec2.CreateLaunchTemplateInput, optFns ...func(*ec2.Options)) (*ec2.CreateLaunchTemplateOutput, error) { m.mutex.Lock() defer m.mutex.Unlock() @@ -150,16 +128,16 @@ func (m *MockEC2) CreateLaunchTemplate(request *ec2.CreateLaunchTemplateInput) ( name: request.LaunchTemplateName, version: 1, } - m.addTags(id, tagSpecificationsToTags(request.TagSpecifications, ec2.ResourceTypeLaunchTemplate)...) + m.addTags(id, tagSpecificationsToTags(request.TagSpecifications, ec2types.ResourceTypeLaunchTemplate)...) return &ec2.CreateLaunchTemplateOutput{ - LaunchTemplate: &ec2.LaunchTemplate{ + LaunchTemplate: &ec2types.LaunchTemplate{ LaunchTemplateId: aws.String(id), }, }, nil } -func (m *MockEC2) CreateLaunchTemplateVersion(request *ec2.CreateLaunchTemplateVersionInput) (*ec2.CreateLaunchTemplateVersionOutput, error) { +func (m *MockEC2) CreateLaunchTemplateVersion(ctx context.Context, request *ec2.CreateLaunchTemplateVersionInput, optFns ...func(*ec2.Options)) (*ec2.CreateLaunchTemplateVersionOutput, error) { m.mutex.Lock() defer m.mutex.Unlock() @@ -170,7 +148,7 @@ func (m *MockEC2) CreateLaunchTemplateVersion(request *ec2.CreateLaunchTemplateV var ltVersion int var ltID string for id, ltInfo := range m.LaunchTemplates { - if aws.StringValue(ltInfo.name) == aws.StringValue(name) { + if aws.ToString(ltInfo.name) == aws.ToString(name) { found = true ltInfo.data = responseLaunchTemplateData(request.LaunchTemplateData) ltInfo.version++ @@ -182,7 +160,7 @@ func (m *MockEC2) CreateLaunchTemplateVersion(request *ec2.CreateLaunchTemplateV return nil, nil // TODO: error } return &ec2.CreateLaunchTemplateVersionOutput{ - LaunchTemplateVersion: &ec2.LaunchTemplateVersion{ + LaunchTemplateVersion: &ec2types.LaunchTemplateVersion{ VersionNumber: aws.Int64(int64(ltVersion)), LaunchTemplateId: <ID, }, @@ -190,7 +168,7 @@ func (m *MockEC2) CreateLaunchTemplateVersion(request *ec2.CreateLaunchTemplateV } // DeleteLaunchTemplate mocks the deletion of a launch template -func (m *MockEC2) DeleteLaunchTemplate(request *ec2.DeleteLaunchTemplateInput) (*ec2.DeleteLaunchTemplateOutput, error) { +func (m *MockEC2) DeleteLaunchTemplate(ctx context.Context, request *ec2.DeleteLaunchTemplateInput, optFns ...func(*ec2.Options)) (*ec2.DeleteLaunchTemplateOutput, error) { m.mutex.Lock() defer m.mutex.Unlock() @@ -202,7 +180,7 @@ func (m *MockEC2) DeleteLaunchTemplate(request *ec2.DeleteLaunchTemplateInput) ( return o, nil } for id := range m.LaunchTemplates { - if id == aws.StringValue(request.LaunchTemplateId) { + if id == aws.ToString(request.LaunchTemplateId) { delete(m.LaunchTemplates, id) } } @@ -210,12 +188,12 @@ func (m *MockEC2) DeleteLaunchTemplate(request *ec2.DeleteLaunchTemplateInput) ( return o, nil } -func (m *MockEC2) ModifyLaunchTemplate(*ec2.ModifyLaunchTemplateInput) (*ec2.ModifyLaunchTemplateOutput, error) { +func (m *MockEC2) ModifyLaunchTemplate(ctx context.Context, request *ec2.ModifyLaunchTemplateInput, optFns ...func(*ec2.Options)) (*ec2.ModifyLaunchTemplateOutput, error) { return &ec2.ModifyLaunchTemplateOutput{}, nil } -func responseLaunchTemplateData(req *ec2.RequestLaunchTemplateData) *ec2.ResponseLaunchTemplateData { - resp := &ec2.ResponseLaunchTemplateData{ +func responseLaunchTemplateData(req *ec2types.RequestLaunchTemplateData) *ec2types.ResponseLaunchTemplateData { + resp := &ec2types.ResponseLaunchTemplateData{ DisableApiTermination: req.DisableApiTermination, EbsOptimized: req.EbsOptimized, ImageId: req.ImageId, @@ -227,26 +205,26 @@ func responseLaunchTemplateData(req *ec2.RequestLaunchTemplateData) *ec2.Respons } if req.MetadataOptions != nil { - resp.MetadataOptions = &ec2.LaunchTemplateInstanceMetadataOptions{ + resp.MetadataOptions = &ec2types.LaunchTemplateInstanceMetadataOptions{ HttpTokens: req.MetadataOptions.HttpTokens, HttpPutResponseHopLimit: req.MetadataOptions.HttpPutResponseHopLimit, HttpProtocolIpv6: req.MetadataOptions.HttpProtocolIpv6, } } if req.Monitoring != nil { - resp.Monitoring = &ec2.LaunchTemplatesMonitoring{Enabled: req.Monitoring.Enabled} + resp.Monitoring = &ec2types.LaunchTemplatesMonitoring{Enabled: req.Monitoring.Enabled} } if req.CpuOptions != nil { - resp.CpuOptions = &ec2.LaunchTemplateCpuOptions{ + resp.CpuOptions = &ec2types.LaunchTemplateCpuOptions{ CoreCount: req.CpuOptions.CoreCount, ThreadsPerCore: req.CpuOptions.ThreadsPerCore, } } if len(req.BlockDeviceMappings) > 0 { for _, x := range req.BlockDeviceMappings { - var ebs *ec2.LaunchTemplateEbsBlockDevice + var ebs *ec2types.LaunchTemplateEbsBlockDevice if x.Ebs != nil { - ebs = &ec2.LaunchTemplateEbsBlockDevice{ + ebs = &ec2types.LaunchTemplateEbsBlockDevice{ DeleteOnTermination: x.Ebs.DeleteOnTermination, Encrypted: x.Ebs.Encrypted, Iops: x.Ebs.Iops, @@ -257,7 +235,7 @@ func responseLaunchTemplateData(req *ec2.RequestLaunchTemplateData) *ec2.Respons VolumeType: x.Ebs.VolumeType, } } - resp.BlockDeviceMappings = append(resp.BlockDeviceMappings, &ec2.LaunchTemplateBlockDeviceMapping{ + resp.BlockDeviceMappings = append(resp.BlockDeviceMappings, ec2types.LaunchTemplateBlockDeviceMapping{ DeviceName: x.DeviceName, Ebs: ebs, NoDevice: x.NoDevice, @@ -266,18 +244,18 @@ func responseLaunchTemplateData(req *ec2.RequestLaunchTemplateData) *ec2.Respons } } if req.CreditSpecification != nil { - resp.CreditSpecification = &ec2.CreditSpecification{CpuCredits: req.CreditSpecification.CpuCredits} + resp.CreditSpecification = &ec2types.CreditSpecification{CpuCredits: req.CreditSpecification.CpuCredits} } if req.IamInstanceProfile != nil { - resp.IamInstanceProfile = &ec2.LaunchTemplateIamInstanceProfileSpecification{ + resp.IamInstanceProfile = &ec2types.LaunchTemplateIamInstanceProfileSpecification{ Arn: req.IamInstanceProfile.Arn, Name: req.IamInstanceProfile.Name, } } if req.InstanceMarketOptions != nil { - resp.InstanceMarketOptions = &ec2.LaunchTemplateInstanceMarketOptions{ + resp.InstanceMarketOptions = &ec2types.LaunchTemplateInstanceMarketOptions{ MarketType: req.InstanceMarketOptions.MarketType, - SpotOptions: &ec2.LaunchTemplateSpotMarketOptions{ + SpotOptions: &ec2types.LaunchTemplateSpotMarketOptions{ BlockDurationMinutes: req.InstanceMarketOptions.SpotOptions.BlockDurationMinutes, InstanceInterruptionBehavior: req.InstanceMarketOptions.SpotOptions.InstanceInterruptionBehavior, MaxPrice: req.InstanceMarketOptions.SpotOptions.MaxPrice, @@ -288,7 +266,7 @@ func responseLaunchTemplateData(req *ec2.RequestLaunchTemplateData) *ec2.Respons } if len(req.NetworkInterfaces) > 0 { for _, x := range req.NetworkInterfaces { - resp.NetworkInterfaces = append(resp.NetworkInterfaces, &ec2.LaunchTemplateInstanceNetworkInterfaceSpecification{ + resp.NetworkInterfaces = append(resp.NetworkInterfaces, ec2types.LaunchTemplateInstanceNetworkInterfaceSpecification{ AssociatePublicIpAddress: x.AssociatePublicIpAddress, DeleteOnTermination: x.DeleteOnTermination, Description: x.Description, @@ -305,7 +283,7 @@ func responseLaunchTemplateData(req *ec2.RequestLaunchTemplateData) *ec2.Respons } if len(req.TagSpecifications) > 0 { for _, x := range req.TagSpecifications { - resp.TagSpecifications = append(resp.TagSpecifications, &ec2.LaunchTemplateTagSpecification{ + resp.TagSpecifications = append(resp.TagSpecifications, ec2types.LaunchTemplateTagSpecification{ ResourceType: x.ResourceType, Tags: x.Tags, }) diff --git a/cloudmock/aws/mockec2/tags.go b/cloudmock/aws/mockec2/tags.go index 5bcf146b45..de646a9778 100644 --- a/cloudmock/aws/mockec2/tags.go +++ b/cloudmock/aws/mockec2/tags.go @@ -17,87 +17,71 @@ limitations under the License. package mockec2 import ( + "context" "fmt" "sort" "strings" - "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/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "k8s.io/klog/v2" ) -func (m *MockEC2) CreateTagsRequest(*ec2.CreateTagsInput) (*request.Request, *ec2.CreateTagsOutput) { - panic("Not implemented") -} - -func (m *MockEC2) CreateTagsWithContext(aws.Context, *ec2.CreateTagsInput, ...request.Option) (*ec2.CreateTagsOutput, error) { - panic("Not implemented") -} - -func (m *MockEC2) CreateTags(request *ec2.CreateTagsInput) (*ec2.CreateTagsOutput, error) { +func (m *MockEC2) CreateTags(ctx context.Context, request *ec2.CreateTagsInput, optFns ...func(*ec2.Options)) (*ec2.CreateTagsOutput, error) { m.mutex.Lock() defer m.mutex.Unlock() klog.Infof("CreateTags %v", request) for _, v := range request.Resources { - resourceId := *v - m.addTags(resourceId, request.Tags...) + m.addTags(v, request.Tags...) } response := &ec2.CreateTagsOutput{} return response, nil } -func (m *MockEC2) addTags(resourceId string, tags ...*ec2.Tag) { - resourceType := "" +func (m *MockEC2) addTags(resourceId string, tags ...ec2types.Tag) { + var resourceType ec2types.ResourceType if strings.HasPrefix(resourceId, "subnet-") { - resourceType = ec2.ResourceTypeSubnet + resourceType = ec2types.ResourceTypeSubnet } else if strings.HasPrefix(resourceId, "vpc-") { - resourceType = ec2.ResourceTypeVpc + resourceType = ec2types.ResourceTypeVpc } else if strings.HasPrefix(resourceId, "sg-") { - resourceType = ec2.ResourceTypeSecurityGroup + resourceType = ec2types.ResourceTypeSecurityGroup } else if strings.HasPrefix(resourceId, "vol-") { - resourceType = ec2.ResourceTypeVolume + resourceType = ec2types.ResourceTypeVolume } else if strings.HasPrefix(resourceId, "igw-") { - resourceType = ec2.ResourceTypeInternetGateway + resourceType = ec2types.ResourceTypeInternetGateway } else if strings.HasPrefix(resourceId, "eigw-") { - resourceType = ec2.ResourceTypeEgressOnlyInternetGateway + resourceType = ec2types.ResourceTypeEgressOnlyInternetGateway } else if strings.HasPrefix(resourceId, "nat-") { - resourceType = ec2.ResourceTypeNatgateway + resourceType = ec2types.ResourceTypeNatgateway } else if strings.HasPrefix(resourceId, "dopt-") { - resourceType = ec2.ResourceTypeDhcpOptions + resourceType = ec2types.ResourceTypeDhcpOptions } else if strings.HasPrefix(resourceId, "rtb-") { - resourceType = ec2.ResourceTypeRouteTable + resourceType = ec2types.ResourceTypeRouteTable } else if strings.HasPrefix(resourceId, "eipalloc-") { - resourceType = ec2.ResourceTypeElasticIp + resourceType = ec2types.ResourceTypeElasticIp } else if strings.HasPrefix(resourceId, "lt-") { - resourceType = ec2.ResourceTypeLaunchTemplate + resourceType = ec2types.ResourceTypeLaunchTemplate } else if strings.HasPrefix(resourceId, "key-") { - resourceType = ec2.ResourceTypeKeyPair + resourceType = ec2types.ResourceTypeKeyPair } else { klog.Fatalf("Unknown resource-type in create tags: %v", resourceId) } for _, tag := range tags { - t := &ec2.TagDescription{ + t := &ec2types.TagDescription{ Key: tag.Key, Value: tag.Value, ResourceId: s(resourceId), - ResourceType: s(resourceType), + ResourceType: resourceType, } m.Tags = append(m.Tags, t) } } -func (m *MockEC2) DescribeTagsRequest(*ec2.DescribeTagsInput) (*request.Request, *ec2.DescribeTagsOutput) { - panic("Not implemented") -} - -func (m *MockEC2) DescribeTagsWithContext(aws.Context, *ec2.DescribeTagsInput, ...request.Option) (*ec2.DescribeTagsOutput, error) { - panic("Not implemented") -} - -func (m *MockEC2) hasTag(resourceType string, resourceId string, filter *ec2.Filter) bool { +func (m *MockEC2) hasTag(resourceType ec2types.ResourceType, resourceId string, filter ec2types.Filter) bool { name := *filter.Name if strings.HasPrefix(name, "tag:") { tagKey := name[4:] @@ -106,7 +90,7 @@ func (m *MockEC2) hasTag(resourceType string, resourceId string, filter *ec2.Fil if *tag.ResourceId != resourceId { continue } - if *tag.ResourceType != resourceType { + if tag.ResourceType != resourceType { continue } if *tag.Key != tagKey { @@ -114,7 +98,7 @@ func (m *MockEC2) hasTag(resourceType string, resourceId string, filter *ec2.Fil } for _, v := range filter.Values { - if *tag.Value == *v { + if *tag.Value == v { return true } } @@ -124,11 +108,11 @@ func (m *MockEC2) hasTag(resourceType string, resourceId string, filter *ec2.Fil if *tag.ResourceId != resourceId { continue } - if *tag.ResourceType != resourceType { + if tag.ResourceType != resourceType { continue } for _, v := range filter.Values { - if *tag.Key == *v { + if *tag.Key == v { return true } } @@ -139,17 +123,17 @@ func (m *MockEC2) hasTag(resourceType string, resourceId string, filter *ec2.Fil return false } -func (m *MockEC2) getTags(resourceType string, resourceId string) []*ec2.Tag { - var tags []*ec2.Tag +func (m *MockEC2) getTags(resourceType ec2types.ResourceType, resourceId string) []ec2types.Tag { + var tags []ec2types.Tag for _, tag := range m.Tags { if *tag.ResourceId != resourceId { continue } - if *tag.ResourceType != resourceType { + if tag.ResourceType != resourceType { continue } - t := &ec2.Tag{ + t := ec2types.Tag{ Key: tag.Key, Value: tag.Value, } @@ -158,13 +142,13 @@ func (m *MockEC2) getTags(resourceType string, resourceId string) []*ec2.Tag { return tags } -func (m *MockEC2) DescribeTags(request *ec2.DescribeTagsInput) (*ec2.DescribeTagsOutput, error) { +func (m *MockEC2) DescribeTags(ctx context.Context, request *ec2.DescribeTagsInput, optFns ...func(*ec2.Options)) (*ec2.DescribeTagsOutput, error) { m.mutex.Lock() defer m.mutex.Unlock() klog.Infof("DescribeTags %v", request) - var tags []*ec2.TagDescription + var tags []ec2types.TagDescription for _, tag := range m.Tags { allFiltersMatch := true @@ -173,14 +157,14 @@ func (m *MockEC2) DescribeTags(request *ec2.DescribeTagsInput) (*ec2.DescribeTag switch *filter.Name { case "key": for _, v := range filter.Values { - if *v == *tag.Key { + if v == *tag.Key { match = true } } case "resource-id": for _, v := range filter.Values { - if *v == *tag.ResourceId { + if v == *tag.ResourceId { match = true } } @@ -200,7 +184,7 @@ func (m *MockEC2) DescribeTags(request *ec2.DescribeTagsInput) (*ec2.DescribeTag } copy := *tag - tags = append(tags, ©) + tags = append(tags, copy) } response := &ec2.DescribeTagsOutput{ @@ -210,29 +194,19 @@ func (m *MockEC2) DescribeTags(request *ec2.DescribeTagsInput) (*ec2.DescribeTag return response, nil } -func (m *MockEC2) DescribeTagsPages(*ec2.DescribeTagsInput, func(*ec2.DescribeTagsOutput, bool) bool) error { - panic("Not implemented") -} - -func (m *MockEC2) DescribeTagsPagesWithContext(aws.Context, *ec2.DescribeTagsInput, func(*ec2.DescribeTagsOutput, bool) bool, ...request.Option) error { - panic("Not implemented") -} - // SortTags sorts the slice of tags by Key -func SortTags(tags []*ec2.Tag) { +func SortTags(tags []ec2types.Tag) { keys := make([]string, len(tags)) for i := range tags { - if tags[i] != nil { - keys[i] = aws.StringValue(tags[i].Key) - } + keys[i] = aws.ToString(tags[i].Key) } sort.SliceStable(tags, func(i, j int) bool { return keys[i] < keys[j] }) } -func tagSpecificationsToTags(specifications []*ec2.TagSpecification, resourceType string) []*ec2.Tag { - tags := make([]*ec2.Tag, 0) +func tagSpecificationsToTags(specifications []ec2types.TagSpecification, resourceType ec2types.ResourceType) []ec2types.Tag { + tags := make([]ec2types.Tag, 0) for _, specification := range specifications { - if aws.StringValue(specification.ResourceType) != resourceType { + if specification.ResourceType != resourceType { continue } tags = append(tags, specification.Tags...) diff --git a/cloudmock/aws/mockec2/volumes.go b/cloudmock/aws/mockec2/volumes.go index fccfa7b56c..6e5323aea1 100644 --- a/cloudmock/aws/mockec2/volumes.go +++ b/cloudmock/aws/mockec2/volumes.go @@ -17,16 +17,17 @@ limitations under the License. package mockec2 import ( + "context" "fmt" "strings" - "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/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "k8s.io/klog/v2" ) -func (m *MockEC2) CreateVolume(request *ec2.CreateVolumeInput) (*ec2.Volume, error) { +func (m *MockEC2) CreateVolume(ctx context.Context, request *ec2.CreateVolumeInput, optFns ...func(*ec2.Options)) (*ec2.CreateVolumeOutput, error) { m.mutex.Lock() defer m.mutex.Unlock() @@ -39,7 +40,7 @@ func (m *MockEC2) CreateVolume(request *ec2.CreateVolumeInput) (*ec2.Volume, err n := len(m.Volumes) + 1 id := fmt.Sprintf("vol-%d", n) - volume := &ec2.Volume{ + volume := &ec2types.Volume{ VolumeId: s(id), AvailabilityZone: request.AvailabilityZone, Encrypted: request.Encrypted, @@ -52,14 +53,14 @@ func (m *MockEC2) CreateVolume(request *ec2.CreateVolumeInput) (*ec2.Volume, err } if m.Volumes == nil { - m.Volumes = make(map[string]*ec2.Volume) + m.Volumes = make(map[string]*ec2types.Volume) } m.Volumes[*volume.VolumeId] = volume - m.addTags(id, tagSpecificationsToTags(request.TagSpecifications, ec2.ResourceTypeVolume)...) + m.addTags(id, tagSpecificationsToTags(request.TagSpecifications, ec2types.ResourceTypeVolume)...) copy := *volume - copy.Tags = m.getTags(ec2.ResourceTypeVolume, *volume.VolumeId) + copy.Tags = m.getTags(ec2types.ResourceTypeVolume, *volume.VolumeId) // TODO: a few fields // // Information about the volume attachments. // Attachments []*VolumeAttachment `locationName:"attachmentSet" locationNameList:"item" type:"list"` @@ -70,58 +71,12 @@ func (m *MockEC2) CreateVolume(request *ec2.CreateVolumeInput) (*ec2.Volume, err // // The volume state. // State *string `locationName:"status" type:"string" enum:"VolumeState"` - return ©, nil + return &ec2.CreateVolumeOutput{ + VolumeId: copy.VolumeId, + }, nil } -func (m *MockEC2) CreateVolumeWithContext(aws.Context, *ec2.CreateVolumeInput, ...request.Option) (*ec2.Volume, error) { - panic("Not implemented") -} - -func (m *MockEC2) CreateVolumeRequest(*ec2.CreateVolumeInput) (*request.Request, *ec2.Volume) { - panic("Not implemented") -} - -func (m *MockEC2) DescribeVolumeAttributeRequest(*ec2.DescribeVolumeAttributeInput) (*request.Request, *ec2.DescribeVolumeAttributeOutput) { - panic("MockEC2 DescribeVolumeAttributeRequest not implemented") -} - -func (m *MockEC2) DescribeVolumeAttributeWithContext(aws.Context, *ec2.DescribeVolumeAttributeInput, ...request.Option) (*ec2.DescribeVolumeAttributeOutput, error) { - panic("Not implemented") -} - -func (m *MockEC2) DescribeVolumeAttribute(*ec2.DescribeVolumeAttributeInput) (*ec2.DescribeVolumeAttributeOutput, error) { - panic("MockEC2 DescribeVolumeAttribute not implemented") -} - -func (m *MockEC2) DescribeVolumeStatusRequest(*ec2.DescribeVolumeStatusInput) (*request.Request, *ec2.DescribeVolumeStatusOutput) { - panic("MockEC2 DescribeVolumeStatusRequest not implemented") -} - -func (m *MockEC2) DescribeVolumeStatusWithContext(aws.Context, *ec2.DescribeVolumeStatusInput, ...request.Option) (*ec2.DescribeVolumeStatusOutput, error) { - panic("Not implemented") -} - -func (m *MockEC2) DescribeVolumeStatus(*ec2.DescribeVolumeStatusInput) (*ec2.DescribeVolumeStatusOutput, error) { - panic("MockEC2 DescribeVolumeStatus not implemented") -} - -func (m *MockEC2) DescribeVolumeStatusPages(*ec2.DescribeVolumeStatusInput, func(*ec2.DescribeVolumeStatusOutput, bool) bool) error { - panic("MockEC2 DescribeVolumeStatusPages not implemented") -} - -func (m *MockEC2) DescribeVolumeStatusPagesWithContext(aws.Context, *ec2.DescribeVolumeStatusInput, func(*ec2.DescribeVolumeStatusOutput, bool) bool, ...request.Option) error { - panic("Not implemented") -} - -func (m *MockEC2) DescribeVolumesRequest(*ec2.DescribeVolumesInput) (*request.Request, *ec2.DescribeVolumesOutput) { - panic("MockEC2 DescribeVolumesRequest not implemented") -} - -func (m *MockEC2) DescribeVolumesWithContext(aws.Context, *ec2.DescribeVolumesInput, ...request.Option) (*ec2.DescribeVolumesOutput, error) { - panic("Not implemented") -} - -func (m *MockEC2) DescribeVolumes(request *ec2.DescribeVolumesInput) (*ec2.DescribeVolumesOutput, error) { +func (m *MockEC2) DescribeVolumes(ctx context.Context, request *ec2.DescribeVolumesInput, optFns ...func(*ec2.Options)) (*ec2.DescribeVolumesOutput, error) { m.mutex.Lock() defer m.mutex.Unlock() @@ -131,7 +86,7 @@ func (m *MockEC2) DescribeVolumes(request *ec2.DescribeVolumesInput) (*ec2.Descr klog.Fatalf("VolumeIds") } - var volumes []*ec2.Volume + var volumes []ec2types.Volume for _, volume := range m.Volumes { allFiltersMatch := true @@ -140,7 +95,7 @@ func (m *MockEC2) DescribeVolumes(request *ec2.DescribeVolumesInput) (*ec2.Descr switch *filter.Name { default: if strings.HasPrefix(*filter.Name, "tag:") { - match = m.hasTag(ec2.ResourceTypeVolume, *volume.VolumeId, filter) + match = m.hasTag(ec2types.ResourceTypeVolume, *volume.VolumeId, filter) } else { return nil, fmt.Errorf("unknown filter name: %q", *filter.Name) } @@ -157,8 +112,8 @@ func (m *MockEC2) DescribeVolumes(request *ec2.DescribeVolumesInput) (*ec2.Descr } copy := *volume - copy.Tags = m.getTags(ec2.ResourceTypeVolume, *volume.VolumeId) - volumes = append(volumes, ©) + copy.Tags = m.getTags(ec2types.ResourceTypeVolume, *volume.VolumeId) + volumes = append(volumes, copy) } response := &ec2.DescribeVolumesOutput{ @@ -168,41 +123,13 @@ func (m *MockEC2) DescribeVolumes(request *ec2.DescribeVolumesInput) (*ec2.Descr return response, nil } -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") -} - -func (m *MockEC2) DescribeVolumesModifications(*ec2.DescribeVolumesModificationsInput) (*ec2.DescribeVolumesModificationsOutput, error) { - panic("Not implemented") -} - -func (m *MockEC2) DescribeVolumesModificationsWithContext(aws.Context, *ec2.DescribeVolumesModificationsInput, ...request.Option) (*ec2.DescribeVolumesModificationsOutput, error) { - panic("Not implemented") -} - -func (m *MockEC2) DescribeVolumesModificationsRequest(*ec2.DescribeVolumesModificationsInput) (*request.Request, *ec2.DescribeVolumesModificationsOutput) { - panic("Not implemented") -} - -func (m *MockEC2) DeleteVolume(request *ec2.DeleteVolumeInput) (*ec2.DeleteVolumeOutput, error) { +func (m *MockEC2) DeleteVolume(ctx context.Context, request *ec2.DeleteVolumeInput, optFns ...func(*ec2.Options)) (*ec2.DeleteVolumeOutput, error) { m.mutex.Lock() defer m.mutex.Unlock() klog.Infof("DeleteVolume: %v", request) - id := aws.StringValue(request.VolumeId) + id := aws.ToString(request.VolumeId) o := m.Volumes[id] if o == nil { return nil, fmt.Errorf("Volume %q not found", id) @@ -211,11 +138,3 @@ func (m *MockEC2) DeleteVolume(request *ec2.DeleteVolumeInput) (*ec2.DeleteVolum return &ec2.DeleteVolumeOutput{}, nil } - -func (m *MockEC2) DeleteVolumeWithContext(aws.Context, *ec2.DeleteVolumeInput, ...request.Option) (*ec2.DeleteVolumeOutput, error) { - panic("Not implemented") -} - -func (m *MockEC2) DeleteVolumeRequest(*ec2.DeleteVolumeInput) (*request.Request, *ec2.DeleteVolumeOutput) { - panic("Not implemented") -} diff --git a/pkg/apis/kops/validation/aws.go b/pkg/apis/kops/validation/aws.go index 7448776ce9..1a9cfdf520 100644 --- a/pkg/apis/kops/validation/aws.go +++ b/pkg/apis/kops/validation/aws.go @@ -23,7 +23,8 @@ import ( "strings" "github.com/aws/aws-sdk-go-v2/aws/arn" - "github.com/aws/aws-sdk-go/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation/field" @@ -186,7 +187,7 @@ func awsValidateInstanceTypeAndImage(instanceTypeFieldPath *field.Path, imageFie return append(allErrs, field.Invalid(imageFieldPath, image, fmt.Sprintf("specified image %q is invalid: %s", image, err))) } - imageArch := fi.ValueOf(imageInfo.Architecture) + imageArch := string(imageInfo.Architecture) // Spotinst uses the instance type field to keep a "," separated list of instance types for _, instanceType := range strings.Split(instanceTypes, ",") { @@ -199,15 +200,17 @@ func awsValidateInstanceTypeAndImage(instanceTypeFieldPath *field.Path, imageFie found := false if machineInfo != nil && machineInfo.ProcessorInfo != nil { for _, machineArch := range machineInfo.ProcessorInfo.SupportedArchitectures { - if imageArch == fi.ValueOf(machineArch) { + if imageArch == string(machineArch) { found = true } } } if !found { - var machineArch []string + machineArch := make([]string, 0) if machineInfo != nil && machineInfo.ProcessorInfo != nil && machineInfo.ProcessorInfo.SupportedArchitectures != nil { - machineArch = fi.StringSliceValue(machineInfo.ProcessorInfo.SupportedArchitectures) + for _, arch := range machineInfo.ProcessorInfo.SupportedArchitectures { + machineArch = append(machineArch, string(arch)) + } } allErrs = append(allErrs, field.Invalid(instanceTypeFieldPath, instanceTypes, fmt.Sprintf("machine type architecture %q does not match image architecture %q", strings.Join(machineArch, ","), imageArch))) @@ -230,8 +233,8 @@ func awsValidateSpotDurationInMinute(fieldPath *field.Path, ig *kops.InstanceGro func awsValidateInstanceInterruptionBehavior(fieldPath *field.Path, ig *kops.InstanceGroup) field.ErrorList { allErrs := field.ErrorList{} if ig.Spec.InstanceInterruptionBehavior != nil { - instanceInterruptionBehavior := *ig.Spec.InstanceInterruptionBehavior - allErrs = append(allErrs, IsValidValue(fieldPath, &instanceInterruptionBehavior, ec2.InstanceInterruptionBehavior_Values())...) + instanceInterruptionBehavior := ec2types.InstanceInterruptionBehavior(*ig.Spec.InstanceInterruptionBehavior) + allErrs = append(allErrs, IsValidValue(fieldPath, &instanceInterruptionBehavior, ec2types.InstanceInterruptionBehavior("").Values())...) } return allErrs } @@ -240,7 +243,7 @@ func awsValidateInstanceInterruptionBehavior(fieldPath *field.Path, ig *kops.Ins func awsValidateMixedInstancesPolicy(path *field.Path, spec *kops.MixedInstancesPolicySpec, ig *kops.InstanceGroup, cloud awsup.AWSCloud) field.ErrorList { var errs field.ErrorList - mainMachineTypeInfo, err := awsup.GetMachineTypeInfo(cloud, ig.Spec.MachineType) + mainMachineTypeInfo, err := awsup.GetMachineTypeInfo(cloud, ec2types.InstanceType(ig.Spec.MachineType)) if err != nil { errs = append(errs, field.Invalid(field.NewPath("spec", "machineType"), ig.Spec.MachineType, fmt.Sprintf("machine type specified is invalid: %q", ig.Spec.MachineType))) return errs @@ -254,7 +257,7 @@ func awsValidateMixedInstancesPolicy(path *field.Path, spec *kops.MixedInstances errs = append(errs, awsValidateInstanceTypeAndImage(path.Child("instances").Index(i), path.Child("image"), instanceTypes, ig.Spec.Image, cloud)...) for _, instanceType := range strings.Split(instanceTypes, ",") { - machineTypeInfo, err := awsup.GetMachineTypeInfo(cloud, instanceType) + machineTypeInfo, err := awsup.GetMachineTypeInfo(cloud, ec2types.InstanceType(instanceType)) if err != nil { errs = append(errs, field.Invalid(field.NewPath("spec", "machineType"), ig.Spec.MachineType, fmt.Sprintf("machine type specified is invalid: %q", ig.Spec.MachineType))) return errs diff --git a/pkg/apis/kops/validation/aws_test.go b/pkg/apis/kops/validation/aws_test.go index 9d71055542..0ebb749b2e 100644 --- a/pkg/apis/kops/validation/aws_test.go +++ b/pkg/apis/kops/validation/aws_test.go @@ -21,7 +21,7 @@ import ( "time" "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/kops/cloudmock/aws/mockec2" @@ -238,13 +238,13 @@ func TestValidateInstanceGroupSpec(t *testing.T) { mockEC2 := &mockec2.MockEC2{} cloud.MockEC2 = mockEC2 - mockEC2.Images = append(mockEC2.Images, &ec2.Image{ + mockEC2.Images = append(mockEC2.Images, &ec2types.Image{ CreationDate: aws.String("2016-10-21T20:07:19.000Z"), ImageId: aws.String("ami-073c8c0760395aab8"), Name: aws.String("focal"), OwnerId: aws.String(awsup.WellKnownAccountUbuntu), RootDeviceName: aws.String("/dev/xvda"), - Architecture: aws.String("x86_64"), + Architecture: ec2types.ArchitectureValuesX8664, }) for _, g := range grid { @@ -339,13 +339,13 @@ func TestMixedInstancePolicies(t *testing.T) { mockEC2 := &mockec2.MockEC2{} cloud.MockEC2 = mockEC2 - mockEC2.Images = append(mockEC2.Images, &ec2.Image{ + mockEC2.Images = append(mockEC2.Images, &ec2types.Image{ CreationDate: aws.String("2016-10-21T20:07:19.000Z"), ImageId: aws.String("ami-073c8c0760395aab8"), Name: aws.String("focal"), OwnerId: aws.String(awsup.WellKnownAccountUbuntu), RootDeviceName: aws.String("/dev/xvda"), - Architecture: aws.String("x86_64"), + Architecture: ec2types.ArchitectureValuesX8664, }) for _, g := range grid { @@ -367,13 +367,13 @@ func TestInstanceMetadataOptions(t *testing.T) { mockEC2 := &mockec2.MockEC2{} cloud.MockEC2 = mockEC2 - mockEC2.Images = append(mockEC2.Images, &ec2.Image{ + mockEC2.Images = append(mockEC2.Images, &ec2types.Image{ CreationDate: aws.String("2016-10-21T20:07:19.000Z"), ImageId: aws.String("ami-073c8c0760395aab8"), Name: aws.String("focal"), OwnerId: aws.String(awsup.WellKnownAccountUbuntu), RootDeviceName: aws.String("/dev/xvda"), - Architecture: aws.String("x86_64"), + Architecture: ec2types.ArchitectureValuesX8664, }) tests := []struct { diff --git a/pkg/apis/kops/validation/instancegroup.go b/pkg/apis/kops/validation/instancegroup.go index aa22074948..0e3b4534a0 100644 --- a/pkg/apis/kops/validation/instancegroup.go +++ b/pkg/apis/kops/validation/instancegroup.go @@ -23,7 +23,7 @@ import ( "k8s.io/kops/pkg/nodeidentity/aws" "github.com/aws/aws-sdk-go-v2/aws/arn" - "github.com/aws/aws-sdk-go/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation/field" @@ -67,7 +67,8 @@ func ValidateInstanceGroup(g *kops.InstanceGroup, cloud fi.Cloud, strict bool) f } if g.Spec.Tenancy != "" { - allErrs = append(allErrs, IsValidValue(field.NewPath("spec", "tenancy"), &g.Spec.Tenancy, ec2.Tenancy_Values())...) + tenancy := ec2types.Tenancy(g.Spec.Tenancy) + allErrs = append(allErrs, IsValidValue(field.NewPath("spec", "tenancy"), &tenancy, ec2types.Tenancy("").Values())...) } if strict && g.Spec.Manager == kops.InstanceManagerCloudGroup { diff --git a/pkg/apis/kops/validation/validation.go b/pkg/apis/kops/validation/validation.go index 99c7188985..593ac88854 100644 --- a/pkg/apis/kops/validation/validation.go +++ b/pkg/apis/kops/validation/validation.go @@ -25,7 +25,7 @@ import ( "regexp" "strings" - "github.com/aws/aws-sdk-go/aws/arn" + "github.com/aws/aws-sdk-go-v2/aws/arn" "github.com/blang/semver/v4" "golang.org/x/net/ipv4" "golang.org/x/net/ipv6" diff --git a/pkg/model/awsmodel/autoscalinggroup.go b/pkg/model/awsmodel/autoscalinggroup.go index aa33229b45..1a37ddd30c 100644 --- a/pkg/model/awsmodel/autoscalinggroup.go +++ b/pkg/model/awsmodel/autoscalinggroup.go @@ -22,7 +22,7 @@ import ( "strings" "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "k8s.io/apimachinery/pkg/api/resource" "k8s.io/klog/v2" @@ -37,7 +37,7 @@ import ( const ( // DefaultVolumeType is the default volume type - DefaultVolumeType = ec2.VolumeTypeGp3 + DefaultVolumeType = ec2types.VolumeTypeGp3 // DefaultVolumeIonIops is the default volume IOPS when volume type is io1 or io2 DefaultVolumeIonIops = 100 // DefaultVolumeGp3Iops is the default volume IOPS when volume type is gp3 @@ -147,7 +147,7 @@ func (b *AutoscalingGroupModelBuilder) buildLaunchTemplateTask(c *fi.CloudupMode if err != nil { return nil, err } - var rootVolumeType string + var rootVolumeType ec2types.VolumeType rootVolumeEncryption := DefaultVolumeEncryption rootVolumeKmsKey := "" @@ -156,7 +156,7 @@ func (b *AutoscalingGroupModelBuilder) buildLaunchTemplateTask(c *fi.CloudupMode rootVolumeSize = fi.ValueOf(ig.Spec.RootVolume.Size) } - rootVolumeType = fi.ValueOf(ig.Spec.RootVolume.Type) + rootVolumeType = ec2types.VolumeType(fi.ValueOf(ig.Spec.RootVolume.Type)) if ig.Spec.RootVolume.Encryption != nil { rootVolumeEncryption = fi.ValueOf(ig.Spec.RootVolume.Encryption) @@ -186,33 +186,37 @@ func (b *AutoscalingGroupModelBuilder) buildLaunchTemplateTask(c *fi.CloudupMode } lt := &awstasks.LaunchTemplate{ - Name: fi.PtrTo(name), - Lifecycle: b.Lifecycle, - CPUCredits: fi.PtrTo(fi.ValueOf(ig.Spec.CPUCredits)), - HTTPPutResponseHopLimit: fi.PtrTo(int64(1)), - HTTPTokens: fi.PtrTo(ec2.LaunchTemplateHttpTokensStateRequired), - HTTPProtocolIPv6: fi.PtrTo(ec2.LaunchTemplateInstanceMetadataProtocolIpv6Disabled), - IAMInstanceProfile: link, - ImageID: fi.PtrTo(ig.Spec.Image), - InstanceInterruptionBehavior: ig.Spec.InstanceInterruptionBehavior, - InstanceMonitoring: fi.PtrTo(false), - IPv6AddressCount: fi.PtrTo(int64(0)), - RootVolumeIops: fi.PtrTo(int64(0)), - RootVolumeSize: fi.PtrTo(int64(rootVolumeSize)), - RootVolumeType: fi.PtrTo(rootVolumeType), - RootVolumeEncryption: fi.PtrTo(rootVolumeEncryption), - RootVolumeKmsKey: fi.PtrTo(rootVolumeKmsKey), - SecurityGroups: securityGroups, - Tags: tags, - UserData: userData, + Name: fi.PtrTo(name), + Lifecycle: b.Lifecycle, + CPUCredits: fi.PtrTo(fi.ValueOf(ig.Spec.CPUCredits)), + HTTPPutResponseHopLimit: fi.PtrTo(int32(1)), + HTTPTokens: fi.PtrTo(ec2types.LaunchTemplateHttpTokensStateRequired), + HTTPProtocolIPv6: fi.PtrTo(ec2types.LaunchTemplateInstanceMetadataProtocolIpv6Disabled), + IAMInstanceProfile: link, + ImageID: fi.PtrTo(ig.Spec.Image), + InstanceMonitoring: fi.PtrTo(false), + IPv6AddressCount: fi.PtrTo(int32(0)), + RootVolumeIops: fi.PtrTo(int32(0)), + RootVolumeSize: fi.PtrTo(int32(rootVolumeSize)), + RootVolumeType: rootVolumeType, + RootVolumeEncryption: fi.PtrTo(rootVolumeEncryption), + RootVolumeKmsKey: fi.PtrTo(rootVolumeKmsKey), + SecurityGroups: securityGroups, + Tags: tags, + UserData: userData, + } + if ig.Spec.InstanceInterruptionBehavior != nil { + lt.InstanceInterruptionBehavior = fi.PtrTo(ec2types.InstanceInterruptionBehavior(fi.ValueOf(ig.Spec.InstanceInterruptionBehavior))) } if ig.Spec.RootVolume != nil { - lt.RootVolumeIops = fi.PtrTo(int64(fi.ValueOf(ig.Spec.RootVolume.IOPS))) + if ig.Spec.RootVolume.IOPS != nil { + lt.RootVolumeIops = fi.PtrTo(int32(fi.ValueOf(ig.Spec.RootVolume.IOPS))) + } lt.RootVolumeOptimization = ig.Spec.RootVolume.Optimization } if ig.Spec.Manager == kops.InstanceManagerCloudGroup { - lt.InstanceType = fi.PtrTo(strings.Split(ig.Spec.MachineType, ",")[0]) + lt.InstanceType = fi.PtrTo(ec2types.InstanceType(strings.Split(ig.Spec.MachineType, ",")[0])) } { @@ -240,8 +244,8 @@ func (b *AutoscalingGroupModelBuilder) buildLaunchTemplateTask(c *fi.CloudupMode continue } if clusterSubnet.IPv6CIDR != "" { - lt.IPv6AddressCount = fi.PtrTo(int64(1)) - lt.HTTPProtocolIPv6 = fi.PtrTo(ec2.LaunchTemplateInstanceMetadataProtocolIpv6Enabled) + lt.IPv6AddressCount = fi.PtrTo(int32(1)) + lt.HTTPProtocolIPv6 = fi.PtrTo(ec2types.LaunchTemplateInstanceMetadataProtocolIpv6Enabled) } } } @@ -251,20 +255,21 @@ func (b *AutoscalingGroupModelBuilder) buildLaunchTemplateTask(c *fi.CloudupMode for i := range ig.Spec.Volumes { x := &ig.Spec.Volumes[i] if x.Type == "" { - x.Type = DefaultVolumeType + x.Type = string(DefaultVolumeType) } - if x.Type == ec2.VolumeTypeIo1 || x.Type == ec2.VolumeTypeIo2 { + switch ec2types.VolumeType(x.Type) { + case ec2types.VolumeTypeIo1, ec2types.VolumeTypeIo2: if x.IOPS == nil { x.IOPS = fi.PtrTo(int64(DefaultVolumeIonIops)) } - } else if x.Type == ec2.VolumeTypeGp3 { + case ec2types.VolumeTypeGp3: if x.IOPS == nil { x.IOPS = fi.PtrTo(int64(DefaultVolumeGp3Iops)) } if x.Throughput == nil { x.Throughput = fi.PtrTo(int64(DefaultVolumeGp3Throughput)) } - } else { + default: x.IOPS = nil } deleteOnTermination := DefaultVolumeDeleteOnTermination @@ -275,16 +280,21 @@ func (b *AutoscalingGroupModelBuilder) buildLaunchTemplateTask(c *fi.CloudupMode if x.Encrypted != nil { encryption = fi.ValueOf(x.Encrypted) } - lt.BlockDeviceMappings = append(lt.BlockDeviceMappings, &awstasks.BlockDeviceMapping{ + bdm := &awstasks.BlockDeviceMapping{ DeviceName: fi.PtrTo(x.Device), EbsDeleteOnTermination: fi.PtrTo(deleteOnTermination), EbsEncrypted: fi.PtrTo(encryption), EbsKmsKey: x.Key, - EbsVolumeIops: x.IOPS, - EbsVolumeSize: fi.PtrTo(x.Size), - EbsVolumeThroughput: x.Throughput, - EbsVolumeType: fi.PtrTo(x.Type), - }) + EbsVolumeSize: fi.PtrTo(int32(x.Size)), + EbsVolumeType: ec2types.VolumeType(x.Type), + } + if x.IOPS != nil { + bdm.EbsVolumeIops = fi.PtrTo(int32(fi.ValueOf(x.IOPS))) + } + if x.Throughput != nil { + bdm.EbsVolumeThroughput = fi.PtrTo(int32(fi.ValueOf(x.Throughput))) + } + lt.BlockDeviceMappings = append(lt.BlockDeviceMappings, bdm) } if ig.Spec.DetailedInstanceMonitoring != nil { @@ -292,27 +302,27 @@ func (b *AutoscalingGroupModelBuilder) buildLaunchTemplateTask(c *fi.CloudupMode } if ig.Spec.InstanceMetadata != nil && ig.Spec.InstanceMetadata.HTTPPutResponseHopLimit != nil { - lt.HTTPPutResponseHopLimit = ig.Spec.InstanceMetadata.HTTPPutResponseHopLimit + lt.HTTPPutResponseHopLimit = fi.PtrTo(int32(fi.ValueOf(ig.Spec.InstanceMetadata.HTTPPutResponseHopLimit))) } if ig.Spec.InstanceMetadata != nil && ig.Spec.InstanceMetadata.HTTPTokens != nil { - lt.HTTPTokens = ig.Spec.InstanceMetadata.HTTPTokens + lt.HTTPTokens = fi.PtrTo(ec2types.LaunchTemplateHttpTokensState(fi.ValueOf(ig.Spec.InstanceMetadata.HTTPTokens))) } else if b.IsKubernetesLT("1.27") { - lt.HTTPTokens = fi.PtrTo(ec2.LaunchTemplateHttpTokensStateOptional) + lt.HTTPTokens = fi.PtrTo(ec2types.LaunchTemplateHttpTokensStateOptional) } - if rootVolumeType == ec2.VolumeTypeIo1 || rootVolumeType == ec2.VolumeTypeIo2 { + if rootVolumeType == ec2types.VolumeTypeIo1 || rootVolumeType == ec2types.VolumeTypeIo2 { if ig.Spec.RootVolume == nil || fi.ValueOf(ig.Spec.RootVolume.IOPS) < 100 { - lt.RootVolumeIops = fi.PtrTo(int64(DefaultVolumeIonIops)) + lt.RootVolumeIops = fi.PtrTo(int32(DefaultVolumeIonIops)) } - } else if rootVolumeType == ec2.VolumeTypeGp3 { + } else if rootVolumeType == ec2types.VolumeTypeGp3 { if ig.Spec.RootVolume == nil || fi.ValueOf(ig.Spec.RootVolume.IOPS) < 3000 { - lt.RootVolumeIops = fi.PtrTo(int64(DefaultVolumeGp3Iops)) + lt.RootVolumeIops = fi.PtrTo(int32(DefaultVolumeGp3Iops)) } if ig.Spec.RootVolume == nil || fi.ValueOf(ig.Spec.RootVolume.Throughput) < 125 { - lt.RootVolumeThroughput = fi.PtrTo(int64(DefaultVolumeGp3Throughput)) + lt.RootVolumeThroughput = fi.PtrTo(int32(DefaultVolumeGp3Throughput)) } else { - lt.RootVolumeThroughput = fi.PtrTo(int64(fi.ValueOf(ig.Spec.RootVolume.Throughput))) + lt.RootVolumeThroughput = fi.PtrTo(int32(fi.ValueOf(ig.Spec.RootVolume.Throughput))) } } else { lt.RootVolumeIops = nil @@ -334,11 +344,11 @@ func (b *AutoscalingGroupModelBuilder) buildLaunchTemplateTask(c *fi.CloudupMode lt.SpotPrice = fi.PtrTo("") } if ig.Spec.SpotDurationInMinutes != nil { - lt.SpotDurationInMinutes = ig.Spec.SpotDurationInMinutes + lt.SpotDurationInMinutes = fi.PtrTo(int32(fi.ValueOf(ig.Spec.SpotDurationInMinutes))) } if ig.Spec.Tenancy != "" { - lt.Tenancy = fi.PtrTo(ig.Spec.Tenancy) + lt.Tenancy = fi.PtrTo(ec2types.Tenancy(ig.Spec.Tenancy)) } return lt, nil diff --git a/pkg/model/master_volumes.go b/pkg/model/master_volumes.go index d2a26112d2..38c6f89087 100644 --- a/pkg/model/master_volumes.go +++ b/pkg/model/master_volumes.go @@ -21,7 +21,7 @@ import ( "sort" "strings" - "github.com/aws/aws-sdk-go/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/scaleway/scaleway-sdk-go/api/instance/v1" "k8s.io/kops/pkg/apis/kops" "k8s.io/kops/pkg/apis/kops/model" @@ -44,7 +44,7 @@ import ( const ( DefaultEtcdVolumeSize = 20 - DefaultAWSEtcdVolumeType = ec2.VolumeTypeGp3 + DefaultAWSEtcdVolumeType = "gp3" DefaultAWSEtcdVolumeIonIops = 100 DefaultAWSEtcdVolumeGp3Iops = 3000 DefaultAWSEtcdVolumeGp3Throughput = 125 @@ -138,12 +138,12 @@ func (b *MasterVolumeBuilder) addAWSVolume(c *fi.CloudupModelBuilderContext, nam } volumeIops := fi.ValueOf(m.VolumeIOPS) volumeThroughput := fi.ValueOf(m.VolumeThroughput) - switch volumeType { - case ec2.VolumeTypeIo1, ec2.VolumeTypeIo2: + switch ec2types.VolumeType(volumeType) { + case ec2types.VolumeTypeIo1, ec2types.VolumeTypeIo2: if volumeIops < 100 { volumeIops = DefaultAWSEtcdVolumeIonIops } - case ec2.VolumeTypeGp3: + case ec2types.VolumeTypeGp3: if volumeIops < 3000 { volumeIops = DefaultAWSEtcdVolumeGp3Iops } @@ -181,18 +181,18 @@ func (b *MasterVolumeBuilder) addAWSVolume(c *fi.CloudupModelBuilderContext, nam Lifecycle: b.Lifecycle, AvailabilityZone: fi.PtrTo(zone), - SizeGB: fi.PtrTo(int64(volumeSize)), - VolumeType: fi.PtrTo(volumeType), + SizeGB: fi.PtrTo(int32(volumeSize)), + VolumeType: ec2types.VolumeType(volumeType), KmsKeyId: m.KmsKeyID, Encrypted: fi.PtrTo(encrypted), Tags: tags, } - switch volumeType { - case ec2.VolumeTypeGp3: - t.VolumeThroughput = fi.PtrTo(int64(volumeThroughput)) + switch ec2types.VolumeType(volumeType) { + case ec2types.VolumeTypeGp3: + t.VolumeThroughput = fi.PtrTo(int32(volumeThroughput)) fallthrough - case ec2.VolumeTypeIo1, ec2.VolumeTypeIo2: - t.VolumeIops = fi.PtrTo(int64(volumeIops)) + case ec2types.VolumeTypeIo1, ec2types.VolumeTypeIo2: + t.VolumeIops = fi.PtrTo(int32(volumeIops)) } c.AddTask(t) @@ -203,16 +203,16 @@ func (b *MasterVolumeBuilder) addAWSVolume(c *fi.CloudupModelBuilderContext, nam func validateAWSVolume(name, volumeType string, volumeSize, volumeIops, volumeThroughput int32) error { volumeIopsSizeRatio := float64(volumeIops) / float64(volumeSize) volumeThroughputIopsRatio := float64(volumeThroughput) / float64(volumeIops) - switch volumeType { - case ec2.VolumeTypeIo1: + switch ec2types.VolumeType(volumeType) { + case ec2types.VolumeTypeIo1: if volumeIopsSizeRatio > 50.0 { return fmt.Errorf("volumeIops to volumeSize ratio must be lower than 50. For %s ratio is %.02f", name, volumeIopsSizeRatio) } - case ec2.VolumeTypeIo2: + case ec2types.VolumeTypeIo2: if volumeIopsSizeRatio > 500.0 { return fmt.Errorf("volumeIops to volumeSize ratio must be lower than 500. For %s ratio is %.02f", name, volumeIopsSizeRatio) } - case ec2.VolumeTypeGp3: + case ec2types.VolumeTypeGp3: if volumeIops > 3000 && volumeIopsSizeRatio > 500.0 { return fmt.Errorf("volumeIops to volumeSize ratio must be lower than 500. For %s ratio is %.02f", name, volumeIopsSizeRatio) } diff --git a/pkg/resources/aws/aws.go b/pkg/resources/aws/aws.go index 9371ee716d..c1096839c4 100644 --- a/pkg/resources/aws/aws.go +++ b/pkg/resources/aws/aws.go @@ -210,11 +210,11 @@ func ListResourcesAWS(cloud awsup.AWSCloud, clusterInfo resources.ClusterInfo) ( return resourceTrackers, nil } -func BuildEC2Filters(cloud fi.Cloud) []*ec2.Filter { +func BuildEC2Filters(cloud fi.Cloud) []ec2types.Filter { awsCloud := cloud.(awsup.AWSCloud) tags := awsCloud.Tags() - var filters []*ec2.Filter + var filters []ec2types.Filter for k, v := range tags { filter := awsup.NewEC2Filter("tag:"+k, v) filters = append(filters, filter) @@ -324,11 +324,12 @@ func matchesIAMTags(tags map[string]string, actual []iamtypes.Tag) bool { } func DeleteInstances(cloud fi.Cloud, t []*resources.Resource) error { + ctx := context.TODO() c := cloud.(awsup.AWSCloud) - var ids []*string + var ids []string for i, instance := range t { - ids = append(ids, &instance.ID) + ids = append(ids, instance.ID) if len(ids) < 100 && i < len(t)-1 { continue } @@ -337,8 +338,8 @@ func DeleteInstances(cloud fi.Cloud, t []*resources.Resource) error { request := &ec2.TerminateInstancesInput{ InstanceIds: ids, } - ids = []*string{} - _, err := c.EC2().TerminateInstances(request) + ids = []string{} + _, err := c.EC2().TerminateInstances(ctx, request) if err != nil { if awsup.AWSErrorCode(err) == "InvalidInstanceID.NotFound" { klog.V(2).Infof("Got InvalidInstanceID.NotFound error terminating instances; will treat as already terminated") @@ -351,27 +352,33 @@ func DeleteInstances(cloud fi.Cloud, t []*resources.Resource) error { } func ListInstances(cloud fi.Cloud, vpcID, clusterName string) ([]*resources.Resource, error) { + ctx := context.TODO() c := cloud.(awsup.AWSCloud) klog.V(2).Infof("Querying EC2 instances") filters := BuildEC2Filters(cloud) filters = append(filters, awsup.NewEC2Filter("vpc-id", vpcID)) - filters = append(filters, awsup.NewEC2Filter("instance-state-name", ec2.InstanceStateNameRunning)) + filters = append(filters, awsup.NewEC2Filter("instance-state-name", string(ec2types.InstanceStateNameRunning))) request := &ec2.DescribeInstancesInput{ Filters: filters, } var resourceTrackers []*resources.Resource - err := c.EC2().DescribeInstancesPages(request, func(p *ec2.DescribeInstancesOutput, lastPage bool) bool { - for _, reservation := range p.Reservations { + paginator := ec2.NewDescribeInstancesPaginator(c.EC2(), request) + for paginator.HasMorePages() { + page, err := paginator.NextPage(ctx) + if err != nil { + return nil, fmt.Errorf("error describing instances: %v", err) + } + for _, reservation := range page.Reservations { for _, instance := range reservation.Instances { id := aws.ToString(instance.InstanceId) resourceTracker := &resources.Resource{ Name: FindName(instance.Tags), ID: id, - Type: ec2.ResourceTypeInstance, + Type: string(ec2types.ResourceTypeInstance), GroupDeleter: DeleteInstances, GroupKey: fi.ValueOf(instance.SubnetId), Dumper: DumpInstance, @@ -397,10 +404,6 @@ func ListInstances(cloud fi.Cloud, vpcID, clusterName string) ([]*resources.Reso resourceTrackers = append(resourceTrackers, resourceTracker) } } - return true - }) - if err != nil { - return nil, fmt.Errorf("error describing instances: %v", err) } return resourceTrackers, nil @@ -456,7 +459,7 @@ func (s *dumpState) getImageInfo(imageID string) (*imageInfo, error) { return info, nil } -func guessSSHUser(image *ec2.Image) string { +func guessSSHUser(image *ec2types.Image) string { owner := aws.ToString(image.OwnerId) switch owner { case awsup.WellKnownAccountAmazonLinux2, awsup.WellKnownAccountRedhat: @@ -482,11 +485,11 @@ func guessSSHUser(image *ec2.Image) string { func DumpInstance(op *resources.DumpOperation, r *resources.Resource) error { data := make(map[string]interface{}) data["id"] = r.ID - data["type"] = ec2.ResourceTypeInstance + data["type"] = ec2types.ResourceTypeInstance data["raw"] = r.Obj op.Dump.Resources = append(op.Dump.Resources, data) - ec2Instance := r.Obj.(*ec2.Instance) + ec2Instance := r.Obj.(*ec2types.Instance) i := &resources.Instance{ Name: r.ID, } @@ -536,6 +539,7 @@ func DumpInstance(op *resources.DumpOperation, r *resources.Resource) error { } func DeleteVolume(cloud fi.Cloud, r *resources.Resource) error { + ctx := context.TODO() c := cloud.(awsup.AWSCloud) id := r.ID @@ -544,7 +548,7 @@ func DeleteVolume(cloud fi.Cloud, r *resources.Resource) error { request := &ec2.DeleteVolumeInput{ VolumeId: &id, } - _, err := c.EC2().DeleteVolume(request) + _, err := c.EC2().DeleteVolume(ctx, request) if err != nil { if awsup.AWSErrorCode(err) == "InvalidVolume.NotFound" { klog.V(2).Infof("Got InvalidVolume.NotFound error deleting Volume %q; will treat as already-deleted", id) @@ -559,6 +563,7 @@ func DeleteVolume(cloud fi.Cloud, r *resources.Resource) error { } func ListVolumes(cloud fi.Cloud, vpcID, clusterName string) ([]*resources.Resource, error) { + ctx := context.TODO() c := cloud.(awsup.AWSCloud) volumes, err := DescribeVolumes(cloud) @@ -587,7 +592,7 @@ func ListVolumes(cloud fi.Cloud, vpcID, clusterName string) ([]*resources.Resour ID: id, Type: "volume", Deleter: DeleteVolume, - Shared: HasSharedTag(ec2.ResourceTypeVolume+":"+id, volume.Tags, clusterName), + Shared: HasSharedTag(string(ec2types.ResourceTypeVolume)+":"+id, volume.Tags, clusterName), } var blocks []string @@ -614,7 +619,7 @@ func ListVolumes(cloud fi.Cloud, vpcID, clusterName string) ([]*resources.Resour if len(elasticIPs) != 0 { klog.V(2).Infof("Querying EC2 Elastic IPs") request := &ec2.DescribeAddressesInput{} - response, err := c.EC2().DescribeAddresses(request) + response, err := c.EC2().DescribeAddresses(ctx, request) if err != nil { return nil, fmt.Errorf("error describing addresses: %v", err) } @@ -632,28 +637,31 @@ func ListVolumes(cloud fi.Cloud, vpcID, clusterName string) ([]*resources.Resour return resourceTrackers, nil } -func DescribeVolumes(cloud fi.Cloud) ([]*ec2.Volume, error) { +func DescribeVolumes(cloud fi.Cloud) ([]ec2types.Volume, error) { + ctx := context.TODO() c := cloud.(awsup.AWSCloud) - var volumes []*ec2.Volume + var volumes []ec2types.Volume klog.V(2).Infof("Listing EC2 Volumes") request := &ec2.DescribeVolumesInput{ Filters: BuildEC2Filters(c), } - err := c.EC2().DescribeVolumesPages(request, func(p *ec2.DescribeVolumesOutput, lastPage bool) bool { - volumes = append(volumes, p.Volumes...) - return true - }) - if err != nil { - return nil, fmt.Errorf("error describing volumes: %v", err) + paginator := ec2.NewDescribeVolumesPaginator(c.EC2(), request) + for paginator.HasMorePages() { + page, err := paginator.NextPage(ctx) + if err != nil { + return nil, fmt.Errorf("error describing volumes: %v", err) + } + volumes = append(volumes, page.Volumes...) } return volumes, nil } func DeleteKeypair(cloud fi.Cloud, r *resources.Resource) error { + ctx := context.TODO() c := cloud.(awsup.AWSCloud) id := r.ID @@ -662,7 +670,7 @@ func DeleteKeypair(cloud fi.Cloud, r *resources.Resource) error { request := &ec2.DeleteKeyPairInput{ KeyPairId: &id, } - _, err := c.EC2().DeleteKeyPair(request) + _, err := c.EC2().DeleteKeyPair(ctx, request) if err != nil { return fmt.Errorf("error deleting KeyPair %q: %v", id, err) } @@ -670,6 +678,7 @@ func DeleteKeypair(cloud fi.Cloud, r *resources.Resource) error { } func ListKeypairs(cloud fi.Cloud, vpcID, clusterName string) ([]*resources.Resource, error) { + ctx := context.TODO() if !strings.Contains(clusterName, ".") { klog.Infof("cluster %q is legacy (kube-up) cluster; won't delete keypairs", clusterName) return nil, nil @@ -684,7 +693,7 @@ func ListKeypairs(cloud fi.Cloud, vpcID, clusterName string) ([]*resources.Resou // TODO: We need to match both the name and a prefix // TODO: usee 'Filters: []*ec2.Filter{awsup.NewEC2Filter("key-name", keypairName)},' request := &ec2.DescribeKeyPairsInput{} - response, err := c.EC2().DescribeKeyPairs(request) + response, err := c.EC2().DescribeKeyPairs(ctx, request) if err != nil { return nil, fmt.Errorf("error listing KeyPairs: %v", err) } @@ -1275,22 +1284,28 @@ func ListAutoScalingGroups(cloud fi.Cloud, vpcID, clusterName string) ([]*resour // FindAutoScalingLaunchTemplates finds any launch templates owned by the cluster (by tag). func FindAutoScalingLaunchTemplates(cloud fi.Cloud, clusterName string) ([]*resources.Resource, error) { + ctx := context.TODO() c := cloud.(awsup.AWSCloud) klog.V(2).Infof("Finding all AutoScaling LaunchTemplates owned by the cluster") input := &ec2.DescribeLaunchTemplatesInput{ - Filters: []*ec2.Filter{ + Filters: []ec2types.Filter{ { Name: aws.String("tag:kubernetes.io/cluster/" + clusterName), - Values: []*string{aws.String("owned")}, + Values: []string{"owned"}, }, }, } var list []*resources.Resource - err := c.EC2().DescribeLaunchTemplatesPages(input, func(p *ec2.DescribeLaunchTemplatesOutput, lastPage bool) (shouldContinue bool) { - for _, lt := range p.LaunchTemplates { + paginator := ec2.NewDescribeLaunchTemplatesPaginator(c.EC2(), input) + for paginator.HasMorePages() { + page, err := paginator.NextPage(ctx) + if err != nil { + return nil, fmt.Errorf("error listing AutoScaling LaunchTemplates: %v", err) + } + for _, lt := range page.LaunchTemplates { list = append(list, &resources.Resource{ Name: aws.ToString(lt.LaunchTemplateName), ID: aws.ToString(lt.LaunchTemplateId), @@ -1298,10 +1313,6 @@ func FindAutoScalingLaunchTemplates(cloud fi.Cloud, clusterName string) ([]*reso Deleter: DeleteAutoScalingGroupLaunchTemplate, }) } - return true - }) - if err != nil { - return nil, fmt.Errorf("error listing AutoScaling LaunchTemplates: %v", err) } return list, nil @@ -1411,13 +1422,14 @@ func FindNatGateways(cloud fi.Cloud, routeTables map[string]*resources.Resource, // DeleteAutoScalingGroupLaunchTemplate deletes func DeleteAutoScalingGroupLaunchTemplate(cloud fi.Cloud, r *resources.Resource) error { + ctx := context.TODO() c, ok := cloud.(awsup.AWSCloud) if !ok { return errors.New("expected a aws.Cloud provider") } klog.V(2).Infof("Deleting EC2 LaunchTemplate %q", r.ID) - if _, err := c.EC2().DeleteLaunchTemplate(&ec2.DeleteLaunchTemplateInput{ + if _, err := c.EC2().DeleteLaunchTemplate(ctx, &ec2.DeleteLaunchTemplateInput{ LaunchTemplateId: fi.PtrTo(r.ID), }); err != nil { return fmt.Errorf("error deleting ec2 LaunchTemplate %q: %v", r.ID, err) @@ -2151,7 +2163,7 @@ func ListSpotinstResources(cloud fi.Cloud, vpcID, clusterName string) ([]*resour return spotinst.ListResources(cloud.(awsup.AWSCloud).Spotinst(), clusterName) } -func FindName(tags []*ec2.Tag) string { +func FindName(tags []ec2types.Tag) string { if name, found := awsup.FindEC2Tag(tags, "Name"); found { return name } @@ -2180,16 +2192,16 @@ func FindELBV2Name(tags []elbv2types.Tag) string { } // HasSharedTag looks for the shared tag indicating that the cluster does not own the resource -func HasSharedTag(description string, tags []*ec2.Tag, clusterName string) bool { +func HasSharedTag(description string, tags []ec2types.Tag, clusterName string) bool { tagKey := "kubernetes.io/cluster/" + clusterName - var found *ec2.Tag + var found *ec2types.Tag for _, tag := range tags { if aws.ToString(tag.Key) != tagKey { continue } - found = tag + found = &tag } if found == nil { diff --git a/pkg/resources/aws/aws_test.go b/pkg/resources/aws/aws_test.go index 60cae0a93d..c28cf43e01 100644 --- a/pkg/resources/aws/aws_test.go +++ b/pkg/resources/aws/aws_test.go @@ -17,14 +17,16 @@ limitations under the License. package aws import ( + "context" "reflect" "sort" "testing" "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" elbtypes "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing/types" iamtypes "github.com/aws/aws-sdk-go-v2/service/iam/types" - "github.com/aws/aws-sdk-go/service/ec2" "k8s.io/kops/cloudmock/aws/mockec2" "k8s.io/kops/cloudmock/aws/mockiam" "k8s.io/kops/pkg/resources" @@ -42,16 +44,16 @@ func TestAddUntaggedRouteTables(t *testing.T) { cloud.MockEC2 = c // Matches by vpc id - c.AddRouteTable(&ec2.RouteTable{ + c.AddRouteTable(&ec2types.RouteTable{ VpcId: aws.String("vpc-1234"), RouteTableId: aws.String("rtb-1234"), }) // Skips main route tables - c.AddRouteTable(&ec2.RouteTable{ + c.AddRouteTable(&ec2types.RouteTable{ VpcId: aws.String("vpc-1234"), RouteTableId: aws.String("rtb-1234main"), - Associations: []*ec2.RouteTableAssociation{ + Associations: []ec2types.RouteTableAssociation{ { Main: aws.Bool(true), }, @@ -59,10 +61,10 @@ func TestAddUntaggedRouteTables(t *testing.T) { }) // Skips route table tagged with other cluster - c.AddRouteTable(&ec2.RouteTable{ + c.AddRouteTable(&ec2types.RouteTable{ VpcId: aws.String("vpc-1234"), RouteTableId: aws.String("rtb-1234notmain"), - Tags: []*ec2.Tag{ + Tags: []ec2types.Tag{ { Key: aws.String(awsup.TagClusterName), Value: aws.String("other.example.com"), @@ -71,7 +73,7 @@ func TestAddUntaggedRouteTables(t *testing.T) { }) // Ignores non-matching vpcs - c.AddRouteTable(&ec2.RouteTable{ + c.AddRouteTable(&ec2types.RouteTable{ VpcId: aws.String("vpc-5555"), RouteTableId: aws.String("rtb-5555"), }) @@ -243,10 +245,10 @@ func TestListRouteTables(t *testing.T) { c := &mockec2.MockEC2{} cloud.MockEC2 = c - c.AddRouteTable(&ec2.RouteTable{ + c.AddRouteTable(&ec2types.RouteTable{ VpcId: aws.String("vpc-1234"), RouteTableId: aws.String("rtb-shared"), - Tags: []*ec2.Tag{ + Tags: []ec2types.Tag{ { Key: aws.String("KubernetesCluster"), Value: aws.String(clusterName), @@ -257,10 +259,10 @@ func TestListRouteTables(t *testing.T) { }, }, }) - c.AddRouteTable(&ec2.RouteTable{ + c.AddRouteTable(&ec2types.RouteTable{ VpcId: aws.String("vpc-1234"), RouteTableId: aws.String("rtb-owned"), - Tags: []*ec2.Tag{ + Tags: []ec2types.Tag{ { Key: aws.String("KubernetesCluster"), Value: aws.String(clusterName), @@ -287,6 +289,7 @@ func TestListRouteTables(t *testing.T) { } func TestSharedVolume(t *testing.T) { + ctx := context.Background() cloud := awsup.BuildMockAWSCloud("us-east-1", "abc") clusterName := "me.example.com" ownershipTagKey := "kubernetes.io/cluster/" + clusterName @@ -294,11 +297,11 @@ func TestSharedVolume(t *testing.T) { c := &mockec2.MockEC2{} cloud.MockEC2 = c - sharedVolume, err := c.CreateVolume(&ec2.CreateVolumeInput{ - TagSpecifications: []*ec2.TagSpecification{ + sharedVolume, err := c.CreateVolume(ctx, &ec2.CreateVolumeInput{ + TagSpecifications: []ec2types.TagSpecification{ { - ResourceType: aws.String(ec2.ResourceTypeVolume), - Tags: []*ec2.Tag{ + ResourceType: ec2types.ResourceTypeVolume, + Tags: []ec2types.Tag{ { Key: aws.String(ownershipTagKey), Value: aws.String("shared"), @@ -311,10 +314,10 @@ func TestSharedVolume(t *testing.T) { t.Fatalf("error creating volume: %v", err) } - ownedVolume, err := c.CreateVolume(&ec2.CreateVolumeInput{ - TagSpecifications: []*ec2.TagSpecification{ + ownedVolume, err := c.CreateVolume(ctx, &ec2.CreateVolumeInput{ + TagSpecifications: []ec2types.TagSpecification{ { - Tags: []*ec2.Tag{ + Tags: []ec2types.Tag{ { Key: aws.String(ownershipTagKey), Value: aws.String("owned"), diff --git a/pkg/resources/aws/filters.go b/pkg/resources/aws/filters.go index 4a2b0c5147..875c072607 100644 --- a/pkg/resources/aws/filters.go +++ b/pkg/resources/aws/filters.go @@ -18,22 +18,22 @@ package aws import ( "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "k8s.io/kops/upup/pkg/fi/cloudup/awsup" ) // buildEc2FiltersForCluster returns the set of filters we must use to find all resources -func buildEC2FiltersForCluster(clusterName string) [][]*ec2.Filter { - var filterSets [][]*ec2.Filter +func buildEC2FiltersForCluster(clusterName string) [][]ec2types.Filter { + var filterSets [][]ec2types.Filter // TODO: We could look for tag-key on the old & new tags, and then post-filter (we do this in k/k cloudprovider) - filterSets = append(filterSets, []*ec2.Filter{ - {Name: aws.String("tag:" + awsup.TagClusterName), Values: aws.StringSlice([]string{clusterName})}, + filterSets = append(filterSets, []ec2types.Filter{ + {Name: aws.String("tag:" + awsup.TagClusterName), Values: []string{clusterName}}, }) - filterSets = append(filterSets, []*ec2.Filter{ - {Name: aws.String("tag-key"), Values: aws.StringSlice([]string{"kubernetes.io/cluster/" + clusterName})}, + filterSets = append(filterSets, []ec2types.Filter{ + {Name: aws.String("tag-key"), Values: []string{"kubernetes.io/cluster/" + clusterName}}, }) return filterSets diff --git a/pkg/resources/aws/tags.go b/pkg/resources/aws/tags.go index 69cd379108..4e3b0d915e 100644 --- a/pkg/resources/aws/tags.go +++ b/pkg/resources/aws/tags.go @@ -18,22 +18,22 @@ package aws import ( "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "k8s.io/klog/v2" "k8s.io/kops/upup/pkg/fi/cloudup/awsup" ) // HasOwnedTag looks for the new tag indicating that the cluster does owns the resource, or the legacy tag -func HasOwnedTag(description string, tags []*ec2.Tag, clusterName string) bool { +func HasOwnedTag(description string, tags []ec2types.Tag, clusterName string) bool { tagKey := "kubernetes.io/cluster/" + clusterName - var found *ec2.Tag + var found *ec2types.Tag for _, tag := range tags { if aws.ToString(tag.Key) != tagKey { continue } - found = tag + found = &tag } if found != nil { @@ -56,7 +56,7 @@ func HasOwnedTag(description string, tags []*ec2.Tag, clusterName string) bool { continue } - found = tag + found = &tag } if found != nil { diff --git a/upup/pkg/fi/cloudup/awstasks/block_device_mappings.go b/upup/pkg/fi/cloudup/awstasks/block_device_mappings.go index ce4b9b4874..54de981a03 100644 --- a/upup/pkg/fi/cloudup/awstasks/block_device_mappings.go +++ b/upup/pkg/fi/cloudup/awstasks/block_device_mappings.go @@ -20,8 +20,8 @@ import ( "k8s.io/kops/upup/pkg/fi" "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go/service/autoscaling" - "github.com/aws/aws-sdk-go/service/ec2" + autoscalingtypes "github.com/aws/aws-sdk-go-v2/service/autoscaling/types" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" ) // BlockDeviceMapping defines the specification for a device mapping @@ -35,19 +35,19 @@ type BlockDeviceMapping struct { // EbsKmsKey is the encryption key identifier for the volume EbsKmsKey *string // EbsVolumeIops is the provisioned iops for the volume - EbsVolumeIops *int64 + EbsVolumeIops *int32 // EbsVolumeThroughput is the throughput for the volume - EbsVolumeThroughput *int64 + EbsVolumeThroughput *int32 // EbsVolumeSize is the size of the volume - EbsVolumeSize *int64 + EbsVolumeSize *int32 // EbsVolumeType is the aws volume type - EbsVolumeType *string + EbsVolumeType ec2types.VolumeType // VirtualName is the device name VirtualName *string } // BlockDeviceMappingFromEC2 converts a e2c block mapping to internal block device mapping -func BlockDeviceMappingFromEC2(i *ec2.BlockDeviceMapping) (string, *BlockDeviceMapping) { +func BlockDeviceMappingFromEC2(i ec2types.BlockDeviceMapping) (string, *BlockDeviceMapping) { o := &BlockDeviceMapping{ DeviceName: i.DeviceName, VirtualName: i.VirtualName, @@ -66,23 +66,23 @@ func BlockDeviceMappingFromEC2(i *ec2.BlockDeviceMapping) (string, *BlockDeviceM } // ToEC2 creates and returns an ec2 block mapping -func (i *BlockDeviceMapping) ToEC2(deviceName string) *ec2.BlockDeviceMapping { - o := &ec2.BlockDeviceMapping{ +func (i *BlockDeviceMapping) ToEC2(deviceName string) ec2types.BlockDeviceMapping { + o := ec2types.BlockDeviceMapping{ DeviceName: aws.String(deviceName), VirtualName: i.VirtualName, } - if i.EbsDeleteOnTermination != nil || i.EbsVolumeSize != nil || i.EbsVolumeType != nil || i.EbsEncrypted != nil { - o.Ebs = &ec2.EbsBlockDevice{ + if i.EbsDeleteOnTermination != nil || i.EbsVolumeSize != nil || len(i.EbsVolumeType) > 0 || i.EbsEncrypted != nil { + o.Ebs = &ec2types.EbsBlockDevice{ DeleteOnTermination: i.EbsDeleteOnTermination, Encrypted: i.EbsEncrypted, VolumeSize: i.EbsVolumeSize, VolumeType: i.EbsVolumeType, } - switch fi.ValueOf(i.EbsVolumeType) { - case ec2.VolumeTypeGp3: + switch i.EbsVolumeType { + case ec2types.VolumeTypeGp3: o.Ebs.Throughput = i.EbsVolumeThroughput fallthrough - case ec2.VolumeTypeIo1, ec2.VolumeTypeIo2: + case ec2types.VolumeTypeIo1, ec2types.VolumeTypeIo2: o.Ebs.Iops = i.EbsVolumeIops } if fi.ValueOf(o.Ebs.Encrypted) { @@ -94,7 +94,7 @@ func (i *BlockDeviceMapping) ToEC2(deviceName string) *ec2.BlockDeviceMapping { } // BlockDeviceMappingFromAutoscaling converts an autoscaling block mapping to internal spec -func BlockDeviceMappingFromAutoscaling(i *autoscaling.BlockDeviceMapping) (string, *BlockDeviceMapping) { +func BlockDeviceMappingFromAutoscaling(i *autoscalingtypes.BlockDeviceMapping) (string, *BlockDeviceMapping) { o := &BlockDeviceMapping{ DeviceName: i.DeviceName, VirtualName: i.VirtualName, @@ -103,9 +103,9 @@ func BlockDeviceMappingFromAutoscaling(i *autoscaling.BlockDeviceMapping) (strin o.EbsDeleteOnTermination = i.Ebs.DeleteOnTermination o.EbsEncrypted = i.Ebs.Encrypted o.EbsVolumeSize = i.Ebs.VolumeSize - o.EbsVolumeType = i.Ebs.VolumeType + o.EbsVolumeType = ec2types.VolumeType(fi.ValueOf(i.Ebs.VolumeType)) - if fi.ValueOf(o.EbsVolumeType) == ec2.VolumeTypeIo1 || fi.ValueOf(o.EbsVolumeType) == ec2.VolumeTypeIo2 { + if o.EbsVolumeType == ec2types.VolumeTypeIo1 || o.EbsVolumeType == ec2types.VolumeTypeIo2 { o.EbsVolumeIops = i.Ebs.Iops } } @@ -114,19 +114,19 @@ func BlockDeviceMappingFromAutoscaling(i *autoscaling.BlockDeviceMapping) (strin } // ToAutoscaling converts the internal block mapping to autoscaling -func (i *BlockDeviceMapping) ToAutoscaling(deviceName string) *autoscaling.BlockDeviceMapping { - o := &autoscaling.BlockDeviceMapping{ +func (i *BlockDeviceMapping) ToAutoscaling(deviceName string) *autoscalingtypes.BlockDeviceMapping { + o := &autoscalingtypes.BlockDeviceMapping{ DeviceName: aws.String(deviceName), VirtualName: i.VirtualName, } - if i.EbsDeleteOnTermination != nil || i.EbsVolumeSize != nil || i.EbsVolumeType != nil { - o.Ebs = &autoscaling.Ebs{ + if i.EbsDeleteOnTermination != nil || i.EbsVolumeSize != nil || len(i.EbsVolumeType) > 0 { + o.Ebs = &autoscalingtypes.Ebs{ DeleteOnTermination: i.EbsDeleteOnTermination, Encrypted: i.EbsEncrypted, VolumeSize: i.EbsVolumeSize, - VolumeType: i.EbsVolumeType, + VolumeType: fi.PtrTo(string(i.EbsVolumeType)), } - if fi.ValueOf(o.Ebs.VolumeType) == ec2.VolumeTypeIo1 || fi.ValueOf(o.Ebs.VolumeType) == ec2.VolumeTypeIo2 { + if ec2types.VolumeType(fi.ValueOf(o.Ebs.VolumeType)) == ec2types.VolumeTypeIo1 || ec2types.VolumeType(fi.ValueOf(o.Ebs.VolumeType)) == ec2types.VolumeTypeIo2 { o.Ebs.Iops = i.EbsVolumeIops } } @@ -135,7 +135,7 @@ func (i *BlockDeviceMapping) ToAutoscaling(deviceName string) *autoscaling.Block } // BlockDeviceMappingFromLaunchTemplateBootDeviceRequest coverts the launch template device mappings to an interval block device mapping -func BlockDeviceMappingFromLaunchTemplateBootDeviceRequest(i *ec2.LaunchTemplateBlockDeviceMapping) (string, *BlockDeviceMapping) { +func BlockDeviceMappingFromLaunchTemplateBootDeviceRequest(i ec2types.LaunchTemplateBlockDeviceMapping) (string, *BlockDeviceMapping) { o := &BlockDeviceMapping{ DeviceName: i.DeviceName, VirtualName: i.VirtualName, @@ -154,24 +154,24 @@ func BlockDeviceMappingFromLaunchTemplateBootDeviceRequest(i *ec2.LaunchTemplate } // ToLaunchTemplateBootDeviceRequest coverts in the internal block device mapping to a launch template request -func (i *BlockDeviceMapping) ToLaunchTemplateBootDeviceRequest(deviceName string) *ec2.LaunchTemplateBlockDeviceMappingRequest { - o := &ec2.LaunchTemplateBlockDeviceMappingRequest{ +func (i *BlockDeviceMapping) ToLaunchTemplateBootDeviceRequest(deviceName string) ec2types.LaunchTemplateBlockDeviceMappingRequest { + o := ec2types.LaunchTemplateBlockDeviceMappingRequest{ DeviceName: aws.String(deviceName), VirtualName: i.VirtualName, } - if i.EbsDeleteOnTermination != nil || i.EbsVolumeSize != nil || i.EbsVolumeType != nil || i.EbsEncrypted != nil { - o.Ebs = &ec2.LaunchTemplateEbsBlockDeviceRequest{ + if i.EbsDeleteOnTermination != nil || i.EbsVolumeSize != nil || len(i.EbsVolumeType) > 0 || i.EbsEncrypted != nil { + o.Ebs = &ec2types.LaunchTemplateEbsBlockDeviceRequest{ DeleteOnTermination: i.EbsDeleteOnTermination, Encrypted: i.EbsEncrypted, VolumeSize: i.EbsVolumeSize, VolumeType: i.EbsVolumeType, } } - switch fi.ValueOf(i.EbsVolumeType) { - case ec2.VolumeTypeGp3: + switch i.EbsVolumeType { + case ec2types.VolumeTypeGp3: o.Ebs.Throughput = i.EbsVolumeThroughput fallthrough - case ec2.VolumeTypeIo1, ec2.VolumeTypeIo2: + case ec2types.VolumeTypeIo1, ec2types.VolumeTypeIo2: o.Ebs.Iops = i.EbsVolumeIops } if fi.ValueOf(i.EbsEncrypted) { diff --git a/upup/pkg/fi/cloudup/awstasks/classic_load_balancer.go b/upup/pkg/fi/cloudup/awstasks/classic_load_balancer.go index a8476cc7c9..7534818ff8 100644 --- a/upup/pkg/fi/cloudup/awstasks/classic_load_balancer.go +++ b/upup/pkg/fi/cloudup/awstasks/classic_load_balancer.go @@ -27,7 +27,6 @@ import ( elb "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing" elbtypes "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing/types" route53types "github.com/aws/aws-sdk-go-v2/service/route53/types" - "github.com/aws/aws-sdk-go/aws/awserr" "k8s.io/klog/v2" "k8s.io/kops/pkg/wellknownservices" "k8s.io/kops/upup/pkg/fi" @@ -131,10 +130,8 @@ func findLoadBalancerByLoadBalancerName(ctx context.Context, cloud awsup.AWSClou return false }) if err != nil { - if awsError, ok := err.(awserr.Error); ok { - if awsError.Code() == "LoadBalancerNotFound" { - return nil, nil - } + if awsup.AWSErrorCode(err) == "LoadBalancerNotFound" { + return nil, nil } return nil, fmt.Errorf("error listing ELBs: %v", err) diff --git a/upup/pkg/fi/cloudup/awstasks/ebsvolume.go b/upup/pkg/fi/cloudup/awstasks/ebsvolume.go index cb75c64b69..dbfb54a0c2 100644 --- a/upup/pkg/fi/cloudup/awstasks/ebsvolume.go +++ b/upup/pkg/fi/cloudup/awstasks/ebsvolume.go @@ -17,6 +17,7 @@ limitations under the License. package awstasks import ( + "context" "fmt" "os" @@ -25,7 +26,8 @@ import ( "k8s.io/kops/upup/pkg/fi/cloudup/terraform" "k8s.io/kops/upup/pkg/fi/cloudup/terraformWriter" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "k8s.io/klog/v2" ) @@ -38,11 +40,11 @@ type EBSVolume struct { Encrypted *bool ID *string KmsKeyId *string - SizeGB *int64 + SizeGB *int32 Tags map[string]string - VolumeIops *int64 - VolumeThroughput *int64 - VolumeType *string + VolumeIops *int32 + VolumeThroughput *int32 + VolumeType ec2types.VolumeType } var _ fi.CompareWithID = &EBSVolume{} @@ -52,15 +54,16 @@ func (e *EBSVolume) CompareWithID() *string { return e.ID } -func (e *EBSVolume) Find(context *fi.CloudupContext) (*EBSVolume, error) { - cloud := context.T.Cloud.(awsup.AWSCloud) +func (e *EBSVolume) Find(c *fi.CloudupContext) (*EBSVolume, error) { + ctx := c.Context() + cloud := c.T.Cloud.(awsup.AWSCloud) filters := cloud.BuildFilters(e.Name) request := &ec2.DescribeVolumesInput{ Filters: filters, } - response, err := cloud.EC2().DescribeVolumes(request) + response, err := cloud.EC2().DescribeVolumes(ctx, request) if err != nil { return nil, fmt.Errorf("error listing volumes: %v", err) } @@ -131,6 +134,7 @@ func (_ *EBSVolume) CheckChanges(a, e, changes *EBSVolume) error { } func (_ *EBSVolume) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *EBSVolume) error { + ctx := context.TODO() if a == nil { klog.V(2).Infof("Creating PersistentVolume with Name:%q", *e.Name) @@ -142,10 +146,10 @@ func (_ *EBSVolume) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *EBSVolume) e Encrypted: e.Encrypted, Iops: e.VolumeIops, Throughput: e.VolumeThroughput, - TagSpecifications: awsup.EC2TagSpecification(ec2.ResourceTypeVolume, e.Tags), + TagSpecifications: awsup.EC2TagSpecification(ec2types.ResourceTypeVolume, e.Tags), } - response, err := t.Cloud.EC2().CreateVolume(request) + response, err := t.Cloud.EC2().CreateVolume(ctx, request) if err != nil { return fmt.Errorf("error creating PersistentVolume: %v", err) } @@ -165,7 +169,7 @@ func (_ *EBSVolume) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *EBSVolume) e } } - if changes.VolumeType != nil || + if len(changes.VolumeType) > 0 || changes.VolumeIops != nil || changes.VolumeThroughput != nil || changes.SizeGB != nil { @@ -178,7 +182,7 @@ func (_ *EBSVolume) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *EBSVolume) e Size: e.SizeGB, } - _, err := t.Cloud.EC2().ModifyVolume(request) + _, err := t.Cloud.EC2().ModifyVolume(ctx, request) if err != nil { return fmt.Errorf("error modifying volume: %v", err) } @@ -201,14 +205,14 @@ func (e *EBSVolume) getEBSVolumeTagsToDelete(currentTags map[string]string) map[ } type terraformVolume struct { - AvailabilityZone *string `cty:"availability_zone"` - Size *int64 `cty:"size"` - Type *string `cty:"type"` - Iops *int64 `cty:"iops"` - Throughput *int64 `cty:"throughput"` - KmsKeyId *string `cty:"kms_key_id"` - Encrypted *bool `cty:"encrypted"` - Tags map[string]string `cty:"tags"` + AvailabilityZone *string `cty:"availability_zone"` + Size *int32 `cty:"size"` + Type ec2types.VolumeType `cty:"type"` + Iops *int32 `cty:"iops"` + Throughput *int32 `cty:"throughput"` + KmsKeyId *string `cty:"kms_key_id"` + Encrypted *bool `cty:"encrypted"` + Tags map[string]string `cty:"tags"` } func (_ *EBSVolume) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *EBSVolume) error { diff --git a/upup/pkg/fi/cloudup/awstasks/helper.go b/upup/pkg/fi/cloudup/awstasks/helper.go index c87ad86d2e..308b96d593 100644 --- a/upup/pkg/fi/cloudup/awstasks/helper.go +++ b/upup/pkg/fi/cloudup/awstasks/helper.go @@ -20,12 +20,13 @@ import ( "errors" "fmt" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "k8s.io/kops/upup/pkg/fi" "k8s.io/kops/upup/pkg/fi/cloudup/awsup" ) // buildEphemeralDevices looks up the machine type and discovery any ephemeral device mappings -func buildEphemeralDevices(cloud awsup.AWSCloud, machineType string) (map[string]*BlockDeviceMapping, error) { +func buildEphemeralDevices(cloud awsup.AWSCloud, machineType ec2types.InstanceType) (map[string]*BlockDeviceMapping, error) { if machineType == "" { return nil, nil } diff --git a/upup/pkg/fi/cloudup/awstasks/instance.go b/upup/pkg/fi/cloudup/awstasks/instance.go index 24fc32ff20..3178a7c43e 100644 --- a/upup/pkg/fi/cloudup/awstasks/instance.go +++ b/upup/pkg/fi/cloudup/awstasks/instance.go @@ -17,12 +17,14 @@ limitations under the License. package awstasks import ( + "context" "encoding/base64" "fmt" "strings" "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "k8s.io/klog/v2" "k8s.io/kops/upup/pkg/fi" "k8s.io/kops/upup/pkg/fi/cloudup/awsup" @@ -49,7 +51,7 @@ type Instance struct { Shared *bool ImageID *string - InstanceType *string + InstanceType ec2types.InstanceType SSHKey *SSHKey SecurityGroups []*SecurityGroup AssociatePublicIP *bool @@ -63,12 +65,13 @@ func (s *Instance) CompareWithID() *string { } func (e *Instance) Find(c *fi.CloudupContext) (*Instance, error) { + ctx := c.Context() cloud := c.T.Cloud.(awsup.AWSCloud) var request *ec2.DescribeInstancesInput if fi.ValueOf(e.Shared) { - var instanceIds []*string - instanceIds = append(instanceIds, e.ID) + var instanceIds []string + instanceIds = append(instanceIds, aws.ToString(e.ID)) request = &ec2.DescribeInstancesInput{ InstanceIds: instanceIds, } @@ -80,12 +83,12 @@ func (e *Instance) Find(c *fi.CloudupContext) (*Instance, error) { } } - response, err := cloud.EC2().DescribeInstances(request) + response, err := cloud.EC2().DescribeInstances(ctx, request) if err != nil { return nil, fmt.Errorf("error listing instances: %v", err) } - instances := []*ec2.Instance{} + instances := []ec2types.Instance{} if response != nil { for _, reservation := range response.Reservations { instances = append(instances, reservation.Instances...) @@ -119,8 +122,8 @@ func (e *Instance) Find(c *fi.CloudupContext) (*Instance, error) { { request := &ec2.DescribeInstanceAttributeInput{} request.InstanceId = i.InstanceId - request.Attribute = aws.String("userData") - response, err := cloud.EC2().DescribeInstanceAttribute(request) + request.Attribute = ec2types.InstanceAttributeNameUserData + response, err := cloud.EC2().DescribeInstanceAttribute(ctx, request) if err != nil { return nil, fmt.Errorf("error querying EC2 for user metadata for instance %q: %v", *i.InstanceId, err) } @@ -208,6 +211,7 @@ func (_ *Instance) CheckChanges(a, e, changes *Instance) error { } func (_ *Instance) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Instance) error { + ctx := context.TODO() if a == nil { if fi.ValueOf(e.Shared) { @@ -226,21 +230,21 @@ func (_ *Instance) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Instance) err request := &ec2.RunInstancesInput{ ImageId: image.ImageId, InstanceType: e.InstanceType, - MinCount: aws.Int64(1), - MaxCount: aws.Int64(1), + MinCount: aws.Int32(1), + MaxCount: aws.Int32(1), } if e.SSHKey != nil { request.KeyName = e.SSHKey.Name } - securityGroupIDs := []*string{} + securityGroupIDs := []string{} for _, sg := range e.SecurityGroups { - securityGroupIDs = append(securityGroupIDs, sg.ID) + securityGroupIDs = append(securityGroupIDs, fi.ValueOf(sg.ID)) } - request.NetworkInterfaces = []*ec2.InstanceNetworkInterfaceSpecification{ + request.NetworkInterfaces = []ec2types.InstanceNetworkInterfaceSpecification{ { - DeviceIndex: aws.Int64(0), + DeviceIndex: aws.Int32(0), AssociatePublicIpAddress: e.AssociatePublicIP, SubnetId: e.Subnet.ID, PrivateIpAddress: e.PrivateIPAddress, @@ -250,13 +254,13 @@ func (_ *Instance) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Instance) err // Build up the actual block device mappings // TODO: Support RootVolumeType & RootVolumeSize (see launchconfiguration) - blockDeviceMappings, err := buildEphemeralDevices(t.Cloud, fi.ValueOf(e.InstanceType)) + blockDeviceMappings, err := buildEphemeralDevices(t.Cloud, e.InstanceType) if err != nil { return err } if len(blockDeviceMappings) != 0 { - request.BlockDeviceMappings = []*ec2.BlockDeviceMapping{} + request.BlockDeviceMappings = []ec2types.BlockDeviceMapping{} for deviceName, bdm := range blockDeviceMappings { request.BlockDeviceMappings = append(request.BlockDeviceMappings, bdm.ToEC2(deviceName)) } @@ -280,12 +284,12 @@ func (_ *Instance) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Instance) err } if e.IAMInstanceProfile != nil { - request.IamInstanceProfile = &ec2.IamInstanceProfileSpecification{ + request.IamInstanceProfile = &ec2types.IamInstanceProfileSpecification{ Name: e.IAMInstanceProfile.Name, } } - response, err := t.Cloud.EC2().RunInstances(request) + response, err := t.Cloud.EC2().RunInstances(ctx, request) if err != nil { return fmt.Errorf("error creating Instance: %v", err) } diff --git a/upup/pkg/fi/cloudup/awstasks/launchtemplate.go b/upup/pkg/fi/cloudup/awstasks/launchtemplate.go index 60863795ce..6e751c0bb3 100644 --- a/upup/pkg/fi/cloudup/awstasks/launchtemplate.go +++ b/upup/pkg/fi/cloudup/awstasks/launchtemplate.go @@ -21,6 +21,7 @@ import ( "sort" "github.com/aws/aws-sdk-go-v2/aws" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "k8s.io/kops/upup/pkg/fi" "k8s.io/kops/upup/pkg/fi/cloudup/awsup" ) @@ -42,34 +43,34 @@ type LaunchTemplate struct { // CPUCredits is the credit option for CPU Usage on some instance types CPUCredits *string // HTTPPutResponseHopLimit is the desired HTTP PUT response hop limit for instance metadata requests. - HTTPPutResponseHopLimit *int64 + HTTPPutResponseHopLimit *int32 // HTTPTokens is the state of token usage for your instance metadata requests. - HTTPTokens *string + HTTPTokens *ec2types.LaunchTemplateHttpTokensState // HTTPProtocolIPv6 enables the IPv6 instance metadata endpoint - HTTPProtocolIPv6 *string + HTTPProtocolIPv6 *ec2types.LaunchTemplateInstanceMetadataProtocolIpv6 // IAMInstanceProfile is the IAM profile to assign to the nodes IAMInstanceProfile *IAMInstanceProfile // ImageID is the AMI to use for the instances ImageID *string // InstanceInterruptionBehavior defines if a spot instance should be terminated, hibernated, // or stopped after interruption - InstanceInterruptionBehavior *string + InstanceInterruptionBehavior *ec2types.InstanceInterruptionBehavior // InstanceMonitoring indicates if monitoring is enabled InstanceMonitoring *bool // InstanceType is the type of instance we are using - InstanceType *string + InstanceType *ec2types.InstanceType // Ipv6AddressCount is the number of IPv6 addresses to assign with the primary network interface. - IPv6AddressCount *int64 + IPv6AddressCount *int32 // RootVolumeIops is the provisioned IOPS when the volume type is io1, io2 or gp3 - RootVolumeIops *int64 + RootVolumeIops *int32 // RootVolumeOptimization enables EBS optimization for an instance RootVolumeOptimization *bool // RootVolumeSize is the size of the EBS root volume to use, in GB - RootVolumeSize *int64 + RootVolumeSize *int32 // RootVolumeThroughput is the volume throughput in MBps when the volume type is gp3 - RootVolumeThroughput *int64 + RootVolumeThroughput *int32 // RootVolumeType is the type of the EBS root volume to use (e.g. gp2) - RootVolumeType *string + RootVolumeType ec2types.VolumeType // RootVolumeEncryption enables EBS root volume encryption for an instance RootVolumeEncryption *bool // RootVolumeKmsKey is the encryption key identifier for EBS root volume encryption @@ -81,11 +82,11 @@ type LaunchTemplate struct { // SpotPrice is set to the spot-price bid if this is a spot pricing request SpotPrice *string // SpotDurationInMinutes is set for requesting spot blocks - SpotDurationInMinutes *int64 + SpotDurationInMinutes *int32 // Tags are the keypairs to apply to the instance and volume on launch as well as the launch template itself. Tags map[string]string // Tenancy. Can be either default or dedicated. - Tenancy *string + Tenancy *ec2types.Tenancy // UserData is the user data configuration UserData fi.Resource } @@ -171,7 +172,7 @@ func (t *LaunchTemplate) FindDeletions(c *fi.CloudupContext) ([]fi.CloudupDeleti for _, lt := range list { if aws.ToString(lt.LaunchTemplateName) != aws.ToString(t.Name) { - removals = append(removals, &deleteLaunchTemplate{lc: lt}) + removals = append(removals, &deleteLaunchTemplate{lc: fi.PtrTo(lt)}) } } diff --git a/upup/pkg/fi/cloudup/awstasks/launchtemplate_target_api.go b/upup/pkg/fi/cloudup/awstasks/launchtemplate_target_api.go index 15bcd8556e..c8ed878752 100644 --- a/upup/pkg/fi/cloudup/awstasks/launchtemplate_target_api.go +++ b/upup/pkg/fi/cloudup/awstasks/launchtemplate_target_api.go @@ -17,13 +17,15 @@ limitations under the License. package awstasks import ( + "context" "encoding/base64" "fmt" "sort" "strconv" "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "k8s.io/klog/v2" "k8s.io/kops/upup/pkg/fi" @@ -32,6 +34,7 @@ import ( // RenderAWS is responsible for performing creating / updating the launch template func (t *LaunchTemplate) RenderAWS(c *awsup.AWSAPITarget, a, e, changes *LaunchTemplate) error { + ctx := context.TODO() // @step: resolve the image id to an AMI for us image, err := c.Cloud.ResolveImage(fi.ValueOf(t.ImageID)) if err != nil { @@ -39,21 +42,21 @@ func (t *LaunchTemplate) RenderAWS(c *awsup.AWSAPITarget, a, e, changes *LaunchT } // @step: lets build the launch template data - data := &ec2.RequestLaunchTemplateData{ + data := &ec2types.RequestLaunchTemplateData{ DisableApiTermination: fi.PtrTo(false), EbsOptimized: t.RootVolumeOptimization, ImageId: image.ImageId, - InstanceType: t.InstanceType, - MetadataOptions: &ec2.LaunchTemplateInstanceMetadataOptionsRequest{ + InstanceType: fi.ValueOf(t.InstanceType), + MetadataOptions: &ec2types.LaunchTemplateInstanceMetadataOptionsRequest{ HttpPutResponseHopLimit: t.HTTPPutResponseHopLimit, - HttpTokens: t.HTTPTokens, - HttpProtocolIpv6: t.HTTPProtocolIPv6, + HttpTokens: fi.ValueOf(t.HTTPTokens), + HttpProtocolIpv6: fi.ValueOf(t.HTTPProtocolIPv6), }, - NetworkInterfaces: []*ec2.LaunchTemplateInstanceNetworkInterfaceSpecificationRequest{ + NetworkInterfaces: []ec2types.LaunchTemplateInstanceNetworkInterfaceSpecificationRequest{ { AssociatePublicIpAddress: t.AssociatePublicIP, DeleteOnTermination: aws.Bool(true), - DeviceIndex: fi.PtrTo(int64(0)), + DeviceIndex: fi.PtrTo(int32(0)), Ipv6AddressCount: t.IPv6AddressCount, }, }, @@ -84,38 +87,38 @@ func (t *LaunchTemplate) RenderAWS(c *awsup.AWSAPITarget, a, e, changes *LaunchT } // @step: add the security groups for _, sg := range t.SecurityGroups { - data.NetworkInterfaces[0].Groups = append(data.NetworkInterfaces[0].Groups, sg.ID) + data.NetworkInterfaces[0].Groups = append(data.NetworkInterfaces[0].Groups, fi.ValueOf(sg.ID)) } // @step: add any tenancy details if t.Tenancy != nil { - data.Placement = &ec2.LaunchTemplatePlacementRequest{Tenancy: t.Tenancy} + data.Placement = &ec2types.LaunchTemplatePlacementRequest{Tenancy: fi.ValueOf(t.Tenancy)} } // @step: set the instance monitoring - data.Monitoring = &ec2.LaunchTemplatesMonitoringRequest{Enabled: fi.PtrTo(false)} + data.Monitoring = &ec2types.LaunchTemplatesMonitoringRequest{Enabled: fi.PtrTo(false)} if t.InstanceMonitoring != nil { - data.Monitoring = &ec2.LaunchTemplatesMonitoringRequest{Enabled: t.InstanceMonitoring} + data.Monitoring = &ec2types.LaunchTemplatesMonitoringRequest{Enabled: t.InstanceMonitoring} } // @step: add the iam instance profile if t.IAMInstanceProfile != nil { - data.IamInstanceProfile = &ec2.LaunchTemplateIamInstanceProfileSpecificationRequest{ + data.IamInstanceProfile = &ec2types.LaunchTemplateIamInstanceProfileSpecificationRequest{ Name: t.IAMInstanceProfile.Name, } } // @step: add the tags - var tags []*ec2.Tag + var tags []ec2types.Tag if len(t.Tags) > 0 { for k, v := range t.Tags { - tags = append(tags, &ec2.Tag{ + tags = append(tags, ec2types.Tag{ Key: aws.String(k), Value: aws.String(v), }) } - data.TagSpecifications = append(data.TagSpecifications, &ec2.LaunchTemplateTagSpecificationRequest{ - ResourceType: aws.String(ec2.ResourceTypeInstance), + data.TagSpecifications = append(data.TagSpecifications, ec2types.LaunchTemplateTagSpecificationRequest{ + ResourceType: ec2types.ResourceTypeInstance, Tags: tags, }) - data.TagSpecifications = append(data.TagSpecifications, &ec2.LaunchTemplateTagSpecificationRequest{ - ResourceType: aws.String(ec2.ResourceTypeVolume), + data.TagSpecifications = append(data.TagSpecifications, ec2types.LaunchTemplateTagSpecificationRequest{ + ResourceType: ec2types.ResourceTypeVolume, Tags: tags, }) } @@ -129,18 +132,20 @@ func (t *LaunchTemplate) RenderAWS(c *awsup.AWSAPITarget, a, e, changes *LaunchT } // @step: add market options if fi.ValueOf(t.SpotPrice) != "" { - s := &ec2.LaunchTemplateSpotMarketOptionsRequest{ - BlockDurationMinutes: t.SpotDurationInMinutes, - InstanceInterruptionBehavior: t.InstanceInterruptionBehavior, - MaxPrice: t.SpotPrice, + s := &ec2types.LaunchTemplateSpotMarketOptionsRequest{ + BlockDurationMinutes: t.SpotDurationInMinutes, + MaxPrice: t.SpotPrice, } - data.InstanceMarketOptions = &ec2.LaunchTemplateInstanceMarketOptionsRequest{ - MarketType: fi.PtrTo("spot"), + if t.InstanceInterruptionBehavior != nil { + s.InstanceInterruptionBehavior = fi.ValueOf(t.InstanceInterruptionBehavior) + } + data.InstanceMarketOptions = &ec2types.LaunchTemplateInstanceMarketOptionsRequest{ + MarketType: ec2types.MarketTypeSpot, SpotOptions: s, } } if fi.ValueOf(t.CPUCredits) != "" { - data.CreditSpecification = &ec2.CreditSpecificationRequest{ + data.CreditSpecification = &ec2types.CreditSpecificationRequest{ CpuCredits: t.CPUCredits, } } @@ -149,14 +154,14 @@ func (t *LaunchTemplate) RenderAWS(c *awsup.AWSAPITarget, a, e, changes *LaunchT input := &ec2.CreateLaunchTemplateInput{ LaunchTemplateName: t.Name, LaunchTemplateData: data, - TagSpecifications: []*ec2.TagSpecification{ + TagSpecifications: []ec2types.TagSpecification{ { - ResourceType: aws.String(ec2.ResourceTypeLaunchTemplate), + ResourceType: ec2types.ResourceTypeLaunchTemplate, Tags: tags, }, }, } - output, err := c.Cloud.EC2().CreateLaunchTemplate(input) + output, err := c.Cloud.EC2().CreateLaunchTemplate(ctx, input) if err != nil || output.LaunchTemplate == nil { return fmt.Errorf("error creating LaunchTemplate %q: %v", fi.ValueOf(t.Name), err) } @@ -166,7 +171,7 @@ func (t *LaunchTemplate) RenderAWS(c *awsup.AWSAPITarget, a, e, changes *LaunchT LaunchTemplateName: t.Name, LaunchTemplateData: data, } - if version, err := c.Cloud.EC2().CreateLaunchTemplateVersion(input); err != nil { + if version, err := c.Cloud.EC2().CreateLaunchTemplateVersion(ctx, input); err != nil { return fmt.Errorf("error creating LaunchTemplateVersion: %v", err) } else { newDefault := strconv.FormatInt(*version.LaunchTemplateVersion.VersionNumber, 10) @@ -174,7 +179,7 @@ func (t *LaunchTemplate) RenderAWS(c *awsup.AWSAPITarget, a, e, changes *LaunchT DefaultVersion: &newDefault, LaunchTemplateId: version.LaunchTemplateVersion.LaunchTemplateId, } - if _, err := c.Cloud.EC2().ModifyLaunchTemplate(input); err != nil { + if _, err := c.Cloud.EC2().ModifyLaunchTemplate(ctx, input); err != nil { return fmt.Errorf("error updating launch template version: %w", err) } } @@ -214,11 +219,13 @@ func (t *LaunchTemplate) Find(c *fi.CloudupContext) (*LaunchTemplate, error) { ID: lt.LaunchTemplateId, ImageID: lt.LaunchTemplateData.ImageId, InstanceMonitoring: fi.PtrTo(false), - InstanceType: lt.LaunchTemplateData.InstanceType, Lifecycle: t.Lifecycle, Name: t.Name, RootVolumeOptimization: lt.LaunchTemplateData.EbsOptimized, } + if len(lt.LaunchTemplateData.InstanceType) > 0 { + actual.InstanceType = fi.PtrTo(lt.LaunchTemplateData.InstanceType) + } // @step: check if any of the interfaces are public facing for _, x := range lt.LaunchTemplateData.NetworkInterfaces { @@ -226,13 +233,13 @@ func (t *LaunchTemplate) Find(c *fi.CloudupContext) (*LaunchTemplate, error) { actual.AssociatePublicIP = fi.PtrTo(true) } for _, id := range x.Groups { - actual.SecurityGroups = append(actual.SecurityGroups, &SecurityGroup{ID: id}) + actual.SecurityGroups = append(actual.SecurityGroups, &SecurityGroup{ID: fi.PtrTo(id)}) } actual.IPv6AddressCount = x.Ipv6AddressCount } // In older Kops versions, security groups were added to LaunchTemplateData.SecurityGroupIds for _, id := range lt.LaunchTemplateData.SecurityGroupIds { - actual.SecurityGroups = append(actual.SecurityGroups, &SecurityGroup{ID: fi.PtrTo("legacy-" + *id)}) + actual.SecurityGroups = append(actual.SecurityGroups, &SecurityGroup{ID: fi.PtrTo("legacy-" + id)}) } sort.Sort(OrderSecurityGroupsById(actual.SecurityGroups)) @@ -246,8 +253,8 @@ func (t *LaunchTemplate) Find(c *fi.CloudupContext) (*LaunchTemplate, error) { actual.InstanceMonitoring = lt.LaunchTemplateData.Monitoring.Enabled } // @step: add the tenancy - if lt.LaunchTemplateData.Placement != nil { - actual.Tenancy = lt.LaunchTemplateData.Placement.Tenancy + if lt.LaunchTemplateData.Placement != nil && len(lt.LaunchTemplateData.Placement.Tenancy) > 0 { + actual.Tenancy = fi.PtrTo(lt.LaunchTemplateData.Placement.Tenancy) } // @step: add the ssh if there is one if lt.LaunchTemplateData.KeyName != nil { @@ -262,7 +269,9 @@ func (t *LaunchTemplate) Find(c *fi.CloudupContext) (*LaunchTemplate, error) { if imo != nil && imo.SpotOptions != nil && aws.ToString(imo.SpotOptions.MaxPrice) != "" { actual.SpotPrice = imo.SpotOptions.MaxPrice actual.SpotDurationInMinutes = imo.SpotOptions.BlockDurationMinutes - actual.InstanceInterruptionBehavior = imo.SpotOptions.InstanceInterruptionBehavior + if len(imo.SpotOptions.InstanceInterruptionBehavior) > 0 { + actual.InstanceInterruptionBehavior = fi.PtrTo(imo.SpotOptions.InstanceInterruptionBehavior) + } } else { actual.SpotPrice = aws.String("") } @@ -316,8 +325,12 @@ func (t *LaunchTemplate) Find(c *fi.CloudupContext) (*LaunchTemplate, error) { // @step: add instance metadata options if options := lt.LaunchTemplateData.MetadataOptions; options != nil { actual.HTTPPutResponseHopLimit = options.HttpPutResponseHopLimit - actual.HTTPTokens = options.HttpTokens - actual.HTTPProtocolIPv6 = options.HttpProtocolIpv6 + if len(options.HttpTokens) > 0 { + actual.HTTPTokens = fi.PtrTo(options.HttpTokens) + } + if len(options.HttpProtocolIpv6) > 0 { + actual.HTTPProtocolIPv6 = fi.PtrTo(options.HttpProtocolIpv6) + } } // @step: to avoid spurious changes on ImageId @@ -341,7 +354,7 @@ func (t *LaunchTemplate) Find(c *fi.CloudupContext) (*LaunchTemplate, error) { } // findAllLaunchTemplates returns all the launch templates for us -func (t *LaunchTemplate) findAllLaunchTemplates(c *fi.CloudupContext) ([]*ec2.LaunchTemplate, error) { +func (t *LaunchTemplate) findAllLaunchTemplates(c *fi.CloudupContext) ([]ec2types.LaunchTemplate, error) { ctx := c.Context() cloud, ok := c.T.Cloud.(awsup.AWSCloud) @@ -350,28 +363,29 @@ func (t *LaunchTemplate) findAllLaunchTemplates(c *fi.CloudupContext) ([]*ec2.La } input := &ec2.DescribeLaunchTemplatesInput{ - Filters: []*ec2.Filter{ + Filters: []ec2types.Filter{ { Name: aws.String("tag:Name"), - Values: []*string{t.Name}, + Values: []string{fi.ValueOf(t.Name)}, }, }, } - var list []*ec2.LaunchTemplate - err := cloud.EC2().DescribeLaunchTemplatesPagesWithContext(ctx, input, func(p *ec2.DescribeLaunchTemplatesOutput, lastPage bool) (shouldContinue bool) { - list = append(list, p.LaunchTemplates...) - return true - }) - if err != nil { - return nil, fmt.Errorf("error listing AutoScaling LaunchTemplates: %v", err) + var list []ec2types.LaunchTemplate + paginator := ec2.NewDescribeLaunchTemplatesPaginator(cloud.EC2(), input) + for paginator.HasMorePages() { + page, err := paginator.NextPage(ctx) + if err != nil { + return nil, fmt.Errorf("error listing AutoScaling LaunchTemplates: %v", err) + } + list = append(list, page.LaunchTemplates...) } return list, nil } // findLatestLaunchTemplateVersion returns the latest template version -func (t *LaunchTemplate) findLatestLaunchTemplateVersion(c *fi.CloudupContext) (*ec2.LaunchTemplateVersion, error) { +func (t *LaunchTemplate) findLatestLaunchTemplateVersion(c *fi.CloudupContext) (*ec2types.LaunchTemplateVersion, error) { ctx := c.Context() cloud, ok := c.T.Cloud.(awsup.AWSCloud) @@ -381,10 +395,10 @@ func (t *LaunchTemplate) findLatestLaunchTemplateVersion(c *fi.CloudupContext) ( input := &ec2.DescribeLaunchTemplateVersionsInput{ LaunchTemplateName: t.Name, - Versions: []*string{aws.String("$Latest")}, + Versions: []string{("$Latest")}, } - output, err := cloud.EC2().DescribeLaunchTemplateVersionsWithContext(ctx, input) + output, err := cloud.EC2().DescribeLaunchTemplateVersions(ctx, input) if err != nil { if awsup.AWSErrorCode(err) == "InvalidLaunchTemplateName.NotFoundException" { klog.V(4).Infof("Got InvalidLaunchTemplateName.NotFoundException error describing latest launch template version: %q", aws.ToString(t.Name)) @@ -398,13 +412,13 @@ func (t *LaunchTemplate) findLatestLaunchTemplateVersion(c *fi.CloudupContext) ( return nil, nil } - return output.LaunchTemplateVersions[0], nil + return &output.LaunchTemplateVersions[0], nil } // deleteLaunchTemplate tracks a LaunchConfiguration that we're going to delete // It implements fi.CloudupDeletion type deleteLaunchTemplate struct { - lc *ec2.LaunchTemplate + lc *ec2types.LaunchTemplate } var _ fi.CloudupDeletion = &deleteLaunchTemplate{} @@ -420,12 +434,13 @@ func (d *deleteLaunchTemplate) Item() string { } func (d *deleteLaunchTemplate) Delete(t fi.CloudupTarget) error { + ctx := context.TODO() awsTarget, ok := t.(*awsup.AWSAPITarget) if !ok { return fmt.Errorf("unexpected target type for deletion: %T", t) } - if _, err := awsTarget.Cloud.EC2().DeleteLaunchTemplate(&ec2.DeleteLaunchTemplateInput{ + if _, err := awsTarget.Cloud.EC2().DeleteLaunchTemplate(ctx, &ec2.DeleteLaunchTemplateInput{ LaunchTemplateName: d.lc.LaunchTemplateName, }); err != nil { return fmt.Errorf("error deleting LaunchTemplate %s: error: %s", d.Item(), err) diff --git a/upup/pkg/fi/cloudup/awstasks/launchtemplate_target_terraform.go b/upup/pkg/fi/cloudup/awstasks/launchtemplate_target_terraform.go index a446c44f6a..d8786b8706 100644 --- a/upup/pkg/fi/cloudup/awstasks/launchtemplate_target_terraform.go +++ b/upup/pkg/fi/cloudup/awstasks/launchtemplate_target_terraform.go @@ -17,6 +17,7 @@ limitations under the License. package awstasks import ( + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "k8s.io/kops/upup/pkg/fi" "k8s.io/kops/upup/pkg/fi/cloudup/awsup" "k8s.io/kops/upup/pkg/fi/cloudup/terraform" @@ -29,7 +30,7 @@ type terraformLaunchTemplateNetworkInterface struct { // DeleteOnTermination indicates whether the network interface should be destroyed on instance termination. DeleteOnTermination *bool `cty:"delete_on_termination"` // Ipv6AddressCount is the number of IPv6 addresses to assign with the primary network interface. - Ipv6AddressCount *int64 `cty:"ipv6_address_count"` + Ipv6AddressCount *int32 `cty:"ipv6_address_count"` // SecurityGroups is a list of security group ids. SecurityGroups []*terraformWriter.Literal `cty:"security_groups"` } @@ -51,7 +52,7 @@ type terraformLaunchTemplatePlacement struct { // SpreadDomain are reserved for future use. SpreadDomain *string `cty:"spread_domain"` // Tenancy ist he tenancy of the instance. Can be default, dedicated, or host. - Tenancy *string `cty:"tenancy"` + Tenancy *ec2types.Tenancy `cty:"tenancy"` } type terraformLaunchTemplateIAMProfile struct { @@ -61,9 +62,9 @@ type terraformLaunchTemplateIAMProfile struct { type terraformLaunchTemplateMarketOptionsSpotOptions struct { // BlockDurationMinutes is required duration in minutes. This value must be a multiple of 60. - BlockDurationMinutes *int64 `cty:"block_duration_minutes"` + BlockDurationMinutes *int32 `cty:"block_duration_minutes"` // InstanceInterruptionBehavior is the behavior when a Spot Instance is interrupted. Can be hibernate, stop, or terminate - InstanceInterruptionBehavior *string `cty:"instance_interruption_behavior"` + InstanceInterruptionBehavior *ec2types.InstanceInterruptionBehavior `cty:"instance_interruption_behavior"` // MaxPrice is the maximum hourly price you're willing to pay for the Spot Instances MaxPrice *string `cty:"max_price"` // SpotInstanceType is the Spot Instance request type. Can be one-time, or persistent @@ -83,11 +84,11 @@ type terraformLaunchTemplateBlockDeviceEBS struct { // VolumeType is the ebs type to use VolumeType *string `cty:"volume_type"` // VolumeSize is the volume size - VolumeSize *int64 `cty:"volume_size"` + VolumeSize *int32 `cty:"volume_size"` // IOPS is the provisioned IOPS - IOPS *int64 `cty:"iops"` + IOPS *int32 `cty:"iops"` // Throughput is the gp3 volume throughput - Throughput *int64 `cty:"throughput"` + Throughput *int32 `cty:"throughput"` // DeleteOnTermination indicates the volume should die with the instance DeleteOnTermination *bool `cty:"delete_on_termination"` // Encrypted indicates the device should be encrypted @@ -120,11 +121,11 @@ type terraformLaunchTemplateInstanceMetadata struct { // HTTPEndpoint enables or disables the HTTP metadata endpoint on instances. HTTPEndpoint *string `cty:"http_endpoint"` // HTTPPutResponseHopLimit is the desired HTTP PUT response hop limit for instance metadata requests. - HTTPPutResponseHopLimit *int64 `cty:"http_put_response_hop_limit"` + HTTPPutResponseHopLimit *int32 `cty:"http_put_response_hop_limit"` // HTTPTokens is the state of token usage for your instance metadata requests. - HTTPTokens *string `cty:"http_tokens"` + HTTPTokens *ec2types.LaunchTemplateHttpTokensState `cty:"http_tokens"` // HTTPProtocolIPv6 enables the IPv6 instance metadata endpoint - HTTPProtocolIPv6 *string `cty:"http_protocol_ipv6"` + HTTPProtocolIPv6 *ec2types.LaunchTemplateInstanceMetadataProtocolIpv6 `cty:"http_protocol_ipv6"` } type terraformLaunchTemplate struct { @@ -144,7 +145,7 @@ type terraformLaunchTemplate struct { // ImageID is the ami to use for the instances ImageID *string `cty:"image_id"` // InstanceType is the type of instance - InstanceType *string `cty:"instance_type"` + InstanceType *ec2types.InstanceType `cty:"instance_type"` // KeyName is the ssh key to use KeyName *terraformWriter.Literal `cty:"key_name"` // MarketOptions are the spot pricing options @@ -213,12 +214,10 @@ func (t *LaunchTemplate) RenderTerraform(target *terraform.TerraformTarget, a, e } if fi.ValueOf(e.SpotPrice) != "" { - marketSpotOptions := terraformLaunchTemplateMarketOptionsSpotOptions{MaxPrice: e.SpotPrice} - if e.SpotDurationInMinutes != nil { - marketSpotOptions.BlockDurationMinutes = e.SpotDurationInMinutes - } - if e.InstanceInterruptionBehavior != nil { - marketSpotOptions.InstanceInterruptionBehavior = e.InstanceInterruptionBehavior + marketSpotOptions := terraformLaunchTemplateMarketOptionsSpotOptions{ + BlockDurationMinutes: e.SpotDurationInMinutes, + InstanceInterruptionBehavior: e.InstanceInterruptionBehavior, + MaxPrice: e.SpotPrice, } tf.MarketOptions = []*terraformLaunchTemplateMarketOptions{ { @@ -278,7 +277,7 @@ func (t *LaunchTemplate) RenderTerraform(target *terraform.TerraformTarget, a, e IOPS: x.EbsVolumeIops, Throughput: x.EbsVolumeThroughput, VolumeSize: x.EbsVolumeSize, - VolumeType: x.EbsVolumeType, + VolumeType: fi.PtrTo(string(x.EbsVolumeType)), }, }, }) @@ -298,7 +297,7 @@ func (t *LaunchTemplate) RenderTerraform(target *terraform.TerraformTarget, a, e Throughput: x.EbsVolumeThroughput, KmsKeyID: x.EbsKmsKey, VolumeSize: x.EbsVolumeSize, - VolumeType: x.EbsVolumeType, + VolumeType: fi.PtrTo(string(x.EbsVolumeType)), }, }, }) diff --git a/upup/pkg/fi/cloudup/awstasks/launchtemplate_target_terraform_test.go b/upup/pkg/fi/cloudup/awstasks/launchtemplate_target_terraform_test.go index 35fec3f9c7..8a3033df79 100644 --- a/upup/pkg/fi/cloudup/awstasks/launchtemplate_target_terraform_test.go +++ b/upup/pkg/fi/cloudup/awstasks/launchtemplate_target_terraform_test.go @@ -19,6 +19,8 @@ package awstasks import ( "testing" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "k8s.io/kops/upup/pkg/fi" ) @@ -33,13 +35,13 @@ func TestLaunchTemplateTerraformRender(t *testing.T) { }, ID: fi.PtrTo("test-11"), InstanceMonitoring: fi.PtrTo(true), - InstanceType: fi.PtrTo("t2.medium"), + InstanceType: fi.PtrTo(ec2types.InstanceTypeT2Medium), SpotPrice: fi.PtrTo("0.1"), - SpotDurationInMinutes: fi.PtrTo(int64(60)), - InstanceInterruptionBehavior: fi.PtrTo("hibernate"), + SpotDurationInMinutes: fi.PtrTo(int32(60)), + InstanceInterruptionBehavior: fi.PtrTo(ec2types.InstanceInterruptionBehaviorHibernate), RootVolumeOptimization: fi.PtrTo(true), - RootVolumeIops: fi.PtrTo(int64(100)), - RootVolumeSize: fi.PtrTo(int64(64)), + RootVolumeIops: fi.PtrTo(int32(100)), + RootVolumeSize: fi.PtrTo(int32(64)), SSHKey: &SSHKey{ Name: fi.PtrTo("newkey"), PublicKey: fi.NewStringResource("newkey"), @@ -48,9 +50,9 @@ func TestLaunchTemplateTerraformRender(t *testing.T) { {Name: fi.PtrTo("nodes-1"), ID: fi.PtrTo("1111")}, {Name: fi.PtrTo("nodes-2"), ID: fi.PtrTo("2222")}, }, - Tenancy: fi.PtrTo("dedicated"), - HTTPTokens: fi.PtrTo("optional"), - HTTPPutResponseHopLimit: fi.PtrTo(int64(1)), + Tenancy: fi.PtrTo(ec2types.TenancyDedicated), + HTTPTokens: fi.PtrTo(ec2types.LaunchTemplateHttpTokensStateOptional), + HTTPPutResponseHopLimit: fi.PtrTo(int32(1)), }, Expected: `provider "aws" { region = "eu-west-2" @@ -114,18 +116,18 @@ terraform { BlockDeviceMappings: []*BlockDeviceMapping{ { DeviceName: fi.PtrTo("/dev/xvdd"), - EbsVolumeType: fi.PtrTo("gp2"), - EbsVolumeSize: fi.PtrTo(int64(100)), + EbsVolumeType: ec2types.VolumeTypeGp2, + EbsVolumeSize: fi.PtrTo(int32(100)), EbsDeleteOnTermination: fi.PtrTo(true), EbsEncrypted: fi.PtrTo(true), }, }, ID: fi.PtrTo("test-11"), InstanceMonitoring: fi.PtrTo(true), - InstanceType: fi.PtrTo("t2.medium"), + InstanceType: fi.PtrTo(ec2types.InstanceTypeT2Medium), RootVolumeOptimization: fi.PtrTo(true), - RootVolumeIops: fi.PtrTo(int64(100)), - RootVolumeSize: fi.PtrTo(int64(64)), + RootVolumeIops: fi.PtrTo(int32(100)), + RootVolumeSize: fi.PtrTo(int32(64)), SSHKey: &SSHKey{ Name: fi.PtrTo("mykey"), }, @@ -133,9 +135,9 @@ terraform { {Name: fi.PtrTo("nodes-1"), ID: fi.PtrTo("1111")}, {Name: fi.PtrTo("nodes-2"), ID: fi.PtrTo("2222")}, }, - Tenancy: fi.PtrTo("dedicated"), - HTTPTokens: fi.PtrTo("required"), - HTTPPutResponseHopLimit: fi.PtrTo(int64(5)), + Tenancy: fi.PtrTo(ec2types.TenancyDedicated), + HTTPTokens: fi.PtrTo(ec2types.LaunchTemplateHttpTokensStateRequired), + HTTPPutResponseHopLimit: fi.PtrTo(int32(5)), }, Expected: `provider "aws" { region = "eu-west-2" diff --git a/upup/pkg/fi/cloudup/awstasks/sshkey.go b/upup/pkg/fi/cloudup/awstasks/sshkey.go index 13c7eecf23..5f5ff733ca 100644 --- a/upup/pkg/fi/cloudup/awstasks/sshkey.go +++ b/upup/pkg/fi/cloudup/awstasks/sshkey.go @@ -17,11 +17,12 @@ limitations under the License. package awstasks import ( + "context" "fmt" "strings" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "k8s.io/klog/v2" "k8s.io/kops/upup/pkg/fi/cloudup/terraformWriter" @@ -55,21 +56,16 @@ func (e *SSHKey) CompareWithID() *string { func (e *SSHKey) Find(c *fi.CloudupContext) (*SSHKey, error) { cloud := c.T.Cloud.(awsup.AWSCloud) - return e.find(cloud) + return e.find(c.Context(), cloud) } -func (e *SSHKey) find(cloud awsup.AWSCloud) (*SSHKey, error) { +func (e *SSHKey) find(ctx context.Context, cloud awsup.AWSCloud) (*SSHKey, error) { request := &ec2.DescribeKeyPairsInput{ - KeyNames: []*string{e.Name}, + KeyNames: []string{fi.ValueOf(e.Name)}, } - response, err := cloud.EC2().DescribeKeyPairs(request) - if awsErr, ok := err.(awserr.Error); ok { - if awsErr.Code() == "InvalidKeyPair.NotFound" { - err = nil - } - } - if err != nil { + response, err := cloud.EC2().DescribeKeyPairs(ctx, request) + if err != nil && awsup.AWSErrorCode(err) != "InvalidKeyPair.NotFound" { return nil, fmt.Errorf("error listing SSHKeys: %v", err) } @@ -94,7 +90,7 @@ func (e *SSHKey) find(cloud awsup.AWSCloud) (*SSHKey, error) { } // Avoid spurious changes - if fi.ValueOf(k.KeyType) == ec2.KeyTypeEd25519 { + if k.KeyType == ec2types.KeyTypeEd25519 { // Trim the trailing "=" and prefix with "SHA256:" to match the output of "ssh-keygen -lf" fingerprint := fi.ValueOf(k.KeyFingerprint) fingerprint = strings.TrimRight(fingerprint, "=") @@ -152,11 +148,12 @@ func (s *SSHKey) CheckChanges(a, e, changes *SSHKey) error { } func (e *SSHKey) createKeypair(cloud awsup.AWSCloud) error { + ctx := context.TODO() klog.V(2).Infof("Creating SSHKey with Name:%q", *e.Name) request := &ec2.ImportKeyPairInput{ KeyName: e.Name, - TagSpecifications: awsup.EC2TagSpecification(ec2.ResourceTypeKeyPair, e.Tags), + TagSpecifications: awsup.EC2TagSpecification(ec2types.ResourceTypeKeyPair, e.Tags), } if e.PublicKey != nil { @@ -167,7 +164,7 @@ func (e *SSHKey) createKeypair(cloud awsup.AWSCloud) error { request.PublicKeyMaterial = d } - response, err := cloud.EC2().ImportKeyPair(request) + response, err := cloud.EC2().ImportKeyPair(ctx, request) if err != nil { return fmt.Errorf("error creating SSHKey: %v", err) } diff --git a/upup/pkg/fi/cloudup/awstasks/tags.go b/upup/pkg/fi/cloudup/awstasks/tags.go index 67b0e91e3e..4b9eb87209 100644 --- a/upup/pkg/fi/cloudup/awstasks/tags.go +++ b/upup/pkg/fi/cloudup/awstasks/tags.go @@ -20,12 +20,12 @@ import ( "strings" "github.com/aws/aws-sdk-go-v2/aws" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" eventbridgetypes "github.com/aws/aws-sdk-go-v2/service/eventbridge/types" iamtypes "github.com/aws/aws-sdk-go-v2/service/iam/types" - "github.com/aws/aws-sdk-go/service/ec2" ) -func mapEC2TagsToMap(tags []*ec2.Tag) map[string]string { +func mapEC2TagsToMap(tags []ec2types.Tag) map[string]string { if tags == nil { return nil } @@ -81,7 +81,7 @@ func mapEventBridgeTagsToMap(tags []eventbridgetypes.Tag) map[string]string { return m } -func findNameTag(tags []*ec2.Tag) *string { +func findNameTag(tags []ec2types.Tag) *string { for _, tag := range tags { if aws.ToString(tag.Key) == "Name" { return tag.Value @@ -92,7 +92,7 @@ func findNameTag(tags []*ec2.Tag) *string { // intersectTags returns the tags of interest from a specified list of AWS tags; // because we only add tags, this set of tags of interest is the tags that occur in the desired set. -func intersectTags(tags []*ec2.Tag, desired map[string]string) map[string]string { +func intersectTags(tags []ec2types.Tag, desired map[string]string) map[string]string { if tags == nil { return nil } diff --git a/upup/pkg/fi/cloudup/spotinsttasks/elastigroup.go b/upup/pkg/fi/cloudup/spotinsttasks/elastigroup.go index df74e1441f..2365885e32 100644 --- a/upup/pkg/fi/cloudup/spotinsttasks/elastigroup.go +++ b/upup/pkg/fi/cloudup/spotinsttasks/elastigroup.go @@ -24,7 +24,7 @@ import ( "strings" "time" - "github.com/aws/aws-sdk-go/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/spotinst/spotinst-sdk-go/service/elastigroup/providers/aws" "github.com/spotinst/spotinst-sdk-go/spotinst/client" "github.com/spotinst/spotinst-sdk-go/spotinst/util/stringutil" @@ -1642,10 +1642,10 @@ func (_ *Elastigroup) RenderTerraform(t *terraform.TerraformTarget, a, e, change tf.RootBlockDevice = &terraformElastigroupBlockDevice{ DeviceName: rootDevice.DeviceName, - VolumeType: rootDevice.EbsVolumeType, - VolumeSize: rootDevice.EbsVolumeSize, - VolumeIOPS: rootDevice.EbsVolumeIops, - VolumeThroughput: rootDevice.EbsVolumeThroughput, + VolumeType: fi.PtrTo(string(rootDevice.EbsVolumeType)), + VolumeSize: ptrInt32ToPtrInt64(rootDevice.EbsVolumeSize), + VolumeIOPS: ptrInt32ToPtrInt64(rootDevice.EbsVolumeIops), + VolumeThroughput: ptrInt32ToPtrInt64(rootDevice.EbsVolumeThroughput), Encrypted: rootDevice.EbsEncrypted, DeleteOnTermination: fi.PtrTo(true), } @@ -1805,7 +1805,7 @@ func (e *Elastigroup) buildTargetGroups() []*aws.LoadBalancer { } func buildEphemeralDevices(cloud awsup.AWSCloud, machineType *string) ([]*awstasks.BlockDeviceMapping, error) { - info, err := awsup.GetMachineTypeInfo(cloud, fi.ValueOf(machineType)) + info, err := awsup.GetMachineTypeInfo(cloud, ec2types.InstanceType(fi.ValueOf(machineType))) if err != nil { return nil, err } @@ -1831,20 +1831,20 @@ func buildRootDevice(cloud awsup.AWSCloud, volumeOpts *RootVolumeOpts, bdm := &awstasks.BlockDeviceMapping{ DeviceName: img.RootDeviceName, - EbsVolumeSize: volumeOpts.Size, - EbsVolumeType: volumeOpts.Type, + EbsVolumeSize: ptrInt64ToPtrInt32(volumeOpts.Size), + EbsVolumeType: ec2types.VolumeType(fi.ValueOf(volumeOpts.Type)), EbsEncrypted: volumeOpts.Encryption, EbsDeleteOnTermination: fi.PtrTo(true), } // IOPS is not supported for gp2 volumes. if volumeOpts.IOPS != nil && fi.ValueOf(volumeOpts.Type) != "gp2" { - bdm.EbsVolumeIops = volumeOpts.IOPS + bdm.EbsVolumeIops = ptrInt64ToPtrInt32(volumeOpts.IOPS) } // Throughput is only supported for gp3 volumes. if volumeOpts.Throughput != nil && fi.ValueOf(volumeOpts.Type) == "gp3" { - bdm.EbsVolumeThroughput = volumeOpts.Throughput + bdm.EbsVolumeThroughput = ptrInt64ToPtrInt32(volumeOpts.Throughput) } return bdm, nil @@ -1856,21 +1856,21 @@ func (e *Elastigroup) convertBlockDeviceMapping(in *awstasks.BlockDeviceMapping) VirtualName: in.VirtualName, } - if in.EbsDeleteOnTermination != nil || in.EbsVolumeSize != nil || in.EbsVolumeType != nil { + if in.EbsDeleteOnTermination != nil || in.EbsVolumeSize != nil || len(in.EbsVolumeType) > 0 { out.EBS = &aws.EBS{ - VolumeType: in.EbsVolumeType, + VolumeType: fi.PtrTo(string(in.EbsVolumeType)), VolumeSize: fi.PtrTo(int(fi.ValueOf(in.EbsVolumeSize))), Encrypted: in.EbsEncrypted, DeleteOnTermination: in.EbsDeleteOnTermination, } // IOPS is not valid for gp2 volumes. - if in.EbsVolumeIops != nil && fi.ValueOf(in.EbsVolumeType) != "gp2" { + if in.EbsVolumeIops != nil && in.EbsVolumeType != ec2types.VolumeTypeGp2 { out.EBS.IOPS = fi.PtrTo(int(fi.ValueOf(in.EbsVolumeIops))) } // Throughput is only valid for gp3 volumes. - if in.EbsVolumeThroughput != nil && fi.ValueOf(in.EbsVolumeType) == "gp3" { + if in.EbsVolumeThroughput != nil && in.EbsVolumeType == ec2types.VolumeTypeGp3 { out.EBS.Throughput = fi.PtrTo(int(fi.ValueOf(in.EbsVolumeThroughput))) } } @@ -1904,7 +1904,7 @@ func (e *Elastigroup) applyDefaults() { } } -func resolveImage(cloud awsup.AWSCloud, name string) (*ec2.Image, error) { +func resolveImage(cloud awsup.AWSCloud, name string) (*ec2types.Image, error) { image, err := cloud.ResolveImage(name) if err != nil { return nil, fmt.Errorf("spotinst: unable to resolve image %q: %v", name, err) diff --git a/upup/pkg/fi/cloudup/spotinsttasks/launch_spec.go b/upup/pkg/fi/cloudup/spotinsttasks/launch_spec.go index 58f6e78e21..8533860561 100644 --- a/upup/pkg/fi/cloudup/spotinsttasks/launch_spec.go +++ b/upup/pkg/fi/cloudup/spotinsttasks/launch_spec.go @@ -23,6 +23,7 @@ import ( "reflect" "strings" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/spotinst/spotinst-sdk-go/service/ocean/providers/aws" "github.com/spotinst/spotinst-sdk-go/spotinst/util/stringutil" corev1 "k8s.io/api/core/v1" @@ -1047,10 +1048,10 @@ func (_ *LaunchSpec) RenderTerraform(t *terraform.TerraformTarget, a, e, changes tf.BlockDeviceMappings = append(tf.BlockDeviceMappings, &terraformBlockDeviceMapping{ DeviceName: rootDevice.DeviceName, EBS: &terraformBlockDeviceMappingEBS{ - VolumeType: rootDevice.EbsVolumeType, - VolumeSize: rootDevice.EbsVolumeSize, - VolumeIOPS: rootDevice.EbsVolumeIops, - VolumeThroughput: rootDevice.EbsVolumeThroughput, + VolumeType: fi.PtrTo(string(rootDevice.EbsVolumeType)), + VolumeSize: ptrInt32ToPtrInt64(rootDevice.EbsVolumeSize), + VolumeIOPS: ptrInt32ToPtrInt64(rootDevice.EbsVolumeIops), + VolumeThroughput: ptrInt32ToPtrInt64(rootDevice.EbsVolumeThroughput), Encrypted: rootDevice.EbsEncrypted, DeleteOnTermination: fi.PtrTo(true), }, @@ -1154,20 +1155,20 @@ func (o *LaunchSpec) convertBlockDeviceMapping(in *awstasks.BlockDeviceMapping) VirtualName: in.VirtualName, } - if in.EbsDeleteOnTermination != nil || in.EbsVolumeSize != nil || in.EbsVolumeType != nil { + if in.EbsDeleteOnTermination != nil || in.EbsVolumeSize != nil || len(in.EbsVolumeType) > 0 { out.EBS = &aws.EBS{ - VolumeType: in.EbsVolumeType, + VolumeType: fi.PtrTo(string(in.EbsVolumeType)), VolumeSize: fi.PtrTo(int(fi.ValueOf(in.EbsVolumeSize))), DeleteOnTermination: in.EbsDeleteOnTermination, } // IOPS is not valid for gp2 volumes. - if in.EbsVolumeIops != nil && fi.ValueOf(in.EbsVolumeType) != "gp2" { + if in.EbsVolumeIops != nil && in.EbsVolumeType != ec2types.VolumeTypeGp2 { out.EBS.IOPS = fi.PtrTo(int(fi.ValueOf(in.EbsVolumeIops))) } // Throughput is only valid for gp3 volumes. - if in.EbsVolumeThroughput != nil && fi.ValueOf(in.EbsVolumeType) == "gp3" { + if in.EbsVolumeThroughput != nil && in.EbsVolumeType == ec2types.VolumeTypeGp3 { out.EBS.Throughput = fi.PtrTo(int(fi.ValueOf(in.EbsVolumeThroughput))) } } diff --git a/upup/pkg/fi/cloudup/spotinsttasks/ocean.go b/upup/pkg/fi/cloudup/spotinsttasks/ocean.go index 0785373d7a..3adb538b25 100644 --- a/upup/pkg/fi/cloudup/spotinsttasks/ocean.go +++ b/upup/pkg/fi/cloudup/spotinsttasks/ocean.go @@ -1367,3 +1367,19 @@ func NormalizeClusterOrientation(orientation *string) ClusterOrientation { return out } + +func ptrInt32ToPtrInt64(i *int32) *int64 { + if i == nil { + return nil + } + v := int64(*i) + return fi.PtrTo(v) +} + +func ptrInt64ToPtrInt32(i *int64) *int32 { + if i == nil { + return nil + } + v := int32(*i) + return fi.PtrTo(v) +}