Skip to content

Commit 4b2f770

Browse files
authored
✨ Migrate ssm code to AWS SDK v2 (#5529)
* Migrate SSM code to AWS SDK V2 - 1.Since ssm interface provided earlier is removed , new is now at pkg/cloud/services/ssm/service.go. 2.Modified client code for ssm client pkg/cloud/scope/clients.go. 3.In the ec2 package updated references of aws-sdk-go/ssm to point to aws-sdk-go-v2/ssm. 4.Types provided by aws-sdk-go-v2/ssm/types pacakage updated in ec2 (launchtemplate_test.go,ami.go,ami_test.go). * Parameter Not found updated as per sdk-v2(smithy.APIError) * Move the MapToSSMTag to central location,add unit test for it * making consistent in error return in tests * Added missing doc.go in mock_ssmiface pkg * initialize the SSMClient properly in the EC2 service ( update to handle in ssm/service as well) * add custom endpoint resolver for ssm * parse smithyError code using existing code pattern * unwrap GetParameter and DeleteParameter for ssmClient * updated ctx to be propagated , but that resulted in some tests being failed ,updated method signatures for tests to pass * ssm client wrapper removed
1 parent 63b8bcf commit 4b2f770

24 files changed

+450
-8786
lines changed

controllers/awsmachine_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,7 @@ func (r *AWSMachineReconciler) createInstance(ctx context.Context, ec2svc servic
737737
return nil, errors.Wrapf(userDataErr, "failed to resolve userdata")
738738
}
739739

740-
instance, err := ec2svc.CreateInstance(machineScope, userData, userDataFormat)
740+
instance, err := ec2svc.CreateInstance(ctx, machineScope, userData, userDataFormat)
741741
if err != nil {
742742
return nil, errors.Wrapf(err, "failed to create AWSMachine instance")
743743
}

controllers/awsmachine_controller_unit_test.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ func TestAWSMachineReconciler(t *testing.T) {
313313
expectedErr := errors.New("Invalid instance")
314314
ec2Svc.EXPECT().InstanceIfExists(gomock.Any()).Return(nil, nil)
315315
secretSvc.EXPECT().Create(gomock.Any(), gomock.Any()).Return("test", int32(1), nil).Times(1)
316-
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, expectedErr)
316+
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, expectedErr)
317317
secretSvc.EXPECT().UserData(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil).Times(1)
318318

319319
_, err := reconciler.reconcileNormal(context.Background(), ms, cs, cs, cs, cs)
@@ -349,7 +349,7 @@ func TestAWSMachineReconciler(t *testing.T) {
349349
instance.State = infrav1.InstanceStatePending
350350

351351
ec2Svc.EXPECT().GetRunningInstanceByTags(gomock.Any()).Return(nil, nil)
352-
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any()).Return(instance, nil)
352+
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(instance, nil)
353353
}
354354

355355
t.Run("instance security group errors", func(t *testing.T) {
@@ -785,7 +785,7 @@ func TestAWSMachineReconciler(t *testing.T) {
785785
return elbSvc
786786
}
787787

788-
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any()).Return(instance, nil)
788+
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(instance, nil)
789789
ec2Svc.EXPECT().GetRunningInstanceByTags(gomock.Any()).Return(nil, nil)
790790
elbSvc.EXPECT().IsInstanceRegisteredWithAPIServerELB(gomock.Any()).Return(false, errors.New("error describing ELB"))
791791
secretSvc.EXPECT().UserData(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil).Times(1)
@@ -811,7 +811,7 @@ func TestAWSMachineReconciler(t *testing.T) {
811811
return elbSvc
812812
}
813813

814-
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any()).Return(instance, nil)
814+
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(instance, nil)
815815
ec2Svc.EXPECT().GetRunningInstanceByTags(gomock.Any()).Return(nil, nil)
816816
elbSvc.EXPECT().IsInstanceRegisteredWithAPIServerELB(gomock.Any()).Return(false, nil)
817817
elbSvc.EXPECT().RegisterInstanceWithAPIServerELB(gomock.Any()).Return(errors.New("failed to attach ELB"))
@@ -842,7 +842,7 @@ func TestAWSMachineReconciler(t *testing.T) {
842842
ensureTag := func(t *testing.T, g *WithT) {
843843
t.Helper()
844844
ec2Svc.EXPECT().InstanceIfExists(gomock.Any()).Return(nil, nil)
845-
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any()).Return(instance, nil)
845+
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(instance, nil)
846846
secretSvc.EXPECT().Create(gomock.Any(), gomock.Any()).Return("test", int32(1), nil)
847847
secretSvc.EXPECT().UserData(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil)
848848
}
@@ -888,7 +888,7 @@ func TestAWSMachineReconciler(t *testing.T) {
888888
ensureSecurityGroups := func(t *testing.T, g *WithT) {
889889
t.Helper()
890890
ec2Svc.EXPECT().InstanceIfExists(gomock.Any()).Return(nil, nil)
891-
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any()).Return(instance, nil)
891+
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(instance, nil)
892892
secretSvc.EXPECT().Create(gomock.Any(), gomock.Any()).Return("test", int32(1), nil)
893893
secretSvc.EXPECT().UserData(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil)
894894
ec2Svc.EXPECT().GetInstanceSecurityGroups(gomock.Any()).Return(map[string][]string{"eid": {}}, nil)
@@ -1011,7 +1011,7 @@ func TestAWSMachineReconciler(t *testing.T) {
10111011

10121012
ec2Svc.EXPECT().GetRunningInstanceByTags(gomock.Any()).Return(nil, nil).AnyTimes()
10131013
secretSvc.EXPECT().Create(gomock.Any(), gomock.Any()).Return(secretPrefix, int32(1), nil).Times(1)
1014-
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any()).Return(instance, nil).AnyTimes()
1014+
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(instance, nil).AnyTimes()
10151015
secretSvc.EXPECT().UserData(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil).Times(1)
10161016
ec2Svc.EXPECT().GetInstanceSecurityGroups(gomock.Any()).Return(map[string][]string{"eid": {}}, nil).Times(1)
10171017
ec2Svc.EXPECT().GetCoreSecurityGroups(gomock.Any()).Return([]string{}, nil).Times(1)
@@ -1048,7 +1048,7 @@ func TestAWSMachineReconciler(t *testing.T) {
10481048

10491049
ec2Svc.EXPECT().GetRunningInstanceByTags(gomock.Any()).Return(nil, nil).AnyTimes()
10501050
secretSvc.EXPECT().Create(gomock.Any(), gomock.Any()).Return(secretPrefix, int32(1), nil).Times(1)
1051-
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any()).Return(instance, nil).AnyTimes()
1051+
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(instance, nil).AnyTimes()
10521052
secretSvc.EXPECT().UserData(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil).Times(1)
10531053
ec2Svc.EXPECT().GetInstanceSecurityGroups(gomock.Any()).Return(map[string][]string{"eid": {}}, nil).Times(1)
10541054
ec2Svc.EXPECT().GetCoreSecurityGroups(gomock.Any()).Return([]string{}, nil).Times(1)
@@ -1304,7 +1304,7 @@ func TestAWSMachineReconciler(t *testing.T) {
13041304
}
13051305
instance.State = infrav1.InstanceStatePending
13061306
secretSvc.EXPECT().Create(gomock.Any(), gomock.Any()).Return(secretPrefix, int32(1), nil).Times(1)
1307-
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any()).Return(instance, nil).AnyTimes()
1307+
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(instance, nil).AnyTimes()
13081308
secretSvc.EXPECT().UserData(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil).Times(1)
13091309
ec2Svc.EXPECT().GetInstanceSecurityGroups(gomock.Any()).Return(map[string][]string{"eid": {}}, nil).Times(1)
13101310
ec2Svc.EXPECT().GetCoreSecurityGroups(gomock.Any()).Return([]string{}, nil).Times(1)
@@ -1357,7 +1357,7 @@ func TestAWSMachineReconciler(t *testing.T) {
13571357
fakeS3URL := "s3://foo"
13581358

13591359
objectStoreSvc.EXPECT().Create(gomock.Any(), gomock.Any(), gomock.Any()).Return(fakeS3URL, nil).Times(1)
1360-
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any()).Return(instance, nil).AnyTimes()
1360+
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(instance, nil).AnyTimes()
13611361
ec2Svc.EXPECT().GetInstanceSecurityGroups(gomock.Any()).Return(map[string][]string{"eid": {}}, nil).Times(1)
13621362
ec2Svc.EXPECT().GetCoreSecurityGroups(gomock.Any()).Return([]string{}, nil).Times(1)
13631363
ec2Svc.EXPECT().GetAdditionalSecurityGroupsIDs(gomock.Any()).Return(nil, nil)
@@ -1392,7 +1392,7 @@ func TestAWSMachineReconciler(t *testing.T) {
13921392
presigned := "https://cluster-api-aws.s3.us-west-2.amazonaws.com/bootstrap-data.yaml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIA3SGQVQG7FGA6KKA6%2F20221104%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20221104T140227Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=b228dbec8c1008c80c162e1210e4503dceead1e4d4751b4d9787314fd6da4d55"
13931393

13941394
objectStoreSvc.EXPECT().Create(gomock.Any(), gomock.Any(), gomock.Any()).Return(presigned, nil).Times(1)
1395-
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any()).Return(instance, nil).AnyTimes()
1395+
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(instance, nil).AnyTimes()
13961396
ec2Svc.EXPECT().GetInstanceSecurityGroups(gomock.Any()).Return(map[string][]string{"eid": {}}, nil).Times(1)
13971397
ec2Svc.EXPECT().GetCoreSecurityGroups(gomock.Any()).Return([]string{}, nil).Times(1)
13981398
ec2Svc.EXPECT().GetAdditionalSecurityGroupsIDs(gomock.Any()).Return(nil, nil)
@@ -1611,7 +1611,7 @@ func TestAWSMachineReconciler(t *testing.T) {
16111611
// Expect no Cluster Object Store to be created.
16121612
objectStoreSvc.EXPECT().Create(gomock.Any(), gomock.Any(), gomock.Any()).Return(fakeS3URL, nil).Times(0)
16131613

1614-
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any()).Return(instance, nil).AnyTimes()
1614+
ec2Svc.EXPECT().CreateInstance(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(instance, nil).AnyTimes()
16151615
ec2Svc.EXPECT().GetInstanceSecurityGroups(gomock.Any()).Return(map[string][]string{"eid": {}}, nil).Times(1)
16161616
ec2Svc.EXPECT().GetCoreSecurityGroups(gomock.Any()).Return([]string{}, nil).Times(1)
16171617
ec2Svc.EXPECT().GetAdditionalSecurityGroupsIDs(gomock.Any()).Return(nil, nil)

exp/controllers/awsmachinepool_controller_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,7 @@ func TestAWSMachinePoolReconciler(t *testing.T) {
703703
defer teardown(t, g)
704704

705705
ec2Svc.EXPECT().GetLaunchTemplate(gomock.Eq("test")).Return(nil, "", nil, nil, nil)
706-
ec2Svc.EXPECT().DiscoverLaunchTemplateAMI(gomock.Any()).Return(ptr.To[string]("ami-abcdef123"), nil)
706+
ec2Svc.EXPECT().DiscoverLaunchTemplateAMI(gomock.Any(), gomock.Any()).Return(ptr.To[string]("ami-abcdef123"), nil)
707707
ec2Svc.EXPECT().CreateLaunchTemplate(gomock.Any(), gomock.Eq(ptr.To[string]("ami-abcdef123")), gomock.Eq(userDataSecretKey), gomock.Eq([]byte("shell-script")), gomock.Eq(userdata.ComputeHash([]byte("shell-script")))).Return("lt-ghijkl456", nil)
708708
asgSvc.EXPECT().GetASGByName(gomock.Any()).Return(nil, nil)
709709
asgSvc.EXPECT().CreateASG(gomock.Any()).DoAndReturn(func(scope *scope.MachinePoolScope) (*expinfrav1.AutoScalingGroup, error) {
@@ -740,7 +740,7 @@ func TestAWSMachinePoolReconciler(t *testing.T) {
740740
&userDataSecretKey,
741741
nil,
742742
nil)
743-
ec2Svc.EXPECT().DiscoverLaunchTemplateAMI(gomock.Any()).Return(ptr.To[string]("ami-existing"), nil) // no change
743+
ec2Svc.EXPECT().DiscoverLaunchTemplateAMI(gomock.Any(), gomock.Any()).Return(ptr.To[string]("ami-existing"), nil) // no change
744744
ec2Svc.EXPECT().LaunchTemplateNeedsUpdate(gomock.Any(), gomock.Any(), gomock.Any()).Return(false, nil)
745745

746746
asgSvc.EXPECT().GetASGByName(gomock.Any()).DoAndReturn(func(scope *scope.MachinePoolScope) (*expinfrav1.AutoScalingGroup, error) {
@@ -789,7 +789,7 @@ func TestAWSMachinePoolReconciler(t *testing.T) {
789789
&userDataSecretKey,
790790
nil,
791791
nil)
792-
ec2Svc.EXPECT().DiscoverLaunchTemplateAMI(gomock.Any()).Return(ptr.To[string]("ami-different"), nil)
792+
ec2Svc.EXPECT().DiscoverLaunchTemplateAMI(gomock.Any(), gomock.Any()).Return(ptr.To[string]("ami-different"), nil)
793793
ec2Svc.EXPECT().LaunchTemplateNeedsUpdate(gomock.Any(), gomock.Any(), gomock.Any()).Return(false, nil)
794794
asgSvc.EXPECT().CanStartASGInstanceRefresh(gomock.Any()).Return(true, nil)
795795
ec2Svc.EXPECT().PruneLaunchTemplateVersions(gomock.Any()).Return(nil, nil)
@@ -845,7 +845,7 @@ func TestAWSMachinePoolReconciler(t *testing.T) {
845845
&apimachinerytypes.NamespacedName{Namespace: "default", Name: "previous-secret-name"},
846846
nil,
847847
nil)
848-
ec2Svc.EXPECT().DiscoverLaunchTemplateAMI(gomock.Any()).Return(ptr.To[string]("ami-existing"), nil)
848+
ec2Svc.EXPECT().DiscoverLaunchTemplateAMI(gomock.Any(), gomock.Any()).Return(ptr.To[string]("ami-existing"), nil)
849849
ec2Svc.EXPECT().LaunchTemplateNeedsUpdate(gomock.Any(), gomock.Any(), gomock.Any()).Return(false, nil)
850850
asgSvc.EXPECT().CanStartASGInstanceRefresh(gomock.Any()).Return(true, nil)
851851
ec2Svc.EXPECT().PruneLaunchTemplateVersions(gomock.Any()).Return(nil, nil)
@@ -887,7 +887,7 @@ func TestAWSMachinePoolReconciler(t *testing.T) {
887887
defer teardown(t, g)
888888

889889
ec2Svc.EXPECT().GetLaunchTemplate(gomock.Eq("test")).Return(nil, "", nil, nil, nil)
890-
ec2Svc.EXPECT().DiscoverLaunchTemplateAMI(gomock.Any()).Return(ptr.To[string]("ami-abcdef123"), nil)
890+
ec2Svc.EXPECT().DiscoverLaunchTemplateAMI(gomock.Any(), gomock.Any()).Return(ptr.To[string]("ami-abcdef123"), nil)
891891
ec2Svc.EXPECT().CreateLaunchTemplate(gomock.Any(), gomock.Eq(ptr.To[string]("ami-abcdef123")), gomock.Eq(userDataSecretKey), gomock.Eq([]byte("shell-script")), gomock.Eq(userdata.ComputeHash([]byte("shell-script")))).Return("lt-ghijkl456", nil)
892892
asgSvc.EXPECT().GetASGByName(gomock.Any()).Return(nil, nil)
893893
asgSvc.EXPECT().CreateASG(gomock.Any()).DoAndReturn(func(scope *scope.MachinePoolScope) (*expinfrav1.AutoScalingGroup, error) {
@@ -931,7 +931,7 @@ func TestAWSMachinePoolReconciler(t *testing.T) {
931931
&apimachinerytypes.NamespacedName{Namespace: "default", Name: "bootstrap-data"},
932932
nil,
933933
nil)
934-
ec2Svc.EXPECT().DiscoverLaunchTemplateAMI(gomock.Any()).Return(ptr.To[string]("ami-existing"), nil)
934+
ec2Svc.EXPECT().DiscoverLaunchTemplateAMI(gomock.Any(), gomock.Any()).Return(ptr.To[string]("ami-existing"), nil)
935935
ec2Svc.EXPECT().LaunchTemplateNeedsUpdate(gomock.Any(), gomock.Any(), gomock.Any()).Return(false, nil)
936936
asgSvc.EXPECT().CanStartASGInstanceRefresh(gomock.Any()).Return(true, nil)
937937
ec2Svc.EXPECT().PruneLaunchTemplateVersions(gomock.Any()).Return(nil, nil)
@@ -1017,7 +1017,7 @@ func TestAWSMachinePoolReconciler(t *testing.T) {
10171017
&apimachinerytypes.NamespacedName{Namespace: "default", Name: "previous-secret-name"},
10181018
nil,
10191019
nil)
1020-
ec2Svc.EXPECT().DiscoverLaunchTemplateAMI(gomock.Any()).Return(ptr.To[string]("ami-existing"), nil)
1020+
ec2Svc.EXPECT().DiscoverLaunchTemplateAMI(gomock.Any(), gomock.Any()).Return(ptr.To[string]("ami-existing"), nil)
10211021
ec2Svc.EXPECT().LaunchTemplateNeedsUpdate(gomock.Any(), gomock.Any(), gomock.Any()).Return(false, nil)
10221022

10231023
s3Mock.EXPECT().PutObject(gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, input *s3.PutObjectInput, optFns ...func(*s3.Options)) (*s3.PutObjectOutput, error) {
@@ -1063,7 +1063,7 @@ func TestAWSMachinePoolReconciler(t *testing.T) {
10631063
&apimachinerytypes.NamespacedName{Namespace: "default", Name: "previous-secret-name"},
10641064
nil,
10651065
nil)
1066-
ec2Svc.EXPECT().DiscoverLaunchTemplateAMI(gomock.Any()).Return(ptr.To[string]("ami-existing"), nil)
1066+
ec2Svc.EXPECT().DiscoverLaunchTemplateAMI(gomock.Any(), gomock.Any()).Return(ptr.To[string]("ami-existing"), nil)
10671067
ec2Svc.EXPECT().LaunchTemplateNeedsUpdate(gomock.Any(), gomock.Any(), gomock.Any()).Return(false, nil)
10681068

10691069
s3Mock.EXPECT().PutObject(gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, input *s3.PutObjectInput, optFns ...func(*s3.Options)) (*s3.PutObjectOutput, error) {

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ require (
1515
github.com/aws/aws-sdk-go-v2/service/eks v1.64.0
1616
github.com/aws/aws-sdk-go-v2/service/iam v1.32.0
1717
github.com/aws/aws-sdk-go-v2/service/s3 v1.53.1
18+
github.com/aws/aws-sdk-go-v2/service/ssm v1.59.1
1819
github.com/aws/aws-sdk-go-v2/service/sts v1.28.6
1920
github.com/aws/smithy-go v1.22.4
2021
github.com/awslabs/goformation/v4 v4.19.5

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ github.com/aws/aws-sdk-go-v2/service/servicequotas v1.21.4 h1:SSDkZRAO8Ok5SoQ4BJ
9696
github.com/aws/aws-sdk-go-v2/service/servicequotas v1.21.4/go.mod h1:plXue/Zg49kU3uU6WwfCWgRR5SRINNiJf03Y/UhYOhU=
9797
github.com/aws/aws-sdk-go-v2/service/sqs v1.38.8 h1:80dpSqWMwx2dAm30Ib7J6ucz1ZHfiv5OCRwN/EnCOXQ=
9898
github.com/aws/aws-sdk-go-v2/service/sqs v1.38.8/go.mod h1:IzNt/udsXlETCdvBOL0nmyMe2t9cGmXmZgsdoZGYYhI=
99+
github.com/aws/aws-sdk-go-v2/service/ssm v1.59.1 h1:Z4cmgV3hKuUIkhJsdn47hf/ABYHUtILfMrV+L8+kRwE=
100+
github.com/aws/aws-sdk-go-v2/service/ssm v1.59.1/go.mod h1:PUWUl5MDiYNQkUHN9Pyd9kgtA/YhbxnSnHP+yQqzrM8=
99101
github.com/aws/aws-sdk-go-v2/service/sso v1.20.5 h1:vN8hEbpRnL7+Hopy9dzmRle1xmDc7o8tmY0klsr175w=
100102
github.com/aws/aws-sdk-go-v2/service/sso v1.20.5/go.mod h1:qGzynb/msuZIE8I75DVRCUXw3o3ZyBmUvMwQ2t/BrGM=
101103
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4 h1:Jux+gDDyi1Lruk+KHF91tK2KCuY61kzoCpvtvJJBtOE=
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
Copyright 2021 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package converters
17+
18+
import (
19+
"reflect"
20+
"testing"
21+
22+
ssmtypes "github.com/aws/aws-sdk-go-v2/service/ssm/types"
23+
24+
infrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
25+
)
26+
27+
func TestMapToSSMTags(t *testing.T) {
28+
tests := []struct {
29+
name string
30+
input infrav1.Tags
31+
expected []ssmtypes.Tag
32+
}{
33+
{
34+
name: "nil map",
35+
input: nil,
36+
expected: []ssmtypes.Tag{},
37+
},
38+
{
39+
name: "empty map",
40+
input: infrav1.Tags{},
41+
expected: []ssmtypes.Tag{},
42+
},
43+
{
44+
name: "single key-value",
45+
input: infrav1.Tags{"k1": "v1"},
46+
expected: []ssmtypes.Tag{
47+
{Key: strPtr("k1"), Value: strPtr("v1")},
48+
},
49+
},
50+
{
51+
name: "multiple keys",
52+
input: infrav1.Tags{"k1": "v1", "k2": "v2"},
53+
expected: []ssmtypes.Tag{
54+
{Key: strPtr("k1"), Value: strPtr("v1")},
55+
{Key: strPtr("k2"), Value: strPtr("v2")},
56+
},
57+
},
58+
{
59+
name: "empty value string",
60+
input: infrav1.Tags{"k1": ""},
61+
expected: []ssmtypes.Tag{
62+
{Key: strPtr("k1"), Value: strPtr("")},
63+
},
64+
},
65+
}
66+
67+
for _, tt := range tests {
68+
t.Run(tt.name, func(t *testing.T) {
69+
got := MapToSSMTags(tt.input)
70+
if len(got) != len(tt.expected) {
71+
t.Errorf("got %d tags, want %d", len(got), len(tt.expected))
72+
return
73+
}
74+
gotMap := make(map[string]string)
75+
for _, tag := range got {
76+
gotMap[*tag.Key] = *tag.Value
77+
}
78+
expectedMap := make(map[string]string)
79+
for _, tag := range tt.expected {
80+
expectedMap[*tag.Key] = *tag.Value
81+
}
82+
if !reflect.DeepEqual(gotMap, expectedMap) {
83+
t.Errorf("MapToSSMTags() = %v, want %v", gotMap, expectedMap)
84+
}
85+
})
86+
}
87+
}
88+
89+
func strPtr(s string) *string {
90+
return &s
91+
}

pkg/cloud/converters/tags.go

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ import (
2222

2323
autoscalingtypes "github.com/aws/aws-sdk-go-v2/service/autoscaling/types"
2424
iamtypes "github.com/aws/aws-sdk-go-v2/service/iam/types"
25+
ssmtypes "github.com/aws/aws-sdk-go-v2/service/ssm/types"
2526
"github.com/aws/aws-sdk-go/aws"
2627
"github.com/aws/aws-sdk-go/service/ec2"
2728
"github.com/aws/aws-sdk-go/service/elb"
2829
"github.com/aws/aws-sdk-go/service/elbv2"
2930
"github.com/aws/aws-sdk-go/service/secretsmanager"
30-
"github.com/aws/aws-sdk-go/service/ssm"
3131

3232
infrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
3333
)
@@ -75,6 +75,20 @@ func MapToTags(src infrav1.Tags) []*ec2.Tag {
7575
return tags
7676
}
7777

78+
// MapToSSMTags converts infrav1.Tags (a map of string key-value pairs) to a slice of SSM Tag objects.
79+
func MapToSSMTags(tags infrav1.Tags) []ssmtypes.Tag {
80+
result := make([]ssmtypes.Tag, 0, len(tags))
81+
for k, v := range tags {
82+
key := k
83+
value := v
84+
result = append(result, ssmtypes.Tag{
85+
Key: &key,
86+
Value: &value,
87+
})
88+
}
89+
return result
90+
}
91+
7892
// ELBTagsToMap converts a []*elb.Tag into a infrav1.Tags.
7993
func ELBTagsToMap(src []*elb.Tag) infrav1.Tags {
8094
tags := make(infrav1.Tags, len(src))
@@ -154,25 +168,6 @@ func MapToSecretsManagerTags(src infrav1.Tags) []*secretsmanager.Tag {
154168
return tags
155169
}
156170

157-
// MapToSSMTags converts a infrav1.Tags to a []*ssm.Tag.
158-
func MapToSSMTags(src infrav1.Tags) []*ssm.Tag {
159-
tags := make([]*ssm.Tag, 0, len(src))
160-
161-
for k, v := range src {
162-
tag := &ssm.Tag{
163-
Key: aws.String(k),
164-
Value: aws.String(v),
165-
}
166-
167-
tags = append(tags, tag)
168-
}
169-
170-
// Sort so that unit tests can expect a stable order
171-
sort.Slice(tags, func(i, j int) bool { return *tags[i].Key < *tags[j].Key })
172-
173-
return tags
174-
}
175-
176171
// MapToIAMTags converts a infrav1.Tags to a []*iam.Tag.
177172
func MapToIAMTags(src infrav1.Tags) []iamtypes.Tag {
178173
tags := make([]iamtypes.Tag, 0, len(src))

0 commit comments

Comments
 (0)