Skip to content

Commit

Permalink
Implement pipeline stage to inject the Hub() function and test
Browse files Browse the repository at this point in the history
  • Loading branch information
theunrepentantgeek committed Jul 5, 2021
1 parent 7475299 commit 94ee4d9
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 0 deletions.
55 changes: 55 additions & 0 deletions hack/generator/pkg/codegen/pipeline/inject_hub_function.go
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 hack/generator/pkg/codegen/pipeline/inject_hub_function_test.go
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())
}
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{})
}
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{})
}

0 comments on commit 94ee4d9

Please sign in to comment.