Skip to content

Commit b3b9928

Browse files
authored
Merge pull request kubernetes-sigs#9380 from willie-yao/cc-mp-unit-tests-2
🌱 Add unit tests for reconcile_state, cluster_controller, & conditions
2 parents 753fa61 + 1ae8a33 commit b3b9928

File tree

9 files changed

+1244
-41
lines changed

9 files changed

+1244
-41
lines changed

controllers/remote/cluster_cache_tracker_fake.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ func NewTestClusterCacheTracker(log logr.Logger, cl client.Client, scheme *runti
3030
client: cl,
3131
scheme: scheme,
3232
clusterAccessors: make(map[client.ObjectKey]*clusterAccessor),
33+
clusterLock: newKeyedMutex(),
3334
}
3435

3536
testCacheTracker.clusterAccessors[objKey] = &clusterAccessor{

internal/controllers/topology/cluster/cluster_controller_test.go

Lines changed: 219 additions & 18 deletions
Large diffs are not rendered by default.

internal/controllers/topology/cluster/conditions_test.go

Lines changed: 329 additions & 6 deletions
Large diffs are not rendered by default.

internal/controllers/topology/cluster/reconcile_state_test.go

Lines changed: 549 additions & 2 deletions
Large diffs are not rendered by default.

internal/controllers/topology/cluster/suite_test.go

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"time"
2525

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

3435
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
3536
"sigs.k8s.io/cluster-api/api/v1beta1/index"
37+
"sigs.k8s.io/cluster-api/controllers/remote"
3638
expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1"
3739
"sigs.k8s.io/cluster-api/internal/controllers/clusterclass"
3840
"sigs.k8s.io/cluster-api/internal/test/envtest"
@@ -49,6 +51,7 @@ func init() {
4951
_ = clusterv1.AddToScheme(fakeScheme)
5052
_ = apiextensionsv1.AddToScheme(fakeScheme)
5153
_ = expv1.AddToScheme(fakeScheme)
54+
_ = corev1.AddToScheme(fakeScheme)
5255
}
5356
func TestMain(m *testing.M) {
5457
setupIndexes := func(ctx context.Context, mgr ctrl.Manager) {
@@ -71,11 +74,40 @@ func TestMain(m *testing.M) {
7174
if err != nil {
7275
panic(fmt.Sprintf("unable to create unstructuredCachineClient: %v", err))
7376
}
77+
// Set up a ClusterCacheTracker and ClusterCacheReconciler to provide to controllers
78+
// requiring a connection to a remote cluster
79+
log := ctrl.Log.WithName("remote").WithName("ClusterCacheTracker")
80+
secretCachingClient, err := client.New(mgr.GetConfig(), client.Options{
81+
HTTPClient: mgr.GetHTTPClient(),
82+
Cache: &client.CacheOptions{
83+
Reader: mgr.GetCache(),
84+
},
85+
})
86+
if err != nil {
87+
panic(fmt.Sprintf("unable to create secretCachingClient: %v", err))
88+
}
89+
tracker, err := remote.NewClusterCacheTracker(
90+
mgr,
91+
remote.ClusterCacheTrackerOptions{
92+
Log: &log,
93+
SecretCachingClient: secretCachingClient,
94+
},
95+
)
96+
if err != nil {
97+
panic(fmt.Sprintf("unable to create cluster cache tracker: %v", err))
98+
}
99+
if err := (&remote.ClusterCacheReconciler{
100+
Client: mgr.GetClient(),
101+
Tracker: tracker,
102+
}).SetupWithManager(ctx, mgr, controller.Options{MaxConcurrentReconciles: 1}); err != nil {
103+
panic(fmt.Sprintf("Failed to start ClusterCacheReconciler: %v", err))
104+
}
74105
if err := (&Reconciler{
75106
Client: mgr.GetClient(),
76107
APIReader: mgr.GetAPIReader(),
77108
UnstructuredCachingClient: unstructuredCachingClient,
78-
}).SetupWithManager(ctx, mgr, controller.Options{MaxConcurrentReconciles: 5}); err != nil {
109+
Tracker: tracker,
110+
}).SetupWithManager(ctx, mgr, controller.Options{MaxConcurrentReconciles: 1}); err != nil {
79111
panic(fmt.Sprintf("unable to create topology cluster reconciler: %v", err))
80112
}
81113
if err := (&clusterclass.Reconciler{

internal/test/builder/builders.go

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,15 +1470,16 @@ func (c *TestControlPlaneBuilder) Build() *unstructured.Unstructured {
14701470

14711471
// MachinePoolBuilder holds the variables and objects needed to build a generic MachinePool.
14721472
type MachinePoolBuilder struct {
1473-
namespace string
1474-
name string
1475-
bootstrap *unstructured.Unstructured
1476-
infrastructure *unstructured.Unstructured
1477-
version *string
1478-
clusterName string
1479-
replicas *int32
1480-
labels map[string]string
1481-
status *expv1.MachinePoolStatus
1473+
namespace string
1474+
name string
1475+
bootstrap *unstructured.Unstructured
1476+
infrastructure *unstructured.Unstructured
1477+
version *string
1478+
clusterName string
1479+
replicas *int32
1480+
labels map[string]string
1481+
status *expv1.MachinePoolStatus
1482+
minReadySeconds *int32
14821483
}
14831484

14841485
// MachinePool creates a MachinePoolBuilder with the given name and namespace.
@@ -1531,6 +1532,12 @@ func (m *MachinePoolBuilder) WithStatus(status expv1.MachinePoolStatus) *Machine
15311532
return m
15321533
}
15331534

1535+
// WithMinReadySeconds sets the passed value on the machine pool spec.
1536+
func (m *MachinePoolBuilder) WithMinReadySeconds(minReadySeconds int32) *MachinePoolBuilder {
1537+
m.minReadySeconds = &minReadySeconds
1538+
return m
1539+
}
1540+
15341541
// Build creates a new MachinePool with the variables and objects passed to the MachinePoolBuilder.
15351542
func (m *MachinePoolBuilder) Build() *expv1.MachinePool {
15361543
obj := &expv1.MachinePool{
@@ -1544,8 +1551,15 @@ func (m *MachinePoolBuilder) Build() *expv1.MachinePool {
15441551
Labels: m.labels,
15451552
},
15461553
Spec: expv1.MachinePoolSpec{
1547-
ClusterName: m.clusterName,
1548-
Replicas: m.replicas,
1554+
ClusterName: m.clusterName,
1555+
Replicas: m.replicas,
1556+
MinReadySeconds: m.minReadySeconds,
1557+
Template: clusterv1.MachineTemplateSpec{
1558+
Spec: clusterv1.MachineSpec{
1559+
Version: m.version,
1560+
ClusterName: m.clusterName,
1561+
},
1562+
},
15491563
},
15501564
}
15511565
if m.bootstrap != nil {
@@ -1554,9 +1568,6 @@ func (m *MachinePoolBuilder) Build() *expv1.MachinePool {
15541568
if m.infrastructure != nil {
15551569
obj.Spec.Template.Spec.InfrastructureRef = *objToRef(m.infrastructure)
15561570
}
1557-
if m.version != nil {
1558-
obj.Spec.Template.Spec.Version = m.version
1559-
}
15601571
if m.status != nil {
15611572
obj.Status = *m.status
15621573
}
@@ -1576,6 +1587,7 @@ type MachineDeploymentBuilder struct {
15761587
generation *int64
15771588
labels map[string]string
15781589
status *clusterv1.MachineDeploymentStatus
1590+
minReadySeconds *int32
15791591
}
15801592

15811593
// MachineDeployment creates a MachineDeploymentBuilder with the given name and namespace.
@@ -1640,6 +1652,12 @@ func (m *MachineDeploymentBuilder) WithStatus(status clusterv1.MachineDeployment
16401652
return m
16411653
}
16421654

1655+
// WithMinReadySeconds sets the passed value on the machine deployment spec.
1656+
func (m *MachineDeploymentBuilder) WithMinReadySeconds(minReadySeconds int32) *MachineDeploymentBuilder {
1657+
m.minReadySeconds = &minReadySeconds
1658+
return m
1659+
}
1660+
16431661
// Build creates a new MachineDeployment with the variables and objects passed to the MachineDeploymentBuilder.
16441662
func (m *MachineDeploymentBuilder) Build() *clusterv1.MachineDeployment {
16451663
obj := &clusterv1.MachineDeployment{
@@ -1683,6 +1701,7 @@ func (m *MachineDeploymentBuilder) Build() *clusterv1.MachineDeployment {
16831701
clusterv1.ClusterNameLabel: m.clusterName,
16841702
}
16851703
}
1704+
obj.Spec.MinReadySeconds = m.minReadySeconds
16861705

16871706
return obj
16881707
}

internal/test/builder/infrastructure.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,13 @@ var (
7474

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

7880
// TestInfrastructureMachinePoolKind is the kind for the TestInfrastructureMachinePool type.
7981
TestInfrastructureMachinePoolKind = "TestInfrastructureMachinePool"
82+
// TestInfrastructureMachinePoolCRD is a test infrastructure machine CRD.
83+
TestInfrastructureMachinePoolCRD = testInfrastructureMachinePoolCRD(InfrastructureGroupVersion.WithKind(TestInfrastructureMachinePoolKind))
8084

8185
// TestInfrastructureMachineKind is the kind for the TestInfrastructureMachine type.
8286
TestInfrastructureMachineKind = "TestInfrastructureMachine"
@@ -151,6 +155,29 @@ func testInfrastructureMachineTemplateCRD(gvk schema.GroupVersionKind) *apiexten
151155
})
152156
}
153157

158+
func testInfrastructureMachinePoolTemplateCRD(gvk schema.GroupVersionKind) *apiextensionsv1.CustomResourceDefinition {
159+
return generateCRD(gvk, map[string]apiextensionsv1.JSONSchemaProps{
160+
"metadata": {
161+
// NOTE: in CRD there is only a partial definition of metadata schema.
162+
// Ref https://github.com/kubernetes-sigs/controller-tools/blob/59485af1c1f6a664655dad49543c474bb4a0d2a2/pkg/crd/gen.go#L185
163+
Type: "object",
164+
},
165+
"spec": {
166+
Type: "object",
167+
Properties: map[string]apiextensionsv1.JSONSchemaProps{
168+
// Mandatory field from the Cluster API contract
169+
"template": {
170+
Type: "object",
171+
Properties: map[string]apiextensionsv1.JSONSchemaProps{
172+
"metadata": metadataSchema,
173+
"spec": machinePoolSpecSchema,
174+
},
175+
},
176+
},
177+
},
178+
})
179+
}
180+
154181
func testInfrastructureMachineCRD(gvk schema.GroupVersionKind) *apiextensionsv1.CustomResourceDefinition {
155182
return generateCRD(gvk, map[string]apiextensionsv1.JSONSchemaProps{
156183
"metadata": {
@@ -172,6 +199,27 @@ func testInfrastructureMachineCRD(gvk schema.GroupVersionKind) *apiextensionsv1.
172199
})
173200
}
174201

202+
func testInfrastructureMachinePoolCRD(gvk schema.GroupVersionKind) *apiextensionsv1.CustomResourceDefinition {
203+
return generateCRD(gvk, map[string]apiextensionsv1.JSONSchemaProps{
204+
"metadata": {
205+
// NOTE: in CRD there is only a partial definition of metadata schema.
206+
// Ref https://github.com/kubernetes-sigs/controller-tools/blob/59485af1c1f6a664655dad49543c474bb4a0d2a2/pkg/crd/gen.go#L185
207+
Type: "object",
208+
},
209+
"spec": machinePoolSpecSchema,
210+
"status": {
211+
Type: "object",
212+
Properties: map[string]apiextensionsv1.JSONSchemaProps{
213+
// mandatory field from the Cluster API contract
214+
"ready": {Type: "boolean"},
215+
// General purpose fields to be used in different test scenario.
216+
"foo": {Type: "string"},
217+
"bar": {Type: "string"},
218+
},
219+
},
220+
})
221+
}
222+
175223
var (
176224
clusterSpecSchema = apiextensionsv1.JSONSchemaProps{
177225
Type: "object",
@@ -219,4 +267,22 @@ var (
219267
"bar": {Type: "string"},
220268
},
221269
}
270+
271+
machinePoolSpecSchema = apiextensionsv1.JSONSchemaProps{
272+
Type: "object",
273+
Properties: map[string]apiextensionsv1.JSONSchemaProps{
274+
// Mandatory field from the Cluster API contract
275+
"providerIDList": {
276+
Type: "array",
277+
Items: &apiextensionsv1.JSONSchemaPropsOrArray{
278+
Schema: &apiextensionsv1.JSONSchemaProps{
279+
Type: "string",
280+
},
281+
},
282+
},
283+
// General purpose fields to be used in different test scenario.
284+
"foo": {Type: "string"},
285+
"bar": {Type: "string"},
286+
},
287+
}
222288
)

internal/test/builder/zz_generated.deepcopy.go

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/test/envtest/environment.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,13 +216,17 @@ func newEnvironment(uncachedObjs ...client.Object) *Environment {
216216
builder.GenericControlPlaneTemplateCRD.DeepCopy(),
217217
builder.GenericInfrastructureMachineCRD.DeepCopy(),
218218
builder.GenericInfrastructureMachineTemplateCRD.DeepCopy(),
219+
builder.GenericInfrastructureMachinePoolCRD.DeepCopy(),
220+
builder.GenericInfrastructureMachinePoolTemplateCRD.DeepCopy(),
219221
builder.GenericInfrastructureClusterCRD.DeepCopy(),
220222
builder.GenericInfrastructureClusterTemplateCRD.DeepCopy(),
221223
builder.GenericRemediationCRD.DeepCopy(),
222224
builder.GenericRemediationTemplateCRD.DeepCopy(),
223225
builder.TestInfrastructureClusterTemplateCRD.DeepCopy(),
224226
builder.TestInfrastructureClusterCRD.DeepCopy(),
225227
builder.TestInfrastructureMachineTemplateCRD.DeepCopy(),
228+
builder.TestInfrastructureMachinePoolCRD.DeepCopy(),
229+
builder.TestInfrastructureMachinePoolTemplateCRD.DeepCopy(),
226230
builder.TestInfrastructureMachineCRD.DeepCopy(),
227231
builder.TestBootstrapConfigTemplateCRD.DeepCopy(),
228232
builder.TestBootstrapConfigCRD.DeepCopy(),

0 commit comments

Comments
 (0)