-
Notifications
You must be signed in to change notification settings - Fork 206
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Inject Hub() function on hub storage resources (#1616)
- Loading branch information
1 parent
2e113ed
commit 4b1363e
Showing
10 changed files
with
357 additions
and
1 deletion.
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
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
55 changes: 55 additions & 0 deletions
55
hack/generator/pkg/codegen/pipeline/inject_hub_function.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,55 @@ | ||
/* | ||
* Copyright (c) Microsoft Corporation. | ||
* Licensed under the MIT license. | ||
*/ | ||
|
||
package pipeline | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/pkg/errors" | ||
|
||
"github.com/Azure/azure-service-operator/hack/generator/pkg/astmodel" | ||
"github.com/Azure/azure-service-operator/hack/generator/pkg/codegen/storage" | ||
"github.com/Azure/azure-service-operator/hack/generator/pkg/functions" | ||
) | ||
|
||
// InjectHubFunctionStageId is the unique identifier for this pipeline stage | ||
const InjectHubFunctionStageId = "injectHubFunction" | ||
|
||
// InjectHubFunction modifies the nominates storage version (aka hub version) of each resource by injecting a Hub() | ||
// function so that it satisfies the required interface. | ||
func InjectHubFunction(idFactory astmodel.IdentifierFactory) Stage { | ||
|
||
result := MakeStage( | ||
InjectHubFunctionStageId, | ||
"Inject the function Hub() into each hub resource", | ||
func(ctx context.Context, types astmodel.Types) (astmodel.Types, error) { | ||
injector := storage.NewFunctionInjector() | ||
result := types.Copy() | ||
|
||
resources := storage.FindResourceTypes(types) | ||
for name, def := range resources { | ||
rt, ok := astmodel.AsResourceType(def.Type()) | ||
if !ok { | ||
return nil, errors.Errorf("expected %s to be a resource type (should never happen)", name) | ||
} | ||
|
||
if rt.IsStorageVersion() { | ||
fn := functions.NewHubFunction(idFactory) | ||
defWithFn, err := injector.Inject(def, fn) | ||
if err != nil { | ||
return nil, errors.Wrapf(err, "injecting Hub() into %s", name) | ||
} | ||
|
||
result[name] = defWithFn | ||
} | ||
} | ||
|
||
return result, nil | ||
}) | ||
|
||
result.RequiresPrerequisiteStages(MarkStorageVersionStageId) | ||
return result | ||
} |
65 changes: 65 additions & 0 deletions
65
hack/generator/pkg/codegen/pipeline/inject_hub_function_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,65 @@ | ||
/* | ||
* Copyright (c) Microsoft Corporation. | ||
* Licensed under the MIT license. | ||
*/ | ||
|
||
package pipeline | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
. "github.com/onsi/gomega" | ||
|
||
"github.com/Azure/azure-service-operator/hack/generator/pkg/astmodel" | ||
"github.com/Azure/azure-service-operator/hack/generator/pkg/test" | ||
) | ||
|
||
func TestInjectHubFunction_WhenResourceIsStorageVersion_GeneratesExpectedFile(t *testing.T) { | ||
g := NewGomegaWithT(t) | ||
|
||
idFactory := astmodel.NewIdentifierFactory() | ||
|
||
// Define a test resource | ||
spec := test.CreateSpec(pkg2020, "Person", fullNameProperty, familyNameProperty, knownAsProperty) | ||
status := test.CreateStatus(pkg2020, "Person") | ||
resource := test.CreateResource(pkg2020, "Person", spec, status) | ||
|
||
resource = resource.WithType( | ||
resource.Type().(*astmodel.ResourceType).MarkAsStorageVersion()) | ||
|
||
types := make(astmodel.Types) | ||
types.AddAll(resource, status, spec) | ||
|
||
injectHubFunction := InjectHubFunction(idFactory) | ||
|
||
// Don't need a context when testing | ||
finalTypes, err := injectHubFunction.Run(context.TODO(), types) | ||
|
||
g.Expect(err).To(Succeed()) | ||
|
||
test.AssertPackagesGenerateExpectedCode(t, finalTypes, t.Name()) | ||
} | ||
|
||
func TestInjectHubFunction_WhenResourceIsNotStorageVersion_GeneratesExpectedFile(t *testing.T) { | ||
g := NewGomegaWithT(t) | ||
|
||
idFactory := astmodel.NewIdentifierFactory() | ||
|
||
// Define a test resource | ||
spec := test.CreateSpec(pkg2020, "Person", fullNameProperty, familyNameProperty, knownAsProperty) | ||
status := test.CreateStatus(pkg2020, "Person") | ||
resource := test.CreateResource(pkg2020, "Person", spec, status) | ||
|
||
types := make(astmodel.Types) | ||
types.AddAll(resource, status, spec) | ||
|
||
injectHubFunction := InjectHubFunction(idFactory) | ||
|
||
// Don't need a context when testing | ||
finalTypes, err := injectHubFunction.Run(context.TODO(), types) | ||
|
||
g.Expect(err).To(Succeed()) | ||
|
||
test.AssertPackagesGenerateExpectedCode(t, finalTypes, t.Name()) | ||
} |
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
41 changes: 41 additions & 0 deletions
41
...tInjectHubFunction_WhenResourceIsNotStorageVersion_GeneratesExpectedFile-v20200101.golden
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,41 @@ | ||
// Code generated by azure-service-operator-codegen. DO NOT EDIT. | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT license. | ||
package v20200101 | ||
|
||
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
|
||
// +kubebuilder:object:root=true | ||
// +kubebuilder:subresource:status | ||
type Person struct { | ||
metav1.TypeMeta `json:",inline"` | ||
metav1.ObjectMeta `json:"metadata,omitempty"` | ||
Spec Person_Spec `json:"spec,omitempty"` | ||
Status Person_Status `json:"status,omitempty"` | ||
} | ||
|
||
// +kubebuilder:object:root=true | ||
type PersonList struct { | ||
metav1.TypeMeta `json:",inline"` | ||
metav1.ListMeta `json:"metadata,omitempty"` | ||
Items []Person `json:"items"` | ||
} | ||
|
||
type Person_Spec struct { | ||
//FamilyName: Shared name of the family | ||
FamilyName string `json:"familyName"` | ||
|
||
//FullName: As would be used to address mail | ||
FullName string `json:"fullName"` | ||
|
||
//KnownAs: How the person is generally known | ||
KnownAs string `json:"knownAs"` | ||
} | ||
|
||
type Person_Status struct { | ||
Status string `json:"status"` | ||
} | ||
|
||
func init() { | ||
SchemeBuilder.Register(&Person{}, &PersonList{}) | ||
} |
48 changes: 48 additions & 0 deletions
48
...TestInjectHubFunction_WhenResourceIsStorageVersion_GeneratesExpectedFile-v20200101.golden
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,48 @@ | ||
// Code generated by azure-service-operator-codegen. DO NOT EDIT. | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT license. | ||
package v20200101 | ||
|
||
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
|
||
// +kubebuilder:rbac:groups=microsoft.person.infra.azure.com,resources=people,verbs=get;list;watch;create;update;patch;delete | ||
// +kubebuilder:rbac:groups=microsoft.person.infra.azure.com,resources={people/status,people/finalizers},verbs=get;update;patch | ||
|
||
// +kubebuilder:object:root=true | ||
// +kubebuilder:subresource:status | ||
// +kubebuilder:storageversion | ||
type Person struct { | ||
metav1.TypeMeta `json:",inline"` | ||
metav1.ObjectMeta `json:"metadata,omitempty"` | ||
Spec Person_Spec `json:"spec,omitempty"` | ||
Status Person_Status `json:"status,omitempty"` | ||
} | ||
|
||
// Hub marks that this Person is the hub type for conversion | ||
func (person *Person) Hub() {} | ||
|
||
// +kubebuilder:object:root=true | ||
type PersonList struct { | ||
metav1.TypeMeta `json:",inline"` | ||
metav1.ListMeta `json:"metadata,omitempty"` | ||
Items []Person `json:"items"` | ||
} | ||
|
||
type Person_Spec struct { | ||
//FamilyName: Shared name of the family | ||
FamilyName string `json:"familyName"` | ||
|
||
//FullName: As would be used to address mail | ||
FullName string `json:"fullName"` | ||
|
||
//KnownAs: How the person is generally known | ||
KnownAs string `json:"knownAs"` | ||
} | ||
|
||
type Person_Status struct { | ||
Status string `json:"status"` | ||
} | ||
|
||
func init() { | ||
SchemeBuilder.Register(&Person{}, &PersonList{}) | ||
} |
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,72 @@ | ||
/* | ||
* Copyright (c) Microsoft Corporation. | ||
* Licensed under the MIT license. | ||
*/ | ||
|
||
package functions | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/dave/dst" | ||
|
||
"github.com/Azure/azure-service-operator/hack/generator/pkg/astbuilder" | ||
"github.com/Azure/azure-service-operator/hack/generator/pkg/astmodel" | ||
) | ||
|
||
// HubFunction generates an empty Hub() function that satisfies the Hub interface required by the controller\ | ||
// See https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/conversion#Hub | ||
type HubFunction struct { | ||
idFactory astmodel.IdentifierFactory | ||
} | ||
|
||
// Ensure HubFunction properly implements Function | ||
var _ astmodel.Function = &HubFunction{} | ||
|
||
// NewHubFunction creates a new instance | ||
func NewHubFunction(idFactory astmodel.IdentifierFactory) *HubFunction { | ||
return &HubFunction{ | ||
idFactory: idFactory, | ||
} | ||
} | ||
|
||
// Name returns the hard coded name of the function | ||
func (h HubFunction) Name() string { | ||
return "Hub" | ||
} | ||
|
||
// RequiredPackageReferences indicates that this function has no required packages | ||
func (h HubFunction) RequiredPackageReferences() *astmodel.PackageReferenceSet { | ||
return astmodel.NewPackageReferenceSet() | ||
} | ||
|
||
// References indicates that this function references no types | ||
func (h HubFunction) References() astmodel.TypeNameSet { | ||
return astmodel.NewTypeNameSet() | ||
} | ||
|
||
// AsFunc generates the required code | ||
func (h HubFunction) AsFunc(generationContext *astmodel.CodeGenerationContext, receiver astmodel.TypeName) *dst.FuncDecl { | ||
// Create a sensible name for our receiver | ||
receiverName := h.idFactory.CreateIdentifier(receiver.Name(), astmodel.NotExported) | ||
|
||
// We always use a pointer receiver so we can modify it | ||
receiverType := astmodel.NewOptionalType(receiver).AsType(generationContext) | ||
|
||
details := astbuilder.FuncDetails{ | ||
ReceiverIdent: receiverName, | ||
ReceiverType: receiverType, | ||
Name: h.Name(), | ||
Body: []dst.Stmt{}, // empty body | ||
} | ||
|
||
details.AddComments(fmt.Sprintf("marks that this %s is the hub type for conversion", receiver.Name())) | ||
|
||
return details.DefineFunc() | ||
} | ||
|
||
// Equals shows that any hub function is equal to any other | ||
func (h HubFunction) Equals(f astmodel.Function) bool { | ||
_, ok := f.(*HubFunction) | ||
return ok | ||
} |
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,33 @@ | ||
/* | ||
* Copyright (c) Microsoft Corporation. | ||
* Licensed under the MIT license. | ||
*/ | ||
|
||
package functions | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/Azure/azure-service-operator/hack/generator/pkg/astmodel" | ||
"github.com/Azure/azure-service-operator/hack/generator/pkg/test" | ||
) | ||
|
||
func Test_HubFunction_GeneratesExpectedCode(t *testing.T) { | ||
idFactory := astmodel.NewIdentifierFactory() | ||
|
||
testGroup := "microsoft.person" | ||
testPackage := test.MakeLocalPackageReference(testGroup, "v20200101") | ||
|
||
fullNameProperty := astmodel.NewPropertyDefinition("FullName", "fullName", astmodel.StringType). | ||
WithDescription("As would be used to address mail") | ||
|
||
hubFunction := NewHubFunction(idFactory) | ||
|
||
// Define a test resource | ||
spec := test.CreateSpec(testPackage, "Person", fullNameProperty) | ||
status := test.CreateStatus(testPackage, "Person") | ||
resource := test.CreateResource(testPackage, "Person", spec, status, hubFunction) | ||
|
||
fileDef := test.CreateFileDefinition(resource) | ||
test.AssertFileGeneratesExpectedCode(t, fileDef, t.Name()) | ||
} |
29 changes: 29 additions & 0 deletions
29
hack/generator/pkg/functions/testdata/Test_HubFunction_GeneratesExpectedCode.golden
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,29 @@ | ||
// Code generated by azure-service-operator-codegen. DO NOT EDIT. | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT license. | ||
package v20200101 | ||
|
||
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
|
||
// +kubebuilder:object:root=true | ||
// +kubebuilder:subresource:status | ||
type Person struct { | ||
metav1.TypeMeta `json:",inline"` | ||
metav1.ObjectMeta `json:"metadata,omitempty"` | ||
Spec Person_Spec `json:"spec,omitempty"` | ||
Status Person_Status `json:"status,omitempty"` | ||
} | ||
|
||
// Hub marks that this Person is the hub type for conversion | ||
func (person *Person) Hub() {} | ||
|
||
// +kubebuilder:object:root=true | ||
type PersonList struct { | ||
metav1.TypeMeta `json:",inline"` | ||
metav1.ListMeta `json:"metadata,omitempty"` | ||
Items []Person `json:"items"` | ||
} | ||
|
||
func init() { | ||
SchemeBuilder.Register(&Person{}, &PersonList{}) | ||
} |