Migrate remaining EC2 resource types to aws-sdk-go-v2

This commit is contained in:
Peter Rifel 2024-04-09 20:21:12 -05:00
parent f0c0c29121
commit dd3d64943f
No known key found for this signature in database
33 changed files with 593 additions and 749 deletions

View File

@ -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 {

View File

@ -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

View File

@ -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 {

View File

@ -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)
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)
}

View File

@ -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"),
},

View File

@ -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)
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")
}

View File

@ -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: &ltID,
},
@ -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,
})

View File

@ -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, &copy)
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...)

View File

@ -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 &copy, 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)
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")
}

View File

@ -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

View File

@ -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 {

View File

@ -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 {

View File

@ -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"

View File

@ -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

View File

@ -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)
}

View File

@ -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 {

View File

@ -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"),

View File

@ -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

View File

@ -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 {

View File

@ -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) {

View File

@ -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)

View File

@ -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 {

View File

@ -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
}

View File

@ -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)
}

View File

@ -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)})
}
}

View File

@ -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)

View File

@ -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)),
},
},
})

View File

@ -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"

View File

@ -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)
}

View File

@ -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
}

View File

@ -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)

View File

@ -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)))
}
}

View File

@ -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)
}