Skip to content
This repository has been archived by the owner on Apr 11, 2024. It is now read-only.

Commit

Permalink
test: unit test for individual patch generator (#21)
Browse files Browse the repository at this point in the history
* test: unit test for individual patch generator

* test: package level unit test for HTTPProxy

* test: fix data race between multiple unit test that use envtest

* test: make patchgenerator generic function

* fix: linting errors after rebase from main
  • Loading branch information
supershal authored and jimmidyson committed Apr 11, 2024
1 parent bf9280c commit 5e7fe95
Show file tree
Hide file tree
Showing 12 changed files with 196 additions and 56 deletions.
26 changes: 20 additions & 6 deletions api/v1alpha1/nutanix_node_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,27 @@ func (NutanixMachineDetails) VariableSchema() clusterv1.VariableSchema {
Description: "memorySize is the memory size (in Quantity format) of the VM eg. 4Gi",
Type: "string",
},
"image": NutanixResourceIdentifier{}.VariableSchema().OpenAPIV3Schema,
"cluster": NutanixResourceIdentifier{}.VariableSchema().OpenAPIV3Schema,
"subnets": NutanixResourceIdentifiers{}.VariableSchema().OpenAPIV3Schema,
"bootType": NutanixBootType(capxv1.NutanixBootTypeLegacy).VariableSchema().OpenAPIV3Schema,
"image": NutanixResourceIdentifier{}.VariableSchema().OpenAPIV3Schema,
"cluster": NutanixResourceIdentifier{}.VariableSchema().OpenAPIV3Schema,
"subnets": NutanixResourceIdentifiers{}.VariableSchema().OpenAPIV3Schema,
"bootType": NutanixBootType(
capxv1.NutanixBootTypeLegacy,
).VariableSchema().
OpenAPIV3Schema,
"systemDiskSize": {
Description: "systemDiskSize is size (in Quantity format) of the system disk of the VM eg. 20Gi",
Type: "string",
},
},
Required: []string{"vcpusPerSocket", "vcpuSockets", "memorySize", "image", "cluster", "subnets", "systemDiskSize"},
Required: []string{
"vcpusPerSocket",
"vcpuSockets",
"memorySize",
"image",
"cluster",
"subnets",
"systemDiskSize",
},
},
}
}
Expand Down Expand Up @@ -134,7 +145,10 @@ func (NutanixResourceIdentifier) VariableSchema() clusterv1.VariableSchema {
Description: "Nutanix Resource Identifier",
Type: "object",
Properties: map[string]clusterv1.JSONSchemaProps{
"type": NutanixIdentifierType(capxv1.NutanixIdentifierName).VariableSchema().OpenAPIV3Schema,
"type": NutanixIdentifierType(
capxv1.NutanixIdentifierName,
).VariableSchema().
OpenAPIV3Schema,
"uuid": {
Type: "string",
Description: "uuid is the UUID of the resource in the PC.",
Expand Down
4 changes: 4 additions & 0 deletions common/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ require (
github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/api v0.0.0-00010101000000-000000000000
github.com/evanphx/json-patch/v5 v5.9.0
github.com/go-logr/logr v1.4.1
github.com/onsi/ginkgo/v2 v2.15.0
github.com/onsi/gomega v1.31.1
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.9.0
Expand All @@ -36,13 +37,15 @@ require (
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/cel-go v0.17.7 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/josharian/intern v1.0.0 // indirect
Expand All @@ -69,6 +72,7 @@ require (
golang.org/x/term v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.16.1 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect
Expand Down
1 change: 0 additions & 1 deletion common/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,6 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU=
Expand Down
86 changes: 44 additions & 42 deletions common/pkg/testutils/capitest/patches.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
"context"
"encoding/json"
"fmt"
"testing"

. "github.com/onsi/ginkgo/v2"
"github.com/onsi/gomega"
"github.com/onsi/gomega/gstruct"
gomegatypes "github.com/onsi/gomega/types"
Expand Down Expand Up @@ -39,55 +39,57 @@ type JSONPatchMatcher struct {
}

func ValidateGeneratePatches[T mutation.GeneratePatches](
t *testing.T,
t GinkgoTInterface,
handlerCreator func() T,
testDefs ...PatchTestDef,
) {
t.Helper()
testFunc := func(tt *PatchTestDef) {
g := gomega.NewWithT(t)
h := handlerCreator()
req := &runtimehooksv1.GeneratePatchesRequest{
Variables: tt.Vars,
Items: []runtimehooksv1.GeneratePatchesRequestItem{
tt.RequestItem,
{
HolderReference: runtimehooksv1.HolderReference{
APIVersion: capiv1.GroupVersion.String(),
Kind: "Cluster",
Namespace: request.Namespace,
Name: request.ClusterName,
},
},
},
}
resp := &runtimehooksv1.GeneratePatchesResponse{}
h.GeneratePatches(context.Background(), req, resp)
expectedStatus := runtimehooksv1.ResponseStatusSuccess
if tt.ExpectedFailure {
expectedStatus = runtimehooksv1.ResponseStatusFailure
}
g.Expect(resp.Status).
To(gomega.Equal(expectedStatus), fmt.Sprintf("Message: %s", resp.Message))

if len(tt.ExpectedPatchMatchers) == 0 {
g.Expect(resp.Items).To(gomega.BeEmpty())
return
}
g.Expect(resp.Items).To(containPatches(&tt.RequestItem, tt.ExpectedPatchMatchers...))

if len(tt.UnexpectedPatchMatchers) > 0 {
g.Expect(resp.Items).
ToNot(containPatches(&tt.RequestItem, tt.UnexpectedPatchMatchers...))
}
}

// compose Ginkgo table arguments
// https://onsi.github.io/ginkgo/#table-specs for more details
testArgs := make([]TableEntry, 0, len(testDefs))
for testIdx := range testDefs {
tt := testDefs[testIdx]

t.Run(tt.Name, func(t *testing.T) {
t.Parallel()

g := gomega.NewWithT(t)
h := handlerCreator()
req := &runtimehooksv1.GeneratePatchesRequest{
Variables: tt.Vars,
Items: []runtimehooksv1.GeneratePatchesRequestItem{
tt.RequestItem,
{
HolderReference: runtimehooksv1.HolderReference{
APIVersion: capiv1.GroupVersion.String(),
Kind: "Cluster",
Namespace: request.Namespace,
Name: request.ClusterName,
},
},
},
}
resp := &runtimehooksv1.GeneratePatchesResponse{}
h.GeneratePatches(context.Background(), req, resp)
expectedStatus := runtimehooksv1.ResponseStatusSuccess
if tt.ExpectedFailure {
expectedStatus = runtimehooksv1.ResponseStatusFailure
}
g.Expect(resp.Status).
To(gomega.Equal(expectedStatus), fmt.Sprintf("Message: %s", resp.Message))

if len(tt.ExpectedPatchMatchers) == 0 {
g.Expect(resp.Items).To(gomega.BeEmpty())
return
}
g.Expect(resp.Items).To(containPatches(&tt.RequestItem, tt.ExpectedPatchMatchers...))

if len(tt.UnexpectedPatchMatchers) > 0 {
g.Expect(resp.Items).
ToNot(containPatches(&tt.RequestItem, tt.UnexpectedPatchMatchers...))
}
})
testArgs = append(testArgs, Entry(tt.Name, &tt))
}
DescribeTable("Patches", testFunc, testArgs)
}

// VariableWithValue returns a runtimehooksv1.Variable with the passed name and value.
Expand Down
35 changes: 35 additions & 0 deletions pkg/handlers/aws/mutation/region/inject_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2023 D2iQ, Inc. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

package region

import (
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/api/v1alpha1"
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/common/pkg/capi/clustertopology/handlers/mutation"
regiontests "github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/aws/mutation/region/tests"
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/clusterconfig"
)

func TestRegionPatch(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "AWS Region mutator suite")
}

var _ = Describe("Generate AWS Region patches", func() {
// only add aws region patch
patchGenerator := func() mutation.GeneratePatches {
return mutation.NewMetaGeneratePatchesHandler("", NewPatch()).(mutation.GeneratePatches)
}
regiontests.TestGeneratePatches(
GinkgoT(),
patchGenerator,
clusterconfig.MetaVariableName,
v1alpha1.AWSVariableName,
VariableName,
)
})
5 changes: 2 additions & 3 deletions pkg/handlers/aws/mutation/region/tests/generate_patches.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
package tests

import (
"testing"

. "github.com/onsi/ginkgo/v2"
"github.com/onsi/gomega"
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"

Expand All @@ -15,7 +14,7 @@ import (
)

func TestGeneratePatches(
t *testing.T,
t GinkgoTInterface,
generatorFunc func() mutation.GeneratePatches,
variableName string,
variablePath ...string,
Expand Down
8 changes: 7 additions & 1 deletion pkg/handlers/generic/lifecycle/ccm/aws/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,13 @@ func (a *AWSCCM) Apply(
)
}

err = lifecycleutils.EnsureCRSForClusterFromObjects(ctx, ccmConfigMap.Name, a.client, cluster, ccmConfigMap)
err = lifecycleutils.EnsureCRSForClusterFromObjects(
ctx,
ccmConfigMap.Name,
a.client,
cluster,
ccmConfigMap,
)
if err != nil {
return fmt.Errorf("failed to generate CCM CRS for cluster: %w", err)
}
Expand Down
29 changes: 29 additions & 0 deletions pkg/handlers/generic/mutation/httpproxy/inject_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@ package httpproxy
import (
"testing"

. "github.com/onsi/ginkgo/v2"
"github.com/onsi/gomega"
v1 "k8s.io/api/core/v1"
capiv1 "sigs.k8s.io/cluster-api/api/v1beta1"

"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/common/pkg/capi/clustertopology/handlers/mutation"
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/clusterconfig"
httpproxy "github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/mutation/httpproxy/tests"
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/test/helpers"
)

func TestGenerateNoProxy(t *testing.T) {
Expand Down Expand Up @@ -179,3 +185,26 @@ func TestGenerateNoProxy(t *testing.T) {
})
}
}

func TestHTTPProxyPatch(t *testing.T) {
gomega.RegisterFailHandler(Fail)
RunSpecs(t, "HTTP Proxy mutator suite")
}

var _ = Describe("Generate HTTPProxy Patches", func() {
// only add HTTPProxy patch
patchGenerator := func() mutation.GeneratePatches {
// Always initialize the testEnv variable in the closure.
// This will allow ginkgo to initialize testEnv variable during test execution time.
testEnv := helpers.TestEnv
return mutation.NewMetaGeneratePatchesHandler(
"",
NewPatch(testEnv.Client)).(mutation.GeneratePatches)
}
httpproxy.TestGeneratePatches(
GinkgoT(),
patchGenerator,
clusterconfig.MetaVariableName,
VariableName,
)
})
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
package tests

import (
"testing"

. "github.com/onsi/ginkgo/v2"
"github.com/onsi/gomega"
"k8s.io/apiserver/pkg/storage/names"
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
Expand All @@ -17,7 +16,7 @@ import (
)

func TestGeneratePatches(
t *testing.T,
t GinkgoTInterface,
generatorFunc func() mutation.GeneratePatches,
variableName string,
variablePath ...string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/common/pkg/testutils/capitest/request"
)

//
//nolint:lll // just a long string
const testCertBundle = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVjekNDQTF1Z0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRUUZBRC4uQWtHQTFVRUJoTUNSMEl4CkV6QVJCZ05WQkFnVENsTnZiV1V0VTNSaGRHVXhGREFTQmdOVkJBb1RDMC4uMEVnVEhSa01UY3dOUVlEClZRUUxFeTVEYkdGemN5QXhJRkIxWW14cFl5QlFjbWx0WVhKNUlFTmxjbi4uWFJwYjI0Z1FYVjBhRzl5CmFYUjVNUlF3RWdZRFZRUURFd3RDWlhOMElFTkJJRXgwWkRBZUZ3MHdNRC4uVFV3TVRaYUZ3MHdNVEF5Ck1EUXhPVFV3TVRaYU1JR0hNUXN3Q1FZRFZRUUdFd0pIUWpFVE1CRUdBMS4uMjl0WlMxVGRHRjBaVEVVCk1CSUdBMVVFQ2hNTFFtVnpkQ0JEUVNCTWRHUXhOekExQmdOVkJBc1RMay4uREVnVUhWaWJHbGpJRkJ5CmFXMWhjbmtnUTJWeWRHbG1hV05oZEdsdmJpQkJkWFJvYjNKcGRIa3hGRC4uQU1UQzBKbGMzUWdRMEVnClRIUmtNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZy4uVHoybXI3U1ppQU1mUXl1CnZCak05T2lKalJhelhCWjFCalA1Q0UvV20vUnI1MDBQUksrTGg5eDVlSi4uL0FOQkUwc1RLMFpzREdNCmFrMm0xZzdvcnVJM2RZM1ZIcUl4RlR6MFRhMWQrTkFqd25MZTRuT2I3Ly4uazA1U2hoQnJKR0JLS3hiCjhuMTA0by81cDhIQXNaUGR6YkZNSXlOakp6Qk0ybzV5NUExM3dpTGl0RS4uZnlZa1F6YXhDdzBBd3psCmtWSGlJeUN1YUY0d2o1NzFwU3prdjZzdis0SURNYlQvWHBDbzhMNndUYS4uc2grZXRMRDZGdFRqWWJiCnJ2WjhSUU0xdGxLZG9NSGcycXhyYUFWKytITkJZbU5XczBkdUVkalViSi4uWEk5VHRuUzRvMUNrajdQCk9mbGppUUlEQVFBQm80SG5NSUhrTUIwR0ExVWREZ1FXQkJROHVyTUNSTC4uNUFrSXA5TkpISnc1VENCCnRBWURWUjBqQklHc01JR3BnQlE4dXJNQ1JMWVlNSFVLVTVBa0lwOU5KSC4uYVNCaWpDQmh6RUxNQWtHCkExVUVCaE1DUjBJeEV6QVJCZ05WQkFnVENsTnZiV1V0VTNSaGRHVXhGRC4uQW9UQzBKbGMzUWdRMEVnClRIUmtNVGN3TlFZRFZRUUxFeTVEYkdGemN5QXhJRkIxWW14cFl5QlFjbS4uRU5sY25ScFptbGpZWFJwCmIyNGdRWFYwYUc5eWFYUjVNUlF3RWdZRFZRUURFd3RDWlhOMElFTkJJRS4uREFNQmdOVkhSTUVCVEFECkFRSC9NQTBHQ1NxR1NJYjNEUUVCQkFVQUE0SUJBUUMxdVlCY3NTbmN3QS4uRENzUWVyNzcyQzJ1Y3BYCnhRVUUvQzBwV1dtNmdEa3dkNUQwRFNNREpScVYvd2VvWjR3QzZCNzNmNS4uYkxoR1lIYVhKZVNENktyClhjb093TGRTYUdtSllzbExLWkIzWklERXAwd1lUR2hndGViNkpGaVR0bi4uc2YyeGRyWWZQQ2lJQjdnCkJNQVY3R3pkYzRWc3BTNmxqckFoYmlpYXdkQmlRbFFtc0JlRno5SmtGNC4uYjNsOEJvR04rcU1hNTZZCkl0OHVuYTJnWTRsMk8vL29uODhyNUlXSmxtMUwwb0E4ZTRmUjJ5ckJIWC4uYWRzR2VGS2t5TnJ3R2kvCjd2UU1mWGRHc1JyWE5HUkduWCt2V0RaMy96V0kwam9EdENrTm5xRXBWbi4uSG9YCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0="

Expand Down
49 changes: 49 additions & 0 deletions test/helpers/environment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2023 D2iQ, Inc. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

package helpers

import (
"context"
"time"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"k8s.io/klog/v2"
"k8s.io/klog/v2/textlogger"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/log"
)

var TestEnv *TestEnvironment

// Initialize the test environment. BeforeSuite will be only executed if this package is loaded by the test.
var _ = BeforeSuite(func(ctx SpecContext) {
By("Initialize loggers for testing")
// Uninitialized logger spits stacktrace as warning during test execution
logger := textlogger.NewLogger(textlogger.NewConfig())
// use klog as the internal logger for this envtest environment.
log.SetLogger(logger)
// additionally force all of the controllers to use the Ginkgo logger.
ctrl.SetLogger(logger)
klog.InitFlags(nil)
// add logger for ginkgo
klog.SetOutput(GinkgoWriter)

By("Starting test environment")
testEnvConfig := NewTestEnvironmentConfiguration()
var err error
TestEnv, err = testEnvConfig.Build()
if err != nil {
panic(err)
}
By("Starting the manager")
go func() {
defer GinkgoRecover()
Expect(TestEnv.StartManager(ctx)).To(Succeed())
}()
}, NodeTimeout(60*time.Second))

var _ = AfterSuite(func(ctx context.Context) {
Expect(TestEnv.Stop()).To(Succeed())
})
3 changes: 3 additions & 0 deletions test/helpers/envtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ func (t *TestEnvironment) StartManager(ctx context.Context) error {

// Stop stops the test environment.
func (t *TestEnvironment) Stop() error {
if t.cancel != nil {
t.cancel()
}
return t.env.Stop()
}

Expand Down

0 comments on commit 5e7fe95

Please sign in to comment.