From 94ee4d9c80eb407a802eb0ba9e01e56a928dd339 Mon Sep 17 00:00:00 2001 From: Bevan Arps Date: Thu, 1 Jul 2021 15:44:35 +1200 Subject: [PATCH] Implement pipeline stage to inject the Hub() function and test --- .../codegen/pipeline/inject_hub_function.go | 55 ++++++++++++++++ .../pipeline/inject_hub_function_test.go | 65 +++++++++++++++++++ ...ion_GeneratesExpectedFile-v20200101.golden | 41 ++++++++++++ ...ion_GeneratesExpectedFile-v20200101.golden | 48 ++++++++++++++ 4 files changed, 209 insertions(+) create mode 100644 hack/generator/pkg/codegen/pipeline/inject_hub_function.go create mode 100644 hack/generator/pkg/codegen/pipeline/inject_hub_function_test.go create mode 100644 hack/generator/pkg/codegen/pipeline/testdata/TestInjectHubFunction_WhenResourceIsNotStorageVersion_GeneratesExpectedFile-v20200101.golden create mode 100644 hack/generator/pkg/codegen/pipeline/testdata/TestInjectHubFunction_WhenResourceIsStorageVersion_GeneratesExpectedFile-v20200101.golden diff --git a/hack/generator/pkg/codegen/pipeline/inject_hub_function.go b/hack/generator/pkg/codegen/pipeline/inject_hub_function.go new file mode 100644 index 00000000000..1a641b7efea --- /dev/null +++ b/hack/generator/pkg/codegen/pipeline/inject_hub_function.go @@ -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 +} diff --git a/hack/generator/pkg/codegen/pipeline/inject_hub_function_test.go b/hack/generator/pkg/codegen/pipeline/inject_hub_function_test.go new file mode 100644 index 00000000000..5fbbf983e14 --- /dev/null +++ b/hack/generator/pkg/codegen/pipeline/inject_hub_function_test.go @@ -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()) +} diff --git a/hack/generator/pkg/codegen/pipeline/testdata/TestInjectHubFunction_WhenResourceIsNotStorageVersion_GeneratesExpectedFile-v20200101.golden b/hack/generator/pkg/codegen/pipeline/testdata/TestInjectHubFunction_WhenResourceIsNotStorageVersion_GeneratesExpectedFile-v20200101.golden new file mode 100644 index 00000000000..07ac0e28703 --- /dev/null +++ b/hack/generator/pkg/codegen/pipeline/testdata/TestInjectHubFunction_WhenResourceIsNotStorageVersion_GeneratesExpectedFile-v20200101.golden @@ -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{}) +} diff --git a/hack/generator/pkg/codegen/pipeline/testdata/TestInjectHubFunction_WhenResourceIsStorageVersion_GeneratesExpectedFile-v20200101.golden b/hack/generator/pkg/codegen/pipeline/testdata/TestInjectHubFunction_WhenResourceIsStorageVersion_GeneratesExpectedFile-v20200101.golden new file mode 100644 index 00000000000..41d168edf03 --- /dev/null +++ b/hack/generator/pkg/codegen/pipeline/testdata/TestInjectHubFunction_WhenResourceIsStorageVersion_GeneratesExpectedFile-v20200101.golden @@ -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{}) +}