Skip to content

Commit b137ce8

Browse files
committed
test: add tag unit tests
1 parent 8ff4ce3 commit b137ce8

5 files changed

Lines changed: 157 additions & 53 deletions

File tree

internal/controller/awsvalidator_controller.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ func (r *AwsValidatorReconciler) Reconcile(ctx context.Context, req ctrl.Request
9191
}
9292
iamRuleService := iam.NewIAMRuleService(r.Log, aws_utils.IAMService(session))
9393
svcQuotaService := servicequota.NewServiceQuotaRuleService(r.Log, session)
94-
tagRuleService := tag.NewTagRuleService(r.Log, session)
9594

9695
// Get the active validator's validation result
9796
vr := &v8or.ValidationResult{}
@@ -157,7 +156,8 @@ func (r *AwsValidatorReconciler) Reconcile(ctx context.Context, req ctrl.Request
157156

158157
// Tag rules
159158
for _, rule := range validator.Spec.TagRules {
160-
validationResult, err := tagRuleService.ReconcileTagRule(nn, rule)
159+
tagRuleService := tag.NewTagRuleService(r.Log, aws_utils.EC2Service(session, rule.Region))
160+
validationResult, err := tagRuleService.ReconcileTagRule(rule)
161161
if err != nil {
162162
r.Log.V(0).Error(err, "failed to reconcile Tag rule")
163163
}

internal/utils/test/test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package test
2+
3+
import (
4+
"errors"
5+
"reflect"
6+
"testing"
7+
8+
"github.com/spectrocloud-labs/valid8or/pkg/types"
9+
)
10+
11+
func CheckTestCase(t *testing.T, res *types.ValidationResult, expectedResult types.ValidationResult, err, expectedError error) {
12+
if !reflect.DeepEqual(res.State, expectedResult.State) {
13+
t.Errorf("expected state (%+v), got (%+v)", expectedResult.State, res.State)
14+
}
15+
if !reflect.DeepEqual(res.Condition.ValidationType, expectedResult.Condition.ValidationType) {
16+
t.Errorf("expected validation type (%s), got (%s)", expectedResult.Condition.ValidationType, res.Condition.ValidationType)
17+
}
18+
if !reflect.DeepEqual(res.Condition.ValidationRule, expectedResult.Condition.ValidationRule) {
19+
t.Errorf("expected validation rule (%s), got (%s)", expectedResult.Condition.ValidationRule, res.Condition.ValidationRule)
20+
}
21+
if !reflect.DeepEqual(res.Condition.Message, expectedResult.Condition.Message) {
22+
t.Errorf("expected message (%s), got (%s)", expectedResult.Condition.Message, res.Condition.Message)
23+
}
24+
if !reflect.DeepEqual(res.Condition.Details, expectedResult.Condition.Details) {
25+
t.Errorf("expected details (%s), got (%s)", expectedResult.Condition.Details, res.Condition.Details)
26+
}
27+
if !reflect.DeepEqual(res.Condition.Failures, expectedResult.Condition.Failures) {
28+
t.Errorf("expected failures (%s), got (%s)", expectedResult.Condition.Failures, res.Condition.Failures)
29+
}
30+
if !reflect.DeepEqual(res.Condition.Status, expectedResult.Condition.Status) {
31+
t.Errorf("expected status (%s), got (%s)", expectedResult.Condition.Status, res.Condition.Status)
32+
}
33+
if !errors.Is(err, expectedError) {
34+
t.Errorf("expected error (%v), got (%v)", expectedError, err)
35+
}
36+
}

internal/validators/iam/iam_validator_test.go

Lines changed: 13 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ package iam
22

33
import (
44
"net/url"
5-
"reflect"
65
"testing"
76

87
"github.com/aws/aws-sdk-go/service/iam"
98
"github.com/go-logr/logr"
109
corev1 "k8s.io/api/core/v1"
1110

1211
"github.com/spectrocloud-labs/valid8or-plugin-aws/api/v1alpha1"
12+
"github.com/spectrocloud-labs/valid8or-plugin-aws/internal/utils/test"
1313
v8or "github.com/spectrocloud-labs/valid8or/api/v1alpha1"
1414
"github.com/spectrocloud-labs/valid8or/pkg/types"
1515
"github.com/spectrocloud-labs/valid8or/pkg/util/ptr"
@@ -76,7 +76,7 @@ const (
7676

7777
var iamService = NewIAMRuleService(logr.Logger{}, iamApiMock{
7878
attachedGroupPolicies: map[string]*iam.ListAttachedGroupPoliciesOutput{
79-
"iamGroup": &iam.ListAttachedGroupPoliciesOutput{
79+
"iamGroup": {
8080
AttachedPolicies: []*iam.AttachedPolicy{
8181
{
8282
PolicyArn: ptr.Ptr("iamRoleArn1"),
@@ -86,15 +86,15 @@ var iamService = NewIAMRuleService(logr.Logger{}, iamApiMock{
8686
},
8787
},
8888
attachedRolePolicies: map[string]*iam.ListAttachedRolePoliciesOutput{
89-
"iamRole1": &iam.ListAttachedRolePoliciesOutput{
89+
"iamRole1": {
9090
AttachedPolicies: []*iam.AttachedPolicy{
9191
{
9292
PolicyArn: ptr.Ptr("iamRoleArn1"),
9393
PolicyName: ptr.Ptr("iamPolicy"),
9494
},
9595
},
9696
},
97-
"iamRole2": &iam.ListAttachedRolePoliciesOutput{
97+
"iamRole2": {
9898
AttachedPolicies: []*iam.AttachedPolicy{
9999
{
100100
PolicyArn: ptr.Ptr("iamRoleArn2"),
@@ -104,19 +104,19 @@ var iamService = NewIAMRuleService(logr.Logger{}, iamApiMock{
104104
},
105105
},
106106
policyArns: map[string]*iam.GetPolicyOutput{
107-
"iamRoleArn1": &iam.GetPolicyOutput{
107+
"iamRoleArn1": {
108108
Policy: ptr.Ptr(iam.Policy{
109109
DefaultVersionId: ptr.Ptr("1"),
110110
}),
111111
},
112-
"iamRoleArn2": &iam.GetPolicyOutput{
112+
"iamRoleArn2": {
113113
Policy: ptr.Ptr(iam.Policy{
114114
DefaultVersionId: ptr.Ptr("1"),
115115
}),
116116
},
117117
},
118118
attachedUserPolicies: map[string]*iam.ListAttachedUserPoliciesOutput{
119-
"iamUser": &iam.ListAttachedUserPoliciesOutput{
119+
"iamUser": {
120120
AttachedPolicies: []*iam.AttachedPolicy{
121121
{
122122
PolicyArn: ptr.Ptr("iamRoleArn1"),
@@ -126,12 +126,12 @@ var iamService = NewIAMRuleService(logr.Logger{}, iamApiMock{
126126
},
127127
},
128128
policyVersions: map[string]*iam.GetPolicyVersionOutput{
129-
"iamRoleArn1": &iam.GetPolicyVersionOutput{
129+
"iamRoleArn1": {
130130
PolicyVersion: ptr.Ptr(iam.PolicyVersion{
131131
Document: ptr.Ptr(url.QueryEscape(policyDocumentOutput1)),
132132
}),
133133
},
134-
"iamRoleArn2": &iam.GetPolicyVersionOutput{
134+
"iamRoleArn2": {
135135
PolicyVersion: ptr.Ptr(iam.PolicyVersion{
136136
Document: ptr.Ptr(url.QueryEscape(policyDocumentOutput2)),
137137
}),
@@ -146,33 +146,6 @@ type testCase struct {
146146
expectedError error
147147
}
148148

149-
func checkTestCase(t *testing.T, c testCase, res *types.ValidationResult, err error) {
150-
if !reflect.DeepEqual(res.State, c.expectedResult.State) {
151-
t.Errorf("expected state (%+v), got (%+v)", c.expectedResult.State, res.State)
152-
}
153-
if !reflect.DeepEqual(res.Condition.ValidationType, c.expectedResult.Condition.ValidationType) {
154-
t.Errorf("expected validation type (%s), got (%s)", c.expectedResult.Condition.ValidationType, res.Condition.ValidationType)
155-
}
156-
if !reflect.DeepEqual(res.Condition.ValidationRule, c.expectedResult.Condition.ValidationRule) {
157-
t.Errorf("expected validation rule (%s), got (%s)", c.expectedResult.Condition.ValidationRule, res.Condition.ValidationRule)
158-
}
159-
if !reflect.DeepEqual(res.Condition.Message, c.expectedResult.Condition.Message) {
160-
t.Errorf("expected message (%s), got (%s)", c.expectedResult.Condition.Message, res.Condition.Message)
161-
}
162-
if !reflect.DeepEqual(res.Condition.Details, c.expectedResult.Condition.Details) {
163-
t.Errorf("expected details (%s), got (%s)", c.expectedResult.Condition.Details, res.Condition.Details)
164-
}
165-
if !reflect.DeepEqual(res.Condition.Failures, c.expectedResult.Condition.Failures) {
166-
t.Errorf("expected failures (%s), got (%s)", c.expectedResult.Condition.Failures, res.Condition.Failures)
167-
}
168-
if !reflect.DeepEqual(res.Condition.Status, c.expectedResult.Condition.Status) {
169-
t.Errorf("expected status (%s), got (%s)", c.expectedResult.Condition.Status, res.Condition.Status)
170-
}
171-
if !reflect.DeepEqual(err, c.expectedError) {
172-
t.Errorf("expected error (%v), got (%v)", c.expectedError, err)
173-
}
174-
}
175-
176149
func TestIAMGroupValidation(t *testing.T) {
177150
cs := []testCase{
178151
{
@@ -240,7 +213,7 @@ func TestIAMGroupValidation(t *testing.T) {
240213
}
241214
for _, c := range cs {
242215
result, err := iamService.ReconcileIAMGroupRule(c.rule)
243-
checkTestCase(t, c, result, err)
216+
test.CheckTestCase(t, result, c.expectedResult, err, c.expectedError)
244217
}
245218
}
246219

@@ -341,7 +314,7 @@ func TestIAMRoleValidation(t *testing.T) {
341314
}
342315
for _, c := range cs {
343316
result, err := iamService.ReconcileIAMRoleRule(c.rule)
344-
checkTestCase(t, c, result, err)
317+
test.CheckTestCase(t, result, c.expectedResult, err, c.expectedError)
345318
}
346319
}
347320

@@ -412,7 +385,7 @@ func TestIAMUserValidation(t *testing.T) {
412385
}
413386
for _, c := range cs {
414387
result, err := iamService.ReconcileIAMUserRule(c.rule)
415-
checkTestCase(t, c, result, err)
388+
test.CheckTestCase(t, result, c.expectedResult, err, c.expectedError)
416389
}
417390
}
418391

@@ -483,6 +456,6 @@ func TestIAMPolicyValidation(t *testing.T) {
483456
}
484457
for _, c := range cs {
485458
result, err := iamService.ReconcileIAMPolicyRule(c.rule)
486-
checkTestCase(t, c, result, err)
459+
test.CheckTestCase(t, result, c.expectedResult, err, c.expectedError)
487460
}
488461
}

internal/validators/tag/tag_validator.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,36 @@ package tag
33
import (
44
"fmt"
55

6-
"github.com/aws/aws-sdk-go/aws/session"
76
"github.com/aws/aws-sdk-go/service/ec2"
87
"github.com/go-logr/logr"
98
corev1 "k8s.io/api/core/v1"
10-
ktypes "k8s.io/apimachinery/pkg/types"
119

1210
"github.com/spectrocloud-labs/valid8or-plugin-aws/api/v1alpha1"
1311
"github.com/spectrocloud-labs/valid8or-plugin-aws/internal/constants"
14-
"github.com/spectrocloud-labs/valid8or-plugin-aws/internal/utils/aws"
1512
v8or "github.com/spectrocloud-labs/valid8or/api/v1alpha1"
1613
v8orconstants "github.com/spectrocloud-labs/valid8or/pkg/constants"
1714
v8ortypes "github.com/spectrocloud-labs/valid8or/pkg/types"
1815
"github.com/spectrocloud-labs/valid8or/pkg/util/ptr"
1916
)
2017

18+
type tagApi interface {
19+
DescribeSubnets(input *ec2.DescribeSubnetsInput) (*ec2.DescribeSubnetsOutput, error)
20+
}
21+
2122
type TagRuleService struct {
22-
log logr.Logger
23-
session *session.Session
23+
log logr.Logger
24+
tagSvc tagApi
2425
}
2526

26-
func NewTagRuleService(log logr.Logger, s *session.Session) *TagRuleService {
27+
func NewTagRuleService(log logr.Logger, tagSvc tagApi) *TagRuleService {
2728
return &TagRuleService{
28-
log: log,
29-
session: s,
29+
log: log,
30+
tagSvc: tagSvc,
3031
}
3132
}
3233

3334
// ReconcileTagRule reconciles an EC2 tagging validation rule from the AWSValidator config
34-
func (s *TagRuleService) ReconcileTagRule(nn ktypes.NamespacedName, rule v1alpha1.TagRule) (*v8ortypes.ValidationResult, error) {
35-
ec2Svc := aws.EC2Service(s.session, rule.Region)
35+
func (s *TagRuleService) ReconcileTagRule(rule v1alpha1.TagRule) (*v8ortypes.ValidationResult, error) {
3636

3737
// Build the default latest condition for this tag rule
3838
state := v8or.ValidationSucceeded
@@ -47,7 +47,7 @@ func (s *TagRuleService) ReconcileTagRule(nn ktypes.NamespacedName, rule v1alpha
4747
// match the tag rule's list of ARNs against the subnets with tag 'rule.Key=rule.ExpectedValue'
4848
failures := make([]string, 0)
4949
foundArns := make(map[string]bool)
50-
subnets, err := ec2Svc.DescribeSubnets(&ec2.DescribeSubnetsInput{
50+
subnets, err := s.tagSvc.DescribeSubnets(&ec2.DescribeSubnetsInput{
5151
Filters: []*ec2.Filter{
5252
{
5353
Name: ptr.Ptr(fmt.Sprintf("tag:%s", rule.Key)),
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package tag
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/aws/aws-sdk-go/service/ec2"
8+
"github.com/go-logr/logr"
9+
corev1 "k8s.io/api/core/v1"
10+
11+
"github.com/spectrocloud-labs/valid8or-plugin-aws/api/v1alpha1"
12+
"github.com/spectrocloud-labs/valid8or-plugin-aws/internal/utils/test"
13+
v8or "github.com/spectrocloud-labs/valid8or/api/v1alpha1"
14+
"github.com/spectrocloud-labs/valid8or/pkg/types"
15+
"github.com/spectrocloud-labs/valid8or/pkg/util/ptr"
16+
)
17+
18+
type tagApiMock struct {
19+
subnetsByTagValue map[string]*ec2.DescribeSubnetsOutput
20+
}
21+
22+
func (m tagApiMock) DescribeSubnets(input *ec2.DescribeSubnetsInput) (*ec2.DescribeSubnetsOutput, error) {
23+
key := fmt.Sprintf("%s=%s", *input.Filters[0].Name, *input.Filters[0].Values[0])
24+
return m.subnetsByTagValue[key], nil
25+
}
26+
27+
var tagService = NewTagRuleService(logr.Logger{}, tagApiMock{
28+
subnetsByTagValue: map[string]*ec2.DescribeSubnetsOutput{
29+
"tag:kubernetes.io/role/elb=1": {
30+
Subnets: []*ec2.Subnet{
31+
{
32+
SubnetArn: ptr.Ptr("subnetArn2"),
33+
},
34+
},
35+
},
36+
},
37+
})
38+
39+
type testCase struct {
40+
name string
41+
rule v1alpha1.TagRule
42+
expectedResult types.ValidationResult
43+
expectedError error
44+
}
45+
46+
func TestTagValidation(t *testing.T) {
47+
cs := []testCase{
48+
{
49+
name: "Fail (missing tag)",
50+
rule: v1alpha1.TagRule{
51+
Key: "kubernetes.io/role/elb",
52+
ExpectedValue: "1",
53+
Region: "us-west-1",
54+
ResourceType: "subnet",
55+
ARNs: []string{"subnetArn1"},
56+
},
57+
expectedResult: types.ValidationResult{
58+
Condition: &v8or.ValidationCondition{
59+
ValidationType: "aws-tag",
60+
ValidationRule: "validation-subnet-kubernetes.io/role/elb",
61+
Message: "One or more required subnet tags was not found",
62+
Details: []string{},
63+
Failures: []string{"Subnet with ARN subnetArn1 missing tag kubernetes.io/role/elb=1"},
64+
Status: corev1.ConditionFalse,
65+
},
66+
State: ptr.Ptr(v8or.ValidationFailed),
67+
},
68+
},
69+
{
70+
name: "Pass",
71+
rule: v1alpha1.TagRule{
72+
Key: "kubernetes.io/role/elb",
73+
ExpectedValue: "1",
74+
Region: "us-west-1",
75+
ResourceType: "subnet",
76+
ARNs: []string{"subnetArn2"},
77+
},
78+
expectedResult: types.ValidationResult{
79+
Condition: &v8or.ValidationCondition{
80+
ValidationType: "aws-tag",
81+
ValidationRule: "validation-subnet-kubernetes.io/role/elb",
82+
Message: "All required subnet tags were found",
83+
Details: []string{},
84+
Failures: nil,
85+
Status: corev1.ConditionTrue,
86+
},
87+
State: ptr.Ptr(v8or.ValidationSucceeded),
88+
},
89+
},
90+
}
91+
for _, c := range cs {
92+
result, err := tagService.ReconcileTagRule(c.rule)
93+
test.CheckTestCase(t, result, c.expectedResult, err, c.expectedError)
94+
}
95+
}

0 commit comments

Comments
 (0)