Skip to content

Commit 65e0327

Browse files
Merge pull request #1796 from dfajmon/pod-count
OCPBUGS-36233: Replicas hook consider Control plane topology
2 parents 756adf2 + 2926c85 commit 65e0327

File tree

2 files changed

+31
-112
lines changed

2 files changed

+31
-112
lines changed

pkg/operator/csi/csidrivercontrollerservicecontroller/helpers.go

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@ import (
1212
appsv1 "k8s.io/api/apps/v1"
1313
apierrors "k8s.io/apimachinery/pkg/api/errors"
1414
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
15-
"k8s.io/apimachinery/pkg/labels"
1615
corev1 "k8s.io/client-go/informers/core/v1"
17-
corev1listers "k8s.io/client-go/listers/core/v1"
1816

1917
configv1 "github.com/openshift/api/config/v1"
2018
opv1 "github.com/openshift/api/operator/v1"
@@ -141,22 +139,20 @@ func WithSecretHashAnnotationHook(
141139
}
142140
}
143141

144-
// WithReplicasHook sets the deployment.Spec.Replicas field according to the number
145-
// of available nodes. If the number of available nodes is bigger than one, then the
146-
// number of replicas will be two. The number of nodes is determined by the node
147-
// selector specified in the field deployment.Spec.Templates.NodeSelector.
148-
// When node ports or hostNetwork are used, maxSurge=0 should be set in the
142+
// WithReplicasHook sets the deployment.Spec.Replicas field according to the ControlPlaneTopology
143+
// mode. If the topology is set to 'HighlyAvailable' then the number of replicas will be two.
144+
// Else it will be one. When node ports or hostNetwork are used, maxSurge=0 should be set in the
149145
// Deployment RollingUpdate strategy to prevent the new pod from getting stuck
150146
// waiting for a node with free ports.
151-
func WithReplicasHook(nodeLister corev1listers.NodeLister) dc.DeploymentHookFunc {
147+
func WithReplicasHook(configInformer configinformers.SharedInformerFactory) dc.DeploymentHookFunc {
152148
return func(_ *opv1.OperatorSpec, deployment *appsv1.Deployment) error {
153-
nodeSelector := deployment.Spec.Template.Spec.NodeSelector
154-
nodes, err := nodeLister.List(labels.SelectorFromSet(nodeSelector))
149+
infra, err := configInformer.Config().V1().Infrastructures().Lister().Get(infraConfigName)
155150
if err != nil {
156151
return err
157152
}
153+
158154
replicas := int32(1)
159-
if len(nodes) > 1 {
155+
if infra.Status.ControlPlaneTopology == configv1.HighlyAvailableTopologyMode {
160156
replicas = int32(2)
161157
}
162158
deployment.Spec.Replicas = &replicas

pkg/operator/csi/csidrivercontrollerservicecontroller/helpers_test.go

Lines changed: 24 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ import (
1515
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1616
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1717
"k8s.io/apimachinery/pkg/runtime"
18-
coreinformers "k8s.io/client-go/informers"
19-
fakecore "k8s.io/client-go/kubernetes/fake"
2018

2119
"github.com/google/go-cmp/cmp"
2220
"sigs.k8s.io/yaml"
@@ -159,135 +157,60 @@ func TestWithObservedProxyDeploymentHook(t *testing.T) {
159157
}
160158

161159
func TestWithReplicasHook(t *testing.T) {
162-
var (
163-
argsLevel2 = 2
164-
masterNodeLabels = map[string]string{"node-role.kubernetes.io/master": ""}
165-
workerNodeLabels = map[string]string{"node-role.kubernetes.io/worker": ""}
166-
)
160+
argsLevel2 := 2
167161
testCases := []struct {
168162
name string
169-
initialDriver *fakeDriverInstance
170-
initialNodes []*v1.Node
163+
infra *configv1.Infrastructure
171164
initialDeployment *appsv1.Deployment
172165
expectedDeployment *appsv1.Deployment
173-
expectError bool
174166
}{
175167
{
176-
name: "three-node control-plane",
177-
initialDriver: makeFakeDriverInstance(),
178-
initialNodes: []*v1.Node{
179-
makeNode("A", masterNodeLabels),
180-
makeNode("B", masterNodeLabels),
181-
makeNode("C", masterNodeLabels),
182-
},
168+
name: "highly available topology",
169+
infra: makeInfraWithCPTopology(configv1.HighlyAvailableTopologyMode),
183170
initialDeployment: makeDeployment(
184171
defaultClusterID,
185172
argsLevel2,
186173
defaultImages(),
187174
withDeploymentReplicas(1),
188-
withDeploymentGeneration(1, 0)),
189-
expectedDeployment: makeDeployment(
190-
defaultClusterID,
191-
argsLevel2,
192-
defaultImages(),
193-
withDeploymentReplicas(2),
194-
withDeploymentGeneration(1, 0)),
195-
expectError: false,
196-
},
197-
{
198-
name: "three-node control-plane with one worker node",
199-
initialDriver: makeFakeDriverInstance(),
200-
initialNodes: []*v1.Node{
201-
makeNode("A", masterNodeLabels),
202-
makeNode("B", masterNodeLabels),
203-
makeNode("C", masterNodeLabels),
204-
makeNode("D", workerNodeLabels),
205-
},
206-
initialDeployment: makeDeployment(
207-
defaultClusterID,
208-
argsLevel2,
209-
defaultImages(),
210-
withDeploymentReplicas(1),
211-
withDeploymentGeneration(1, 0)),
212-
expectedDeployment: makeDeployment(
213-
defaultClusterID,
214-
argsLevel2,
215-
defaultImages(),
216-
withDeploymentReplicas(2),
217-
withDeploymentGeneration(1, 0)),
218-
expectError: false,
219-
},
220-
{
221-
name: "two-node control-plane",
222-
initialDriver: makeFakeDriverInstance(),
223-
initialNodes: []*v1.Node{
224-
makeNode("A", masterNodeLabels),
225-
makeNode("B", masterNodeLabels),
226-
},
227-
initialDeployment: makeDeployment(
228-
defaultClusterID,
229-
argsLevel2,
230-
defaultImages(),
231-
withDeploymentReplicas(1),
232-
withDeploymentGeneration(1, 0)),
175+
withDeploymentGeneration(1, 0),
176+
),
233177
expectedDeployment: makeDeployment(
234178
defaultClusterID,
235179
argsLevel2,
236180
defaultImages(),
237181
withDeploymentReplicas(2),
238-
withDeploymentGeneration(1, 0)),
239-
expectError: false,
182+
withDeploymentGeneration(1, 0),
183+
),
240184
},
241185
{
242-
name: "single-node control-plane with one worker node",
243-
initialDriver: makeFakeDriverInstance(),
244-
initialNodes: []*v1.Node{
245-
makeNode("A", masterNodeLabels),
246-
makeNode("B", workerNodeLabels),
247-
},
248-
initialDeployment: makeDeployment(
249-
defaultClusterID,
186+
name: "single replica topology",
187+
infra: makeInfraWithCPTopology(configv1.SingleReplicaTopologyMode),
188+
initialDeployment: makeDeployment(defaultClusterID,
250189
argsLevel2,
251190
defaultImages(),
252191
withDeploymentReplicas(1),
253-
withDeploymentGeneration(1, 0)),
254-
expectedDeployment: makeDeployment(
255-
defaultClusterID,
192+
withDeploymentGeneration(1, 0),
193+
),
194+
expectedDeployment: makeDeployment(defaultClusterID,
256195
argsLevel2,
257196
defaultImages(),
258197
withDeploymentReplicas(1),
259-
withDeploymentGeneration(1, 0)),
260-
expectError: false,
198+
withDeploymentGeneration(1, 0),
199+
),
261200
},
262201
}
263202

264203
for _, tc := range testCases {
265204
t.Run(tc.name, func(t *testing.T) {
266-
var initialObjects []runtime.Object
267-
268-
// Add deployment to slice of objects to be added to client and informer
269-
initialObjects = append(initialObjects, tc.initialDeployment)
270-
271-
// Do the same with nodes
272-
for _, node := range tc.initialNodes {
273-
initialObjects = append(initialObjects, node)
274-
}
275-
276-
// Create fake client and informer
277-
coreClient := fakecore.NewSimpleClientset(initialObjects...)
278-
coreInformerFactory := coreinformers.NewSharedInformerFactory(coreClient, 0 /*no resync */)
279-
280-
// Fill the fake informer with the initial deployment and nodes
281-
coreInformerFactory.Apps().V1().Deployments().Informer().GetIndexer().Add(tc.initialDeployment)
282-
for _, node := range initialObjects {
283-
coreInformerFactory.Core().V1().Nodes().Informer().GetIndexer().Add(node)
284-
}
285-
286-
fn := WithReplicasHook(coreInformerFactory.Core().V1().Nodes().Lister())
287-
err := fn(&tc.initialDriver.Spec, tc.initialDeployment)
288-
if err != nil && !tc.expectError {
289-
t.Errorf("Expected no error running hook function, got: %v", err)
205+
initialInfras := []runtime.Object{tc.infra}
206+
configClient := fakeconfig.NewSimpleClientset(initialInfras...)
207+
configInformerFactory := configinformers.NewSharedInformerFactory(configClient, 0)
208+
configInformerFactory.Config().V1().Infrastructures().Informer().GetIndexer().Add(initialInfras[0])
290209

210+
fn := WithReplicasHook(configInformerFactory)
211+
err := fn(nil, tc.initialDeployment)
212+
if err != nil {
213+
t.Errorf("Unexpected error: %v", err)
291214
}
292215
if !equality.Semantic.DeepEqual(tc.initialDeployment, tc.expectedDeployment) {
293216
t.Errorf("Unexpected Deployment content:\n%s", cmp.Diff(tc.initialDeployment, tc.expectedDeployment))

0 commit comments

Comments
 (0)