Skip to content

Commit b248e92

Browse files
committed
Allows for override replicas quantity to deploy a HA cert manager
Signed-off-by: appiepollo14 <[email protected]>
1 parent dd64dc3 commit b248e92

File tree

8 files changed

+239
-0
lines changed

8 files changed

+239
-0
lines changed

api/operator/v1alpha1/certmanager_types.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ type DeploymentConfig struct {
8282
// +optional
8383
OverrideResources CertManagerResourceRequirements `json:"overrideResources,omitempty"`
8484

85+
// Replicas defines the number of replicas to run for an operand
86+
// +kubebuilder:validation:Optional
87+
// +optional
88+
OverrideReplicas int32 `json:"overrideReplicas,omitempty"`
89+
8590
// +kubebuilder:validation:Optional
8691
// +optional
8792
OverrideScheduling CertManagerScheduling `json:"overrideScheduling,omitempty"`

bundle/manifests/operator.openshift.io_certmanagers.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,11 @@ spec:
177177
additionalProperties:
178178
type: string
179179
type: object
180+
overrideReplicas:
181+
description: Replicas defines the number of replicas to run for
182+
an operand
183+
format: int32
184+
type: integer
180185
overrideResources:
181186
description: |-
182187
CertManagerResourceRequirements describes the compute resource requirements for the cert-manager operands,
@@ -413,6 +418,11 @@ spec:
413418
additionalProperties:
414419
type: string
415420
type: object
421+
overrideReplicas:
422+
description: Replicas defines the number of replicas to run for
423+
an operand
424+
format: int32
425+
type: integer
416426
overrideResources:
417427
description: |-
418428
CertManagerResourceRequirements describes the compute resource requirements for the cert-manager operands,
@@ -694,6 +704,11 @@ spec:
694704
additionalProperties:
695705
type: string
696706
type: object
707+
overrideReplicas:
708+
description: Replicas defines the number of replicas to run for
709+
an operand
710+
format: int32
711+
type: integer
697712
overrideResources:
698713
description: |-
699714
CertManagerResourceRequirements describes the compute resource requirements for the cert-manager operands,

config/crd/bases/operator.openshift.io_certmanagers.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,11 @@ spec:
177177
additionalProperties:
178178
type: string
179179
type: object
180+
overrideReplicas:
181+
description: Replicas defines the number of replicas to run for
182+
an operand
183+
format: int32
184+
type: integer
180185
overrideResources:
181186
description: |-
182187
CertManagerResourceRequirements describes the compute resource requirements for the cert-manager operands,
@@ -413,6 +418,11 @@ spec:
413418
additionalProperties:
414419
type: string
415420
type: object
421+
overrideReplicas:
422+
description: Replicas defines the number of replicas to run for
423+
an operand
424+
format: int32
425+
type: integer
416426
overrideResources:
417427
description: |-
418428
CertManagerResourceRequirements describes the compute resource requirements for the cert-manager operands,
@@ -694,6 +704,11 @@ spec:
694704
additionalProperties:
695705
type: string
696706
type: object
707+
overrideReplicas:
708+
description: Replicas defines the number of replicas to run for
709+
an operand
710+
format: int32
711+
type: integer
697712
overrideResources:
698713
description: |-
699714
CertManagerResourceRequirements describes the compute resource requirements for the cert-manager operands,

pkg/controller/deployment/deployment_helper.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,33 @@ func getOverridePodLabelsFor(certmanagerinformer certmanagerinformer.CertManager
214214

215215
}
216216

217+
// getOverrideReplicasFor is a helper function that returns the OverrideReplicas provided
218+
// in the operator spec based on the deployment name.
219+
func getOverrideReplicasFor(certmanagerinformer certmanagerinformer.CertManagerInformer, deploymentName string) (int32, error) {
220+
certmanager, err := certmanagerinformer.Lister().Get("cluster")
221+
if err != nil {
222+
return 0, fmt.Errorf("failed to get certmanager %q due to %v", "cluster", err)
223+
}
224+
225+
switch deploymentName {
226+
case certmanagerControllerDeployment:
227+
if certmanager.Spec.ControllerConfig != nil {
228+
return certmanager.Spec.ControllerConfig.OverrideReplicas, nil
229+
}
230+
case certmanagerWebhookDeployment:
231+
if certmanager.Spec.WebhookConfig != nil {
232+
return certmanager.Spec.WebhookConfig.OverrideReplicas, nil
233+
}
234+
case certmanagerCAinjectorDeployment:
235+
if certmanager.Spec.CAInjectorConfig != nil {
236+
return certmanager.Spec.CAInjectorConfig.OverrideReplicas, nil
237+
}
238+
default:
239+
return 0, fmt.Errorf("unsupported deployment name %q provided", deploymentName)
240+
}
241+
return 0, nil
242+
}
243+
217244
// getOverrideResourcesFor is a helper function that returns the OverrideResources provided
218245
// in the operator spec based on the deployment name.
219246
func getOverrideResourcesFor(certmanagerinformer certmanagerinformer.CertManagerInformer, deploymentName string) (v1alpha1.CertManagerResourceRequirements, error) {

pkg/controller/deployment/deployment_helper_test.go

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,3 +944,146 @@ func TestGetOverrideSchedulingFor(t *testing.T) {
944944
})
945945
}
946946
}
947+
948+
func TestGetOverrideReplicasFor(t *testing.T) {
949+
tests := []struct {
950+
name string
951+
certManagerObj v1alpha1.CertManager
952+
deploymentName string
953+
expectedOverrideReplicas int32
954+
}{
955+
{
956+
name: "get override replicas of cert manager controller config",
957+
certManagerObj: v1alpha1.CertManager{
958+
ObjectMeta: metav1.ObjectMeta{
959+
Name: "cluster",
960+
},
961+
Spec: v1alpha1.CertManagerSpec{
962+
ControllerConfig: &v1alpha1.DeploymentConfig{
963+
OverrideReplicas: 2,
964+
},
965+
},
966+
},
967+
deploymentName: certmanagerControllerDeployment,
968+
expectedOverrideReplicas: 2,
969+
},
970+
{
971+
name: "get override scheduling of cert manager webhook config",
972+
certManagerObj: v1alpha1.CertManager{
973+
ObjectMeta: metav1.ObjectMeta{
974+
Name: "cluster",
975+
},
976+
Spec: v1alpha1.CertManagerSpec{
977+
WebhookConfig: &v1alpha1.DeploymentConfig{
978+
OverrideReplicas: 0,
979+
},
980+
},
981+
},
982+
deploymentName: certmanagerWebhookDeployment,
983+
expectedOverrideReplicas: 0,
984+
},
985+
{
986+
name: "get override scheduling of cert manager cainjector config",
987+
certManagerObj: v1alpha1.CertManager{
988+
ObjectMeta: metav1.ObjectMeta{
989+
Name: "cluster",
990+
},
991+
Spec: v1alpha1.CertManagerSpec{
992+
CAInjectorConfig: &v1alpha1.DeploymentConfig{
993+
OverrideReplicas: 2,
994+
},
995+
},
996+
},
997+
deploymentName: certmanagerCAinjectorDeployment,
998+
expectedOverrideReplicas: 2,
999+
},
1000+
}
1001+
1002+
ctx, cancel := context.WithCancel(context.Background())
1003+
defer cancel()
1004+
1005+
// Create channel to know when the watch has started.
1006+
watcherStarted := make(chan struct{})
1007+
// Create the fake client.
1008+
fakeClient := fake.NewSimpleClientset()
1009+
// A watch reactor for cert manager objects that allows the injection of the watcherStarted channel.
1010+
fakeClient.PrependWatchReactor("certmanagers", func(action clienttesting.Action) (handled bool, ret watch.Interface, err error) {
1011+
gvr := action.GetResource()
1012+
ns := action.GetNamespace()
1013+
watch, err := fakeClient.Tracker().Watch(gvr, ns)
1014+
if err != nil {
1015+
return false, nil, err
1016+
}
1017+
close(watcherStarted)
1018+
return true, watch, nil
1019+
})
1020+
1021+
// Create cert manager informers using the fake client.
1022+
certManagerInformers := certmanoperatorinformer.NewSharedInformerFactory(fakeClient, 0).Operator().V1alpha1().CertManagers()
1023+
1024+
// Create a channel to receive the cert manager objects from the informer.
1025+
certManagerChan := make(chan *v1alpha1.CertManager, 1)
1026+
1027+
// Add event handlers to the informer to write the cert manager objects to
1028+
// the channel received during the add and the delete events.
1029+
certManagerInformers.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
1030+
AddFunc: func(obj interface{}) {
1031+
certManagerObj := obj.(*v1alpha1.CertManager)
1032+
t.Logf("cert manager obj added: %s", certManagerObj.Name)
1033+
certManagerChan <- certManagerObj
1034+
},
1035+
DeleteFunc: func(obj interface{}) {
1036+
certManagerObj := obj.(*v1alpha1.CertManager)
1037+
t.Logf("cert manager obj deleted: %s", certManagerObj.Name)
1038+
certManagerChan <- certManagerObj
1039+
},
1040+
})
1041+
1042+
// Make sure informer is running.
1043+
go certManagerInformers.Informer().Run(ctx.Done())
1044+
1045+
// This is not required in tests, but it serves as a proof-of-concept by
1046+
// ensuring that the informer goroutine have warmed up and called List before
1047+
// we send any events to it.
1048+
cache.WaitForCacheSync(ctx.Done(), certManagerInformers.Informer().HasSynced)
1049+
1050+
// The fake client doesn't support resource version. Any writes to the client
1051+
// after the informer's initial LIST and before the informer establishing the
1052+
// watcher will be missed by the informer. Therefore we wait until the watcher
1053+
// starts.
1054+
<-watcherStarted
1055+
1056+
for _, tc := range tests {
1057+
t.Run(tc.name, func(t *testing.T) {
1058+
// Create the cert manager object using the fake client.
1059+
_, err := fakeClient.OperatorV1alpha1().CertManagers().Create(ctx, &tc.certManagerObj, metav1.CreateOptions{})
1060+
if err != nil {
1061+
t.Fatalf("error injecting cert manager add: %v", err)
1062+
}
1063+
1064+
// Wait for the informer to get the event.
1065+
select {
1066+
case <-certManagerChan:
1067+
case <-time.After(wait.ForeverTestTimeout):
1068+
t.Fatal("Informer did not get the added cert manager object")
1069+
}
1070+
1071+
actualOverrideReplicas, err := getOverrideReplicasFor(certManagerInformers, tc.deploymentName)
1072+
assert.NoError(t, err)
1073+
require.Equal(t, tc.expectedOverrideReplicas, actualOverrideReplicas)
1074+
1075+
// Delete the cert manager object using the fake client.
1076+
err = fakeClient.OperatorV1alpha1().CertManagers().Delete(ctx, tc.certManagerObj.Name, metav1.DeleteOptions{})
1077+
if err != nil {
1078+
t.Fatalf("error deleting cert manager add: %v", err)
1079+
}
1080+
1081+
// Wait for the informer to get the event.
1082+
select {
1083+
case <-certManagerChan:
1084+
case <-time.After(wait.ForeverTestTimeout):
1085+
t.Fatal("Informer did not get the deleted cert manager")
1086+
}
1087+
})
1088+
}
1089+
}

pkg/controller/deployment/deployment_overrides.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"k8s.io/utils/ptr"
1313

1414
operatorv1 "github.com/openshift/api/operator/v1"
15+
v1 "github.com/openshift/api/operator/v1"
1516
"github.com/operator-framework/operator-lib/proxy"
1617

1718
"github.com/openshift/cert-manager-operator/api/operator/v1alpha1"
@@ -57,6 +58,11 @@ type overrideEnvFunc func(certmanagerinformer.CertManagerInformer, string) ([]co
5758
// to cert-manager-operator spec.
5859
type overrideLabelsFunc func(certmanagerinformer.CertManagerInformer, string) (map[string]string, error)
5960

61+
// overrideReplicasFunc defines a function signature that is accepted by
62+
// withContainerReplicasOverrideHook(). This function returns the override
63+
// replicas provided to cert-manager-operator spec.
64+
type overrideReplicasFunc func(certmanagerinformer.CertManagerInformer, string) (int32, error)
65+
6066
// overrideResourcesFunc defines a function signature that is accepted by
6167
// withContainerResourcesOverrideHook(). This function returns the override
6268
// resources provided to cert-manager-operator spec.
@@ -137,6 +143,24 @@ func withContainerResourcesOverrideHook(certmanagerinformer certmanagerinformer.
137143
}
138144
}
139145

146+
// withContainerReplicasOverrideHook overrides the deployment replicas with those provided by
147+
// the overrideReplicasFunc function.
148+
func withContainerReplicasOverrideHook(certmanagerinformer certmanagerinformer.CertManagerInformer, deploymentName string, fn overrideReplicasFunc) func(operatorSpec *v1.OperatorSpec, deployment *appsv1.Deployment) error {
149+
return func(operatorSpec *v1.OperatorSpec, deployment *appsv1.Deployment) error {
150+
overrideReplicas, err := fn(certmanagerinformer, deploymentName)
151+
if err != nil {
152+
return err
153+
}
154+
155+
if overrideReplicas != 0 {
156+
if deployment.Name == deploymentName {
157+
deployment.Spec.Replicas = &overrideReplicas
158+
}
159+
}
160+
return nil
161+
}
162+
}
163+
140164
// withPodSchedulingOverrideHook overrides the pod scheduling with those provided by
141165
// the overrideSchedulingFunc function.
142166
func withPodSchedulingOverrideHook(certmanagerinformer certmanagerinformer.CertManagerInformer, deploymentName string, fn overrideSchedulingFunc) func(operatorSpec *operatorv1.OperatorSpec, deployment *appsv1.Deployment) error {

pkg/controller/deployment/generic_deployment_controller.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ func newGenericDeploymentController(
5050
withContainerArgsValidateHook(certManagerOperatorInformers.Operator().V1alpha1().CertManagers(), deployment.Name),
5151
withContainerEnvOverrideHook(certManagerOperatorInformers.Operator().V1alpha1().CertManagers(), deployment.Name, getOverrideEnvFor),
5252
withContainerEnvValidateHook(certManagerOperatorInformers.Operator().V1alpha1().CertManagers(), deployment.Name),
53+
withContainerReplicasOverrideHook(certManagerOperatorInformers.Operator().V1alpha1().CertManagers(), deployment.Name, getOverrideReplicasFor),
5354
withContainerResourcesOverrideHook(certManagerOperatorInformers.Operator().V1alpha1().CertManagers(), deployment.Name, getOverrideResourcesFor),
5455
withContainerResourcesValidateHook(certManagerOperatorInformers.Operator().V1alpha1().CertManagers(), deployment.Name),
5556
withPodSchedulingOverrideHook(certManagerOperatorInformers.Operator().V1alpha1().CertManagers(), deployment.Name, getOverrideSchedulingFor),

pkg/operator/applyconfigurations/operator/v1alpha1/deploymentconfig.go

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

0 commit comments

Comments
 (0)