-
Notifications
You must be signed in to change notification settings - Fork 203
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ResourceReference Validator (#1513)
- Loading branch information
Showing
25 changed files
with
749 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
117 changes: 117 additions & 0 deletions
117
hack/generated/pkg/genruntime/resource_reference_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
/* | ||
Copyright (c) Microsoft Corporation. | ||
Licensed under the MIT license. | ||
*/ | ||
|
||
package genruntime_test | ||
|
||
import ( | ||
"testing" | ||
|
||
. "github.com/onsi/gomega" | ||
|
||
"github.com/Azure/azure-service-operator/hack/generated/pkg/genruntime" | ||
) | ||
|
||
var validARMIDRef = genruntime.ResourceReference{ARMID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg/providers/microsoft.compute/VirtualMachine/myvm"} | ||
var validKubRef = genruntime.ResourceReference{Group: "microsoft.resources.infra.azure.com", Kind: "ResourceGroup", Namespace: "default", Name: "myrg"} | ||
var invalidRefBothSpecified = genruntime.ResourceReference{Group: "microsoft.resources.infra.azure.com", Kind: "ResourceGroup", Namespace: "default", Name: "myrg", ARMID: "oops"} | ||
var invalidRefNeitherSpecified = genruntime.ResourceReference{} | ||
var invalidRefIncompleteKubReference = genruntime.ResourceReference{Group: "microsoft.resources.infra.azure.com", Namespace: "default", Name: "myrg"} | ||
|
||
func Test_ResourceReference_Validate(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
ref genruntime.ResourceReference | ||
errSubstring string | ||
}{ | ||
{ | ||
name: "valid ARM reference is valid", | ||
ref: validARMIDRef, | ||
errSubstring: "", | ||
}, | ||
{ | ||
name: "valid Kubernetes reference is valid", | ||
ref: validKubRef, | ||
errSubstring: "", | ||
}, | ||
{ | ||
name: "both ARM and Kubernetes fields filled out, reference is invalid", | ||
ref: invalidRefBothSpecified, | ||
errSubstring: "'ARMID' field is mutually exclusive with", | ||
}, | ||
{ | ||
name: "nothing filled out, reference is invalid", | ||
ref: invalidRefNeitherSpecified, | ||
errSubstring: "at least one of ['ARMID'] or ['Group', 'Kind', 'Namespace', 'Name'] must be set for ResourceReference", | ||
}, | ||
{ | ||
name: "incomplete Kubernetes reference is invalid", | ||
ref: invalidRefIncompleteKubReference, | ||
errSubstring: "'Group', 'Kind', 'Namespace', and 'Name' must all be specified", | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
g := NewWithT(t) | ||
|
||
err := tt.ref.Validate() | ||
if tt.errSubstring != "" { | ||
g.Expect(err).To(HaveOccurred()) | ||
g.Expect(err.Error()).To(ContainSubstring(tt.errSubstring)) | ||
} else { | ||
g.Expect(err).ToNot(HaveOccurred()) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func Test_ResourceReference_IsARMOrKubernetes(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
ref genruntime.ResourceReference | ||
isARM bool | ||
isKubernetes bool | ||
}{ | ||
{ | ||
name: "valid ARM reference is ARM", | ||
ref: validARMIDRef, | ||
isARM: true, | ||
isKubernetes: false, | ||
}, | ||
{ | ||
name: "valid Kubernetes reference is Kubernetes", | ||
ref: validKubRef, | ||
isARM: false, | ||
isKubernetes: true, | ||
}, | ||
{ | ||
name: "both ARM and Kubernetes fields filled out, reference is neither", | ||
ref: invalidRefBothSpecified, | ||
isARM: false, | ||
isKubernetes: false, | ||
}, | ||
{ | ||
name: "nothing filled out, reference is neither", | ||
ref: invalidRefNeitherSpecified, | ||
isARM: false, | ||
isKubernetes: false, | ||
}, | ||
{ | ||
name: "incomplete Kubernetes reference is neither", | ||
ref: invalidRefIncompleteKubReference, | ||
isARM: false, | ||
isKubernetes: false, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
g := NewWithT(t) | ||
|
||
g.Expect(tt.ref.IsDirectARMReference()).To(Equal(tt.isARM)) | ||
g.Expect(tt.ref.IsKubernetesReference()).To(Equal(tt.isKubernetes)) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
85 changes: 85 additions & 0 deletions
85
hack/generator/pkg/astmodel/kubernetes_admissions_validations.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
/* | ||
* Copyright (c) Microsoft Corporation. | ||
* Licensed under the MIT license. | ||
*/ | ||
|
||
package astmodel | ||
|
||
import ( | ||
"go/token" | ||
|
||
"github.com/dave/dst" | ||
|
||
"github.com/Azure/azure-service-operator/hack/generator/pkg/astbuilder" | ||
) | ||
|
||
func NewValidateResourceReferencesFunction(resource *ResourceType, idFactory IdentifierFactory) *resourceFunction { | ||
return &resourceFunction{ | ||
name: "validateResourceReferences", | ||
resource: resource, | ||
idFactory: idFactory, | ||
asFunc: validateResourceReferences, | ||
requiredPackages: NewPackageReferenceSet(GenRuntimeReference, ReflectHelpersReference), | ||
} | ||
} | ||
|
||
func validateResourceReferences(k *resourceFunction, codeGenerationContext *CodeGenerationContext, receiver TypeName, methodName string) *dst.FuncDecl { | ||
receiverIdent := k.idFactory.CreateIdentifier(receiver.Name(), NotExported) | ||
receiverType := receiver.AsType(codeGenerationContext) | ||
|
||
fn := &astbuilder.FuncDetails{ | ||
Name: methodName, | ||
ReceiverIdent: receiverIdent, | ||
ReceiverType: &dst.StarExpr{ | ||
X: receiverType, | ||
}, | ||
Returns: []*dst.Field{ | ||
{ | ||
Type: dst.NewIdent("error"), | ||
}, | ||
}, | ||
Body: validateResourceReferencesBody(codeGenerationContext, receiverIdent), | ||
} | ||
|
||
fn.AddComments("validates all resource references") | ||
return fn.DefineFunc() | ||
} | ||
|
||
// validateResourceReferencesBody helps generate the body of the validateResourceReferences function: | ||
// refs, err := reflecthelpers.FindResourceReferences(&<resource>.Spec) | ||
// if err != nil { | ||
// return err | ||
// } | ||
// return genruntime.ValidateResourceReferences(refs) | ||
func validateResourceReferencesBody(codeGenerationContext *CodeGenerationContext, receiverIdent string) []dst.Stmt { | ||
reflectHelpers, err := codeGenerationContext.GetImportedPackageName(ReflectHelpersReference) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
genRuntime, err := codeGenerationContext.GetImportedPackageName(GenRuntimeReference) | ||
if err != nil { | ||
panic(err) | ||
} | ||
var body []dst.Stmt | ||
|
||
body = append( | ||
body, | ||
astbuilder.SimpleAssignmentWithErr( | ||
dst.NewIdent("refs"), | ||
token.DEFINE, | ||
astbuilder.CallQualifiedFunc( | ||
reflectHelpers, | ||
"FindResourceReferences", | ||
astbuilder.AddrOf(astbuilder.Selector(dst.NewIdent(receiverIdent), "Spec"))))) | ||
body = append(body, astbuilder.CheckErrorAndReturn()) | ||
body = append( | ||
body, | ||
astbuilder.Returns( | ||
astbuilder.CallQualifiedFunc( | ||
genRuntime, | ||
"ValidateResourceReferences", | ||
dst.NewIdent("refs")))) | ||
|
||
return body | ||
} |
Oops, something went wrong.