Skip to content

Commit

Permalink
Add unit tests for reconcile_state, cluster_controller, & conditions
Browse files Browse the repository at this point in the history
  • Loading branch information
willie-yao authored and sbueringer committed Sep 21, 2023
1 parent 321096f commit 1ae8a33
Show file tree
Hide file tree
Showing 9 changed files with 1,248 additions and 41 deletions.
1 change: 1 addition & 0 deletions controllers/remote/cluster_cache_tracker_fake.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func NewTestClusterCacheTracker(log logr.Logger, cl client.Client, scheme *runti
client: cl,
scheme: scheme,
clusterAccessors: make(map[client.ObjectKey]*clusterAccessor),
clusterLock: newKeyedMutex(),
}

testCacheTracker.clusterAccessors[objKey] = &clusterAccessor{
Expand Down
237 changes: 219 additions & 18 deletions internal/controllers/topology/cluster/cluster_controller_test.go

Large diffs are not rendered by default.

335 changes: 329 additions & 6 deletions internal/controllers/topology/cluster/conditions_test.go

Large diffs are not rendered by default.

551 changes: 549 additions & 2 deletions internal/controllers/topology/cluster/reconcile_state_test.go

Large diffs are not rendered by default.

34 changes: 33 additions & 1 deletion internal/controllers/topology/cluster/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"time"

. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
Expand All @@ -33,6 +34,7 @@ import (

clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/api/v1beta1/index"
"sigs.k8s.io/cluster-api/controllers/remote"
expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1"
"sigs.k8s.io/cluster-api/internal/controllers/clusterclass"
"sigs.k8s.io/cluster-api/internal/test/envtest"
Expand All @@ -49,6 +51,7 @@ func init() {
_ = clusterv1.AddToScheme(fakeScheme)
_ = apiextensionsv1.AddToScheme(fakeScheme)
_ = expv1.AddToScheme(fakeScheme)
_ = corev1.AddToScheme(fakeScheme)
}
func TestMain(m *testing.M) {
setupIndexes := func(ctx context.Context, mgr ctrl.Manager) {
Expand All @@ -71,11 +74,40 @@ func TestMain(m *testing.M) {
if err != nil {
panic(fmt.Sprintf("unable to create unstructuredCachineClient: %v", err))
}
// Set up a ClusterCacheTracker and ClusterCacheReconciler to provide to controllers
// requiring a connection to a remote cluster
log := ctrl.Log.WithName("remote").WithName("ClusterCacheTracker")
secretCachingClient, err := client.New(mgr.GetConfig(), client.Options{
HTTPClient: mgr.GetHTTPClient(),
Cache: &client.CacheOptions{
Reader: mgr.GetCache(),
},
})
if err != nil {
panic(fmt.Sprintf("unable to create secretCachingClient: %v", err))
}
tracker, err := remote.NewClusterCacheTracker(
mgr,
remote.ClusterCacheTrackerOptions{
Log: &log,
SecretCachingClient: secretCachingClient,
},
)
if err != nil {
panic(fmt.Sprintf("unable to create cluster cache tracker: %v", err))
}
if err := (&remote.ClusterCacheReconciler{
Client: mgr.GetClient(),
Tracker: tracker,
}).SetupWithManager(ctx, mgr, controller.Options{MaxConcurrentReconciles: 1}); err != nil {
panic(fmt.Sprintf("Failed to start ClusterCacheReconciler: %v", err))
}
if err := (&Reconciler{
Client: mgr.GetClient(),
APIReader: mgr.GetAPIReader(),
UnstructuredCachingClient: unstructuredCachingClient,
}).SetupWithManager(ctx, mgr, controller.Options{MaxConcurrentReconciles: 5}); err != nil {
Tracker: tracker,
}).SetupWithManager(ctx, mgr, controller.Options{MaxConcurrentReconciles: 1}); err != nil {
panic(fmt.Sprintf("unable to create topology cluster reconciler: %v", err))
}
if err := (&clusterclass.Reconciler{
Expand Down
47 changes: 33 additions & 14 deletions internal/test/builder/builders.go
Original file line number Diff line number Diff line change
Expand Up @@ -1440,15 +1440,16 @@ func (c *TestControlPlaneBuilder) Build() *unstructured.Unstructured {

// MachinePoolBuilder holds the variables and objects needed to build a generic MachinePool.
type MachinePoolBuilder struct {
namespace string
name string
bootstrap *unstructured.Unstructured
infrastructure *unstructured.Unstructured
version *string
clusterName string
replicas *int32
labels map[string]string
status *expv1.MachinePoolStatus
namespace string
name string
bootstrap *unstructured.Unstructured
infrastructure *unstructured.Unstructured
version *string
clusterName string
replicas *int32
labels map[string]string
status *expv1.MachinePoolStatus
minReadySeconds *int32
}

// MachinePool creates a MachinePoolBuilder with the given name and namespace.
Expand Down Expand Up @@ -1501,6 +1502,12 @@ func (m *MachinePoolBuilder) WithStatus(status expv1.MachinePoolStatus) *Machine
return m
}

// WithMinReadySeconds sets the passed value on the machine pool spec.
func (m *MachinePoolBuilder) WithMinReadySeconds(minReadySeconds int32) *MachinePoolBuilder {
m.minReadySeconds = &minReadySeconds
return m
}

// Build creates a new MachinePool with the variables and objects passed to the MachinePoolBuilder.
func (m *MachinePoolBuilder) Build() *expv1.MachinePool {
obj := &expv1.MachinePool{
Expand All @@ -1514,8 +1521,15 @@ func (m *MachinePoolBuilder) Build() *expv1.MachinePool {
Labels: m.labels,
},
Spec: expv1.MachinePoolSpec{
ClusterName: m.clusterName,
Replicas: m.replicas,
ClusterName: m.clusterName,
Replicas: m.replicas,
MinReadySeconds: m.minReadySeconds,
Template: clusterv1.MachineTemplateSpec{
Spec: clusterv1.MachineSpec{
Version: m.version,
ClusterName: m.clusterName,
},
},
},
}
if m.bootstrap != nil {
Expand All @@ -1524,9 +1538,6 @@ func (m *MachinePoolBuilder) Build() *expv1.MachinePool {
if m.infrastructure != nil {
obj.Spec.Template.Spec.InfrastructureRef = *objToRef(m.infrastructure)
}
if m.version != nil {
obj.Spec.Template.Spec.Version = m.version
}
if m.status != nil {
obj.Status = *m.status
}
Expand All @@ -1546,6 +1557,7 @@ type MachineDeploymentBuilder struct {
generation *int64
labels map[string]string
status *clusterv1.MachineDeploymentStatus
minReadySeconds *int32
}

// MachineDeployment creates a MachineDeploymentBuilder with the given name and namespace.
Expand Down Expand Up @@ -1610,6 +1622,12 @@ func (m *MachineDeploymentBuilder) WithStatus(status clusterv1.MachineDeployment
return m
}

// WithMinReadySeconds sets the passed value on the machine deployment spec.
func (m *MachineDeploymentBuilder) WithMinReadySeconds(minReadySeconds int32) *MachineDeploymentBuilder {
m.minReadySeconds = &minReadySeconds
return m
}

// Build creates a new MachineDeployment with the variables and objects passed to the MachineDeploymentBuilder.
func (m *MachineDeploymentBuilder) Build() *clusterv1.MachineDeployment {
obj := &clusterv1.MachineDeployment{
Expand Down Expand Up @@ -1653,6 +1671,7 @@ func (m *MachineDeploymentBuilder) Build() *clusterv1.MachineDeployment {
clusterv1.ClusterNameLabel: m.clusterName,
}
}
obj.Spec.MinReadySeconds = m.minReadySeconds

return obj
}
Expand Down
70 changes: 70 additions & 0 deletions internal/test/builder/infrastructure.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,13 @@ var (

// GenericInfrastructureMachinePoolTemplateKind is the Kind for the GenericInfrastructureMachinePoolTemplate.
GenericInfrastructureMachinePoolTemplateKind = "GenericInfrastructureMachinePoolTemplate"
// GenericInfrastructureMachinePoolTemplateCRD is a generic infrastructure machine pool template CRD.
GenericInfrastructureMachinePoolTemplateCRD = untypedCRD(InfrastructureGroupVersion.WithKind(GenericInfrastructureMachinePoolTemplateKind))

// GenericInfrastructureMachinePoolKind is the Kind for the GenericInfrastructureMachinePool.
GenericInfrastructureMachinePoolKind = "GenericInfrastructureMachinePool"
// GenericInfrastructureMachinePoolCRD is a generic infrastructure machine pool CRD.
GenericInfrastructureMachinePoolCRD = untypedCRD(InfrastructureGroupVersion.WithKind(GenericInfrastructureMachinePoolKind))

// GenericInfrastructureClusterKind is the kind for the GenericInfrastructureCluster type.
GenericInfrastructureClusterKind = "GenericInfrastructureCluster"
Expand Down Expand Up @@ -70,9 +74,13 @@ var (

// TestInfrastructureMachinePoolTemplateKind is the kind for the TestInfrastructureMachinePoolTemplate type.
TestInfrastructureMachinePoolTemplateKind = "TestInfrastructureMachinePoolTemplate"
// TestInfrastructureMachinePoolTemplateCRD is a test infrastructure machine pool template CRD.
TestInfrastructureMachinePoolTemplateCRD = testInfrastructureMachinePoolTemplateCRD(InfrastructureGroupVersion.WithKind(TestInfrastructureMachinePoolTemplateKind))

// TestInfrastructureMachinePoolKind is the kind for the TestInfrastructureMachinePool type.
TestInfrastructureMachinePoolKind = "TestInfrastructureMachinePool"
// TestInfrastructureMachinePoolCRD is a test infrastructure machine CRD.
TestInfrastructureMachinePoolCRD = testInfrastructureMachinePoolCRD(InfrastructureGroupVersion.WithKind(TestInfrastructureMachinePoolKind))

// TestInfrastructureMachineKind is the kind for the TestInfrastructureMachine type.
TestInfrastructureMachineKind = "TestInfrastructureMachine"
Expand Down Expand Up @@ -147,6 +155,29 @@ func testInfrastructureMachineTemplateCRD(gvk schema.GroupVersionKind) *apiexten
})
}

func testInfrastructureMachinePoolTemplateCRD(gvk schema.GroupVersionKind) *apiextensionsv1.CustomResourceDefinition {
return generateCRD(gvk, map[string]apiextensionsv1.JSONSchemaProps{
"metadata": {
// NOTE: in CRD there is only a partial definition of metadata schema.
// Ref https://github.com/kubernetes-sigs/controller-tools/blob/59485af1c1f6a664655dad49543c474bb4a0d2a2/pkg/crd/gen.go#L185
Type: "object",
},
"spec": {
Type: "object",
Properties: map[string]apiextensionsv1.JSONSchemaProps{
// Mandatory field from the Cluster API contract
"template": {
Type: "object",
Properties: map[string]apiextensionsv1.JSONSchemaProps{
"metadata": metadataSchema,
"spec": machinePoolSpecSchema,
},
},
},
},
})
}

func testInfrastructureMachineCRD(gvk schema.GroupVersionKind) *apiextensionsv1.CustomResourceDefinition {
return generateCRD(gvk, map[string]apiextensionsv1.JSONSchemaProps{
"metadata": {
Expand All @@ -168,6 +199,27 @@ func testInfrastructureMachineCRD(gvk schema.GroupVersionKind) *apiextensionsv1.
})
}

func testInfrastructureMachinePoolCRD(gvk schema.GroupVersionKind) *apiextensionsv1.CustomResourceDefinition {
return generateCRD(gvk, map[string]apiextensionsv1.JSONSchemaProps{
"metadata": {
// NOTE: in CRD there is only a partial definition of metadata schema.
// Ref https://github.com/kubernetes-sigs/controller-tools/blob/59485af1c1f6a664655dad49543c474bb4a0d2a2/pkg/crd/gen.go#L185
Type: "object",
},
"spec": machinePoolSpecSchema,
"status": {
Type: "object",
Properties: map[string]apiextensionsv1.JSONSchemaProps{
// mandatory field from the Cluster API contract
"ready": {Type: "boolean"},
// General purpose fields to be used in different test scenario.
"foo": {Type: "string"},
"bar": {Type: "string"},
},
},
})
}

var (
clusterSpecSchema = apiextensionsv1.JSONSchemaProps{
Type: "object",
Expand Down Expand Up @@ -215,4 +267,22 @@ var (
"bar": {Type: "string"},
},
}

machinePoolSpecSchema = apiextensionsv1.JSONSchemaProps{
Type: "object",
Properties: map[string]apiextensionsv1.JSONSchemaProps{
// Mandatory field from the Cluster API contract
"providerIDList": {
Type: "array",
Items: &apiextensionsv1.JSONSchemaPropsOrArray{
Schema: &apiextensionsv1.JSONSchemaProps{
Type: "string",
},
},
},
// General purpose fields to be used in different test scenario.
"foo": {Type: "string"},
"bar": {Type: "string"},
},
}
)
10 changes: 10 additions & 0 deletions internal/test/builder/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions internal/test/envtest/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,13 +212,17 @@ func newEnvironment(uncachedObjs ...client.Object) *Environment {
builder.GenericControlPlaneTemplateCRD.DeepCopy(),
builder.GenericInfrastructureMachineCRD.DeepCopy(),
builder.GenericInfrastructureMachineTemplateCRD.DeepCopy(),
builder.GenericInfrastructureMachinePoolCRD.DeepCopy(),
builder.GenericInfrastructureMachinePoolTemplateCRD.DeepCopy(),
builder.GenericInfrastructureClusterCRD.DeepCopy(),
builder.GenericInfrastructureClusterTemplateCRD.DeepCopy(),
builder.GenericRemediationCRD.DeepCopy(),
builder.GenericRemediationTemplateCRD.DeepCopy(),
builder.TestInfrastructureClusterTemplateCRD.DeepCopy(),
builder.TestInfrastructureClusterCRD.DeepCopy(),
builder.TestInfrastructureMachineTemplateCRD.DeepCopy(),
builder.TestInfrastructureMachinePoolCRD.DeepCopy(),
builder.TestInfrastructureMachinePoolTemplateCRD.DeepCopy(),
builder.TestInfrastructureMachineCRD.DeepCopy(),
builder.TestBootstrapConfigTemplateCRD.DeepCopy(),
builder.TestBootstrapConfigCRD.DeepCopy(),
Expand Down

0 comments on commit 1ae8a33

Please sign in to comment.