Skip to content

Commit 832b64d

Browse files
author
Matt Welke
authored
Merge pull request #473 from validator-labs/refactor/validation-rule-interface
refactor: make each rule implement `validationrule.Interface`
2 parents 5121485 + c6460f1 commit 832b64d

12 files changed

Lines changed: 117 additions & 50 deletions

api/v1alpha1/awsvalidator_types.go

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import (
2323

2424
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2525

26+
"github.com/validator-labs/validator/pkg/validationrule"
27+
2628
"github.com/validator-labs/validator-plugin-aws/pkg/constants"
2729
)
2830

@@ -97,11 +99,25 @@ type AwsSTSAuth struct {
9799
// Each AmiRule is intended to match a single AMI, as an AmiRule is considered successful if at least one AMI is found.
98100
// Refer to https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeImages.html for more information.
99101
type AmiRule struct {
100-
Name string `json:"name" yaml:"name"`
101-
AmiIDs []string `json:"amiIds,omitempty" yaml:"amiIds,omitempty"`
102-
Filters []Filter `json:"filters,omitempty" yaml:"filters,omitempty"`
103-
Owners []string `json:"owners,omitempty" yaml:"owners,omitempty"`
104-
Region string `json:"region" yaml:"region"`
102+
validationrule.ManuallyNamed `json:"-"`
103+
104+
RuleName string `json:"name" yaml:"name"`
105+
AmiIDs []string `json:"amiIds,omitempty" yaml:"amiIds,omitempty"`
106+
Filters []Filter `json:"filters,omitempty" yaml:"filters,omitempty"`
107+
Owners []string `json:"owners,omitempty" yaml:"owners,omitempty"`
108+
Region string `json:"region" yaml:"region"`
109+
}
110+
111+
var _ validationrule.Interface = (*AmiRule)(nil)
112+
113+
// Name returns the name of the AmiRule.
114+
func (r AmiRule) Name() string {
115+
return r.RuleName
116+
}
117+
118+
// SetName sets the name of the AmiRule.
119+
func (r *AmiRule) SetName(name string) {
120+
r.RuleName = name
105121
}
106122

107123
// Filter defines a filter to apply to an AWS API query.
@@ -113,10 +129,14 @@ type Filter struct {
113129

114130
// IamRoleRule compares the IAM permissions associated with an IAM role against an expected permission set.
115131
type IamRoleRule struct {
132+
validationrule.AutomaticallyNamed `json:"-"`
133+
116134
IamRoleName string `json:"iamRoleName" yaml:"iamRoleName"`
117135
Policies []PolicyDocument `json:"iamPolicies" yaml:"iamPolicies"`
118136
}
119137

138+
var _ validationrule.Interface = (*IamRoleRule)(nil)
139+
120140
// Name returns the name of an IamRoleRule.
121141
func (r IamRoleRule) Name() string {
122142
return r.IamRoleName
@@ -129,10 +149,14 @@ func (r IamRoleRule) IAMPolicies() []PolicyDocument {
129149

130150
// IamUserRule compares the IAM permissions associated with an IAM user against an expected permission set.
131151
type IamUserRule struct {
152+
validationrule.AutomaticallyNamed `json:"-"`
153+
132154
IamUserName string `json:"iamUserName" yaml:"iamUserName"`
133155
Policies []PolicyDocument `json:"iamPolicies" yaml:"iamPolicies"`
134156
}
135157

158+
var _ validationrule.Interface = (*IamUserRule)(nil)
159+
136160
// Name returns the name of an IamUserRule.
137161
func (r IamUserRule) Name() string {
138162
return r.IamUserName
@@ -145,10 +169,14 @@ func (r IamUserRule) IAMPolicies() []PolicyDocument {
145169

146170
// IamGroupRule compares the IAM permissions associated with an IAM group against an expected permission set.
147171
type IamGroupRule struct {
172+
validationrule.AutomaticallyNamed `json:"-"`
173+
148174
IamGroupName string `json:"iamGroupName" yaml:"iamGroupName"`
149175
Policies []PolicyDocument `json:"iamPolicies" yaml:"iamPolicies"`
150176
}
151177

178+
var _ validationrule.Interface = (*IamGroupRule)(nil)
179+
152180
// Name returns the name of an IamGroupRule.
153181
func (r IamGroupRule) Name() string {
154182
return r.IamGroupName
@@ -161,10 +189,14 @@ func (r IamGroupRule) IAMPolicies() []PolicyDocument {
161189

162190
// IamPolicyRule compares the IAM permissions associated with an IAM policy against an expected permission set.
163191
type IamPolicyRule struct {
192+
validationrule.AutomaticallyNamed `json:"-"`
193+
164194
IamPolicyARN string `json:"iamPolicyArn" yaml:"iamPolicyArn"`
165195
Policies []PolicyDocument `json:"iamPolicies" yaml:"iamPolicies"`
166196
}
167197

198+
var _ validationrule.Interface = (*IamPolicyRule)(nil)
199+
168200
// Name returns the name of an IamPolicyRule.
169201
func (r IamPolicyRule) Name() string {
170202
return r.IamPolicyARN
@@ -208,12 +240,26 @@ func (c Condition) String() string {
208240

209241
// ServiceQuotaRule ensures that AWS service quotas are within a particular threshold.
210242
type ServiceQuotaRule struct {
211-
Name string `json:"name" yaml:"name"`
243+
validationrule.ManuallyNamed `json:"-"`
244+
245+
RuleName string `json:"name" yaml:"name"`
212246
Region string `json:"region" yaml:"region"`
213247
ServiceCode string `json:"serviceCode" yaml:"serviceCode"`
214248
ServiceQuotas []ServiceQuota `json:"serviceQuotas" yaml:"serviceQuotas"`
215249
}
216250

251+
var _ validationrule.Interface = (*ServiceQuotaRule)(nil)
252+
253+
// Name returns the name of the ServiceQuotaRule.
254+
func (r ServiceQuotaRule) Name() string {
255+
return r.RuleName
256+
}
257+
258+
// SetName sets the name of the ServiceQuotaRule.
259+
func (r *ServiceQuotaRule) SetName(name string) {
260+
r.RuleName = name
261+
}
262+
217263
// ServiceQuota defines an AWS service quota and an associated buffer.
218264
type ServiceQuota struct {
219265
Name string `json:"name" yaml:"name"`
@@ -222,14 +268,28 @@ type ServiceQuota struct {
222268

223269
// TagRule ensures that the tags associated with a particular AWS resource match an expected tag set.
224270
type TagRule struct {
225-
Name string `json:"name" yaml:"name"`
271+
validationrule.ManuallyNamed `json:"-"`
272+
273+
RuleName string `json:"name" yaml:"name"`
226274
Key string `json:"key" yaml:"key"`
227275
ExpectedValue string `json:"expectedValue" yaml:"expectedValue"`
228276
Region string `json:"region" yaml:"region"`
229277
ResourceType string `json:"resourceType" yaml:"resourceType"`
230278
ARNs []string `json:"arns" yaml:"arns"`
231279
}
232280

281+
var _ validationrule.Interface = (*TagRule)(nil)
282+
283+
// Name returns the name of the ServiceQuotaRule.
284+
func (r TagRule) Name() string {
285+
return r.RuleName
286+
}
287+
288+
// SetName sets the name of the ServiceQuotaRule.
289+
func (r *TagRule) SetName(name string) {
290+
r.RuleName = name
291+
}
292+
233293
// AwsValidatorStatus defines the observed state of AwsValidator
234294
type AwsValidatorStatus struct{}
235295

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ require (
1818
github.com/onsi/ginkgo/v2 v2.20.1
1919
github.com/onsi/gomega v1.34.1
2020
github.com/pkg/errors v0.9.1
21-
github.com/validator-labs/validator v0.1.6
21+
github.com/validator-labs/validator v0.1.7
2222
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa
2323
k8s.io/api v0.31.0
2424
k8s.io/apimachinery v0.31.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
206206
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
207207
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
208208
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
209-
github.com/validator-labs/validator v0.1.6 h1:Gckp+rYFPNYJwCU5iLgJXuS/o6yy7ayivvGzhxNOf3o=
210-
github.com/validator-labs/validator v0.1.6/go.mod h1:ssEvc9ws3kwWJ2VpIsOtgm7WmA6bdux2kkuIHbgT6oU=
209+
github.com/validator-labs/validator v0.1.7 h1:x1iBKoecChM52G7bbacMsdIQYvB84C65DRIex8TG6vQ=
210+
github.com/validator-labs/validator v0.1.7/go.mod h1:ssEvc9ws3kwWJ2VpIsOtgm7WmA6bdux2kkuIHbgT6oU=
211211
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
212212
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
213213
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=

internal/controller/awsvalidator_controller_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ var _ = Describe("AWSValidator controller", Ordered, func() {
5050
DefaultRegion: "us-west-1",
5151
AmiRules: []v1alpha1.AmiRule{
5252
{
53-
Name: "AMIRule",
54-
AmiIDs: []string{"ami-12345678"},
55-
Region: "us-west-2",
53+
RuleName: "AMIRule",
54+
AmiIDs: []string{"ami-12345678"},
55+
Region: "us-west-2",
5656
},
5757
},
5858
IamRoleRules: []v1alpha1.IamRoleRule{
@@ -81,7 +81,7 @@ var _ = Describe("AWSValidator controller", Ordered, func() {
8181
},
8282
ServiceQuotaRules: []v1alpha1.ServiceQuotaRule{
8383
{
84-
Name: "ServiceQuotaRule",
84+
RuleName: "ServiceQuotaRule",
8585
Region: "us-west-1",
8686
ServiceCode: "ec2",
8787
ServiceQuotas: []v1alpha1.ServiceQuota{

pkg/validate/validate.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func Validate(spec v1alpha1.AwsValidatorSpec, log logr.Logger) types.ValidationR
2929
if err != nil {
3030
errMsg := "Failed to reconcile AMI rule"
3131
log.V(0).Error(err, errMsg)
32-
vrr := validators.BuildValidationResult(rule.Name, errMsg, constants.ValidationTypeAmi)
32+
vrr := validators.BuildValidationResult(rule.Name(), errMsg, constants.ValidationTypeAmi)
3333
resp.AddResult(vrr, err)
3434
continue
3535
}
@@ -84,7 +84,7 @@ func Validate(spec v1alpha1.AwsValidatorSpec, log logr.Logger) types.ValidationR
8484
if err != nil {
8585
errMsg := "Failed to reconcile Service Quota rule"
8686
log.V(0).Error(err, errMsg)
87-
vrr := validators.BuildValidationResult(rule.Name, errMsg, constants.ValidationTypeServiceQuota)
87+
vrr := validators.BuildValidationResult(rule.Name(), errMsg, constants.ValidationTypeServiceQuota)
8888
resp.AddResult(vrr, err)
8989
continue
9090
}
@@ -109,7 +109,7 @@ func Validate(spec v1alpha1.AwsValidatorSpec, log logr.Logger) types.ValidationR
109109
if err != nil {
110110
errMsg := "Failed to reconcile Tag rule"
111111
log.V(0).Error(err, errMsg)
112-
vrr := validators.BuildValidationResult(rule.Name, errMsg, constants.ValidationTypeTag)
112+
vrr := validators.BuildValidationResult(rule.Name(), errMsg, constants.ValidationTypeTag)
113113
resp.AddResult(vrr, err)
114114
continue
115115
}

pkg/validators/ami/ami_validator.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func NewAmiRuleService(log logr.Logger, amiSvc amiAPI) *RuleService {
4242
func (s *RuleService) ReconcileAmiRule(rule v1alpha1.AmiRule) (*vapitypes.ValidationRuleResult, error) {
4343

4444
// Build the default latest condition for this AMI rule
45-
vr := validators.BuildValidationResult(rule.Name, "All required AMIs were found", constants.ValidationTypeAmi)
45+
vr := validators.BuildValidationResult(rule.Name(), "All required AMIs were found", constants.ValidationTypeAmi)
4646

4747
// Describe AMIs matching the rule. There should be at least one.
4848
input := &ec2.DescribeImagesInput{

pkg/validators/ami/ami_validator_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ func TestAmiValidation(t *testing.T) {
5151
{
5252
name: "Fail (missing image)",
5353
rule: v1alpha1.AmiRule{
54-
Name: "AMI Rule Fail",
55-
AmiIDs: []string{"ami-87654321"},
56-
Region: "us-west-1",
54+
RuleName: "AMI Rule Fail",
55+
AmiIDs: []string{"ami-87654321"},
56+
Region: "us-west-1",
5757
},
5858
expectedResult: types.ValidationRuleResult{
5959
Condition: &vapi.ValidationCondition{
@@ -70,9 +70,9 @@ func TestAmiValidation(t *testing.T) {
7070
{
7171
name: "Pass",
7272
rule: v1alpha1.AmiRule{
73-
Name: "AMI Rule Pass",
74-
AmiIDs: []string{"ami-12345678"},
75-
Region: "us-west-1",
73+
RuleName: "AMI Rule Pass",
74+
AmiIDs: []string{"ami-12345678"},
75+
Region: "us-west-1",
7676
},
7777
expectedResult: types.ValidationRuleResult{
7878
Condition: &vapi.ValidationCondition{

pkg/validators/servicequota/servicequota_validator.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ func (s *RuleService) ReconcileServiceQuotaRule(rule v1alpha1.ServiceQuotaRule)
110110

111111
// Build the default latest condition for this service quota rule
112112
vr := validators.BuildValidationResult(
113-
rule.Name, "Usage for all service quotas is below specified buffer", constants.ValidationTypeServiceQuota,
113+
rule.Name(), "Usage for all service quotas is below specified buffer", constants.ValidationTypeServiceQuota,
114114
)
115115

116116
// Fetch the quota by service code & name & compare against usage

0 commit comments

Comments
 (0)