• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kubevirt / hyperconverged-cluster-operator / 19509545460

19 Nov 2025 04:57PM UTC coverage: 77.008% (-0.2%) from 77.24%
19509545460

Pull #3871

github

web-flow
Merge d84db5bfe into 2350d213b
Pull Request #3871: Allow virt-operator deployment on Hosted Control Planes Cluster

65 of 127 new or added lines in 3 files covered. (51.18%)

15 existing lines in 1 file now uncovered.

7988 of 10373 relevant lines covered (77.01%)

1.84 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

3.02
/pkg/components/components.go
1
package components
2

3
import (
4
        "encoding/json"
5
        "fmt"
6
        "strconv"
7
        "time"
8

9
        "github.com/blang/semver/v4"
10
        csvVersion "github.com/operator-framework/api/pkg/lib/version"
11
        csvv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
12
        admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
13
        appsv1 "k8s.io/api/apps/v1"
14
        corev1 "k8s.io/api/core/v1"
15
        networkingv1 "k8s.io/api/networking/v1"
16
        rbacv1 "k8s.io/api/rbac/v1"
17
        "k8s.io/apimachinery/pkg/api/resource"
18
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
19
        "k8s.io/apimachinery/pkg/runtime"
20
        "k8s.io/apimachinery/pkg/util/intstr"
21
        "k8s.io/utils/ptr"
22

23
        cnaoapi "github.com/kubevirt/cluster-network-addons-operator/pkg/apis/networkaddonsoperator/v1"
24
        kvapi "kubevirt.io/api/core"
25
        aaqapi "kubevirt.io/application-aware-quota/staging/src/kubevirt.io/application-aware-quota-api/pkg/apis/core"
26
        cdiapi "kubevirt.io/containerized-data-importer-api/pkg/apis/core"
27
        sspapi "kubevirt.io/ssp-operator/api/v1beta3"
28

29
        hcov1beta1 "github.com/kubevirt/hyperconverged-cluster-operator/api/v1beta1"
30
        "github.com/kubevirt/hyperconverged-cluster-operator/pkg/util"
31
)
32

33
const DisableOperandDeletionAnnotation = "console.openshift.io/disable-operand-delete"
34

35
const (
36
        crName              = util.HyperConvergedName
37
        packageName         = util.HyperConvergedName
38
        hcoDeploymentName   = "hco-operator"
39
        hcoWhDeploymentName = "hco-webhook"
40
        certVolume          = "apiservice-cert"
41

42
        kubevirtProjectName = "KubeVirt project"
43
        rbacVersionV1       = "rbac.authorization.k8s.io/v1"
44
)
45

46
var deploymentType = metav1.TypeMeta{
47
        APIVersion: "apps/v1",
48
        Kind:       "Deployment",
49
}
50

51
type DeploymentOperatorParams struct {
52
        Namespace              string
53
        Image                  string
54
        WebhookImage           string
55
        CliDownloadsImage      string
56
        KVUIPluginImage        string
57
        KVUIProxyImage         string
58
        PasstImage             string
59
        PasstCNIImage          string
60
        WaspAgentImage         string
61
        ImagePullPolicy        string
62
        ConversionContainer    string
63
        VmwareContainer        string
64
        VirtIOWinContainer     string
65
        Smbios                 string
66
        Machinetype            string
67
        Amd64MachineType       string
68
        Arm64MachineType       string
69
        HcoKvIoVersion         string
70
        KubevirtVersion        string
71
        KvVirtLancherOsVersion string
72
        CdiVersion             string
73
        CnaoVersion            string
74
        SspVersion             string
75
        HppoVersion            string
76
        MtqVersion             string
77
        AaqVersion             string
78
        Env                    []corev1.EnvVar
79
        AddNetworkPolicyLabels bool
80
}
81

82
func GetDeploymentOperator(params *DeploymentOperatorParams) appsv1.Deployment {
×
83
        return appsv1.Deployment{
×
84
                TypeMeta: deploymentType,
×
85
                ObjectMeta: metav1.ObjectMeta{
×
86
                        Name: util.HCOOperatorName,
×
87
                        Labels: map[string]string{
×
88
                                "name": util.HCOOperatorName,
×
89
                        },
×
90
                },
×
91
                Spec: GetDeploymentSpecOperator(params),
×
92
        }
×
93
}
×
94

95
func GetDeploymentWebhook(params *DeploymentOperatorParams) appsv1.Deployment {
×
96
        deploy := appsv1.Deployment{
×
97
                TypeMeta: deploymentType,
×
98
                ObjectMeta: metav1.ObjectMeta{
×
99
                        Name: util.HCOWebhookName,
×
100
                        Labels: map[string]string{
×
101
                                "name": util.HCOWebhookName,
×
102
                        },
×
103
                },
×
104
                Spec: GetDeploymentSpecWebhook(params),
×
105
        }
×
106

×
107
        InjectVolumesForWebHookCerts(&deploy)
×
108
        return deploy
×
109
}
×
110

111
func GetDeploymentCliDownloads(params *DeploymentOperatorParams) appsv1.Deployment {
×
112
        return appsv1.Deployment{
×
113
                TypeMeta: deploymentType,
×
114
                ObjectMeta: metav1.ObjectMeta{
×
115
                        Name: util.CLIDownloadsName,
×
116
                        Labels: map[string]string{
×
117
                                "name": util.CLIDownloadsName,
×
118
                        },
×
119
                },
×
120
                Spec: GetDeploymentSpecCliDownloads(params),
×
121
        }
×
122
}
×
123

124
func GetServiceWebhook() corev1.Service {
×
125
        return corev1.Service{
×
126
                TypeMeta: metav1.TypeMeta{
×
127
                        APIVersion: "v1",
×
128
                        Kind:       "Service",
×
129
                },
×
130
                ObjectMeta: metav1.ObjectMeta{
×
131
                        Name: util.HCOWebhookName + "-service",
×
132
                },
×
133
                Spec: corev1.ServiceSpec{
×
134
                        Selector: map[string]string{
×
135
                                "name": util.HCOWebhookName,
×
136
                        },
×
137
                        Ports: []corev1.ServicePort{
×
138
                                {
×
139
                                        Name:       strconv.Itoa(util.WebhookPort),
×
140
                                        Port:       util.WebhookPort,
×
141
                                        Protocol:   corev1.ProtocolTCP,
×
142
                                        TargetPort: intstr.FromInt32(util.WebhookPort),
×
143
                                },
×
144
                        },
×
145
                        Type: corev1.ServiceTypeClusterIP,
×
146
                },
×
147
        }
×
148
}
×
149

150
func GetDeploymentSpecOperator(params *DeploymentOperatorParams) appsv1.DeploymentSpec {
×
151
        envs := buildEnvVars(params)
×
152

×
153
        return appsv1.DeploymentSpec{
×
154
                Replicas: ptr.To[int32](1),
×
155
                Selector: &metav1.LabelSelector{
×
156
                        MatchLabels: map[string]string{
×
157
                                "name": util.HCOOperatorName,
×
158
                        },
×
159
                },
×
160
                Strategy: appsv1.DeploymentStrategy{
×
161
                        Type: appsv1.RollingUpdateDeploymentStrategyType,
×
162
                },
×
163
                Template: corev1.PodTemplateSpec{
×
164
                        ObjectMeta: metav1.ObjectMeta{
×
165
                                Labels: getLabelsWithNetworkPolicies(util.HCOOperatorName, params),
×
166
                        },
×
167
                        Spec: corev1.PodSpec{
×
168
                                ServiceAccountName: util.HCOOperatorName,
×
169
                                SecurityContext:    GetStdPodSecurityContext(),
×
170
                                Containers: []corev1.Container{
×
171
                                        {
×
172
                                                Name:            util.HCOOperatorName,
×
173
                                                Image:           params.Image,
×
174
                                                ImagePullPolicy: corev1.PullPolicy(params.ImagePullPolicy),
×
175
                                                Command:         stringListToSlice(util.HCOOperatorName),
×
176
                                                ReadinessProbe:  getReadinessProbe(util.ReadinessEndpointName, util.HealthProbePort),
×
177
                                                LivenessProbe:   getLivenessProbe(util.LivenessEndpointName, util.HealthProbePort),
×
178
                                                Env:             envs,
×
179
                                                Resources: corev1.ResourceRequirements{
×
180
                                                        Requests: map[corev1.ResourceName]resource.Quantity{
×
181
                                                                corev1.ResourceCPU:    resource.MustParse("10m"),
×
182
                                                                corev1.ResourceMemory: resource.MustParse("96Mi"),
×
183
                                                        },
×
184
                                                },
×
185
                                                SecurityContext:          GetStdContainerSecurityContext(),
×
186
                                                TerminationMessagePolicy: corev1.TerminationMessageFallbackToLogsOnError,
×
187
                                                Ports: []corev1.ContainerPort{
×
188
                                                        getMetricsPort(),
×
189
                                                },
×
190
                                        },
×
191
                                },
×
192
                                PriorityClassName: "system-cluster-critical",
×
193
                        },
×
194
                },
×
195
        }
×
196
}
×
197

198
func buildEnvVars(params *DeploymentOperatorParams) []corev1.EnvVar {
×
199
        envs := append([]corev1.EnvVar{
×
200
                {
×
201
                        // deprecated: left here for CI test.
×
202
                        Name:  util.OperatorWebhookModeEnv,
×
203
                        Value: "false",
×
204
                },
×
205
                {
×
206
                        Name:  util.ContainerAppName,
×
207
                        Value: util.ContainerOperatorApp,
×
208
                },
×
209
                {
×
210
                        Name:  "KVM_EMULATION",
×
211
                        Value: "",
×
212
                },
×
213
                {
×
214
                        Name:  "OPERATOR_IMAGE",
×
215
                        Value: params.Image,
×
216
                },
×
217
                {
×
218
                        Name:  "OPERATOR_NAME",
×
219
                        Value: util.HCOOperatorName,
×
220
                },
×
221
                {
×
222
                        Name:  "OPERATOR_NAMESPACE",
×
223
                        Value: params.Namespace,
×
224
                },
×
225
                {
×
226
                        Name: "POD_NAME",
×
227
                        ValueFrom: &corev1.EnvVarSource{
×
228
                                FieldRef: &corev1.ObjectFieldSelector{
×
229
                                        FieldPath: "metadata.name",
×
230
                                },
×
231
                        },
×
232
                },
×
233
                {
×
234
                        Name:  "VIRTIOWIN_CONTAINER",
×
235
                        Value: params.VirtIOWinContainer,
×
236
                },
×
237
                {
×
238
                        Name:  "SMBIOS",
×
239
                        Value: params.Smbios,
×
240
                },
×
241
                {
×
242
                        Name:  "MACHINETYPE",
×
243
                        Value: params.Machinetype,
×
244
                },
×
245
                {
×
246
                        Name:  "AMD64_MACHINETYPE",
×
247
                        Value: params.Amd64MachineType,
×
248
                },
×
249
                {
×
250
                        Name:  "ARM64_MACHINETYPE",
×
251
                        Value: params.Arm64MachineType,
×
252
                },
×
253
                {
×
254
                        Name:  util.HcoKvIoVersionName,
×
255
                        Value: params.HcoKvIoVersion,
×
256
                },
×
257
                {
×
258
                        Name:  util.KubevirtVersionEnvV,
×
259
                        Value: params.KubevirtVersion,
×
260
                },
×
261
                {
×
262
                        Name:  util.CdiVersionEnvV,
×
263
                        Value: params.CdiVersion,
×
264
                },
×
265
                {
×
266
                        Name:  util.CnaoVersionEnvV,
×
267
                        Value: params.CnaoVersion,
×
268
                },
×
269
                {
×
270
                        Name:  util.SspVersionEnvV,
×
271
                        Value: params.SspVersion,
×
272
                },
×
273
                {
×
274
                        Name:  util.HppoVersionEnvV,
×
275
                        Value: params.HppoVersion,
×
276
                },
×
277
                {
×
278
                        Name:  util.AaqVersionEnvV,
×
279
                        Value: params.AaqVersion,
×
280
                },
×
281
                {
×
282
                        Name:  util.KVUIPluginImageEnvV,
×
283
                        Value: params.KVUIPluginImage,
×
284
                },
×
285
                {
×
286
                        Name:  util.KVUIProxyImageEnvV,
×
287
                        Value: params.KVUIProxyImage,
×
288
                },
×
289
                {
×
290
                        Name:  util.PasstImageEnvV,
×
291
                        Value: params.PasstImage,
×
292
                },
×
293
                {
×
294
                        Name:  util.PasstCNIImageEnvV,
×
295
                        Value: params.PasstCNIImage,
×
296
                },
×
297
                {
×
298
                        Name:  util.WaspAgentImageEnvV,
×
299
                        Value: params.WaspAgentImage,
×
300
                },
×
301
        }, params.Env...)
×
302

×
303
        if params.KvVirtLancherOsVersion != "" {
×
304
                envs = append(envs, corev1.EnvVar{
×
305
                        Name:  util.KvVirtLauncherOSVersionEnvV,
×
306
                        Value: params.KvVirtLancherOsVersion,
×
307
                })
×
308
        }
×
309

310
        if params.AddNetworkPolicyLabels {
×
311
                envs = append(envs, corev1.EnvVar{
×
312
                        Name:  util.DeployNetworkPoliciesEnvV,
×
313
                        Value: "true",
×
314
                })
×
315
        }
×
316

317
        return envs
×
318
}
319

320
func GetDeploymentSpecCliDownloads(params *DeploymentOperatorParams) appsv1.DeploymentSpec {
×
321
        return appsv1.DeploymentSpec{
×
322
                Replicas: ptr.To[int32](1),
×
323
                Selector: &metav1.LabelSelector{
×
324
                        MatchLabels: map[string]string{
×
325
                                "name": util.CLIDownloadsName,
×
326
                        },
×
327
                },
×
328
                Strategy: appsv1.DeploymentStrategy{
×
329
                        Type: appsv1.RollingUpdateDeploymentStrategyType,
×
330
                },
×
331
                Template: corev1.PodTemplateSpec{
×
332
                        ObjectMeta: metav1.ObjectMeta{
×
333
                                Labels: getLabels(util.CLIDownloadsName, params.HcoKvIoVersion),
×
334
                        },
×
335
                        Spec: corev1.PodSpec{
×
336
                                ServiceAccountName:           util.CLIDownloadsName,
×
337
                                AutomountServiceAccountToken: ptr.To(false),
×
338
                                SecurityContext:              GetStdPodSecurityContext(),
×
339
                                Containers: []corev1.Container{
×
340
                                        {
×
341
                                                Name:            "server",
×
342
                                                Image:           params.CliDownloadsImage,
×
343
                                                ImagePullPolicy: corev1.PullPolicy(params.ImagePullPolicy),
×
344
                                                Resources: corev1.ResourceRequirements{
×
345
                                                        Requests: map[corev1.ResourceName]resource.Quantity{
×
346
                                                                corev1.ResourceCPU:    resource.MustParse("10m"),
×
347
                                                                corev1.ResourceMemory: resource.MustParse("96Mi"),
×
348
                                                        },
×
349
                                                },
×
350
                                                Ports: []corev1.ContainerPort{
×
351
                                                        {
×
352
                                                                Protocol:      corev1.ProtocolTCP,
×
353
                                                                ContainerPort: util.CliDownloadsServerPort,
×
354
                                                        },
×
355
                                                },
×
356
                                                SecurityContext:          GetStdContainerSecurityContext(),
×
357
                                                ReadinessProbe:           getReadinessProbe("/health", util.CliDownloadsServerPort),
×
358
                                                LivenessProbe:            getLivenessProbe("/health", util.CliDownloadsServerPort),
×
359
                                                TerminationMessagePolicy: corev1.TerminationMessageFallbackToLogsOnError,
×
360
                                        },
×
361
                                },
×
362
                                PriorityClassName: "system-cluster-critical",
×
363
                        },
×
364
                },
×
365
        }
×
366
}
×
367

368
func getLabels(name, hcoKvIoVersion string) map[string]string {
×
369
        return map[string]string{
×
370
                "name":                 name,
×
371
                util.AppLabelVersion:   hcoKvIoVersion,
×
372
                util.AppLabelPartOf:    util.HyperConvergedCluster,
×
373
                util.AppLabelComponent: string(util.AppComponentDeployment),
×
374
        }
×
375
}
×
376

377
func getLabelsWithNetworkPolicies(deploymentName string, params *DeploymentOperatorParams) map[string]string {
×
378
        labels := getLabels(deploymentName, params.HcoKvIoVersion)
×
379
        if params.AddNetworkPolicyLabels {
×
380
                labels[util.AllowEgressToDNSAndAPIServerLabel] = "true"
×
381
                labels[util.AllowIngressToMetricsEndpointLabel] = "true"
×
382
        }
×
383

384
        return labels
×
385
}
386

387
func GetStdPodSecurityContext() *corev1.PodSecurityContext {
3✔
388
        return &corev1.PodSecurityContext{
3✔
389
                RunAsNonRoot: ptr.To(true),
3✔
390
                SeccompProfile: &corev1.SeccompProfile{
3✔
391
                        Type: corev1.SeccompProfileTypeRuntimeDefault,
3✔
392
                },
3✔
393
        }
3✔
394
}
3✔
395

396
func GetStdContainerSecurityContext() *corev1.SecurityContext {
3✔
397
        return &corev1.SecurityContext{
3✔
398
                AllowPrivilegeEscalation: ptr.To(false),
3✔
399
                Capabilities: &corev1.Capabilities{
3✔
400
                        Drop: []corev1.Capability{"ALL"},
3✔
401
                },
3✔
402
        }
3✔
403
}
3✔
404

405
// Currently we are abusing the pod readiness to signal to OLM that HCO is not ready
406
// for an upgrade. This has a lot of side effects, one of this is the validating webhook
407
// being not able to receive traffic when exposed by a pod that is not reporting ready=true.
408
// This can cause a lot of side effects if not deadlocks when the system reach a status where,
409
// for any possible reason, HCO pod cannot be ready and so HCO pod cannot validate any further update or
410
// delete request on HCO CR.
411
// A proper solution is properly use the readiness probe only to report the pod readiness and communicate
412
// status to OLM via conditions once OLM will be ready for:
413
// https://github.com/operator-framework/enhancements/blob/master/enhancements/operator-conditions.md
414
// in the meanwhile a quick (but dirty!) solution is to expose the same hco binary on two distinct pods:
415
// the first one will run only the controller and the second one (almost always ready) just the validating
416
// webhook one.
417
func GetDeploymentSpecWebhook(params *DeploymentOperatorParams) appsv1.DeploymentSpec {
×
418
        return appsv1.DeploymentSpec{
×
419
                Replicas: ptr.To[int32](1),
×
420
                Selector: &metav1.LabelSelector{
×
421
                        MatchLabels: map[string]string{
×
422
                                "name": util.HCOWebhookName,
×
423
                        },
×
424
                },
×
425
                Strategy: appsv1.DeploymentStrategy{
×
426
                        Type: appsv1.RollingUpdateDeploymentStrategyType,
×
427
                },
×
428
                Template: corev1.PodTemplateSpec{
×
429
                        ObjectMeta: metav1.ObjectMeta{
×
430
                                Labels: getLabelsWithNetworkPolicies(util.HCOWebhookName, params),
×
431
                        },
×
432
                        Spec: corev1.PodSpec{
×
433
                                ServiceAccountName: util.HCOOperatorName,
×
434
                                SecurityContext:    GetStdPodSecurityContext(),
×
435
                                Containers: []corev1.Container{
×
436
                                        {
×
437
                                                Name:            util.HCOWebhookName,
×
438
                                                Image:           params.WebhookImage,
×
439
                                                ImagePullPolicy: corev1.PullPolicy(params.ImagePullPolicy),
×
440
                                                Command:         stringListToSlice(util.HCOWebhookName),
×
441
                                                ReadinessProbe:  getReadinessProbe(util.ReadinessEndpointName, util.HealthProbePort),
×
442
                                                LivenessProbe:   getLivenessProbe(util.LivenessEndpointName, util.HealthProbePort),
×
443
                                                Env: append([]corev1.EnvVar{
×
444
                                                        {
×
445
                                                                // deprecated: left here for CI test.
×
446
                                                                Name:  util.OperatorWebhookModeEnv,
×
447
                                                                Value: "true",
×
448
                                                        },
×
449
                                                        {
×
450
                                                                Name:  util.ContainerAppName,
×
451
                                                                Value: util.ContainerWebhookApp,
×
452
                                                        },
×
453
                                                        {
×
454
                                                                Name:  "OPERATOR_IMAGE",
×
455
                                                                Value: params.WebhookImage,
×
456
                                                        },
×
457
                                                        {
×
458
                                                                Name:  "OPERATOR_NAME",
×
459
                                                                Value: util.HCOWebhookName,
×
460
                                                        },
×
461
                                                        {
×
462
                                                                Name:  "OPERATOR_NAMESPACE",
×
463
                                                                Value: params.Namespace,
×
464
                                                        },
×
465
                                                        {
×
466
                                                                Name: "POD_NAME",
×
467
                                                                ValueFrom: &corev1.EnvVarSource{
×
468
                                                                        FieldRef: &corev1.ObjectFieldSelector{
×
469
                                                                                FieldPath: "metadata.name",
×
470
                                                                        },
×
471
                                                                },
×
472
                                                        },
×
473
                                                        {
×
474
                                                                Name:  util.HcoKvIoVersionName,
×
475
                                                                Value: params.HcoKvIoVersion,
×
476
                                                        },
×
477
                                                }, params.Env...),
×
478
                                                Resources: corev1.ResourceRequirements{
×
479
                                                        Requests: map[corev1.ResourceName]resource.Quantity{
×
480
                                                                corev1.ResourceCPU:    resource.MustParse("5m"),
×
481
                                                                corev1.ResourceMemory: resource.MustParse("48Mi"),
×
482
                                                        },
×
483
                                                },
×
484
                                                SecurityContext:          GetStdContainerSecurityContext(),
×
485
                                                TerminationMessagePolicy: corev1.TerminationMessageFallbackToLogsOnError,
×
486
                                                Ports: []corev1.ContainerPort{
×
487
                                                        getWebhookPort(),
×
488
                                                        getMetricsPort(),
×
489
                                                },
×
490
                                        },
×
491
                                },
×
492
                                PriorityClassName: "system-node-critical",
×
493
                        },
×
494
                },
×
495
        }
×
496
}
×
497

498
func GetClusterRole() rbacv1.ClusterRole {
×
499
        return rbacv1.ClusterRole{
×
500
                TypeMeta: metav1.TypeMeta{
×
501
                        APIVersion: rbacVersionV1,
×
502
                        Kind:       "ClusterRole",
×
503
                },
×
504
                ObjectMeta: metav1.ObjectMeta{
×
505
                        Name: util.HCOOperatorName,
×
506
                        Labels: map[string]string{
×
507
                                "name": util.HCOOperatorName,
×
508
                        },
×
509
                },
×
510
                Rules: GetClusterPermissions(),
×
511
        }
×
512
}
×
513

514
var (
515
        emptyAPIGroup = []string{""}
516
)
517

518
func GetClusterPermissions() []rbacv1.PolicyRule {
×
519
        const configOpenshiftIO = "config.openshift.io"
×
520
        const operatorOpenshiftIO = "operator.openshift.io"
×
521
        return []rbacv1.PolicyRule{
×
522
                {
×
523
                        APIGroups: stringListToSlice(util.APIVersionGroup),
×
524
                        Resources: stringListToSlice("hyperconvergeds"),
×
525
                        Verbs:     stringListToSlice("get", "list", "update", "watch"),
×
526
                },
×
527
                {
×
528
                        APIGroups: stringListToSlice(util.APIVersionGroup),
×
529
                        Resources: stringListToSlice("hyperconvergeds/finalizers", "hyperconvergeds/status"),
×
530
                        Verbs:     stringListToSlice("get", "list", "create", "update", "watch"),
×
531
                },
×
532
                roleWithAllPermissions(kvapi.GroupName, stringListToSlice("kubevirts", "kubevirts/finalizers")),
×
533
                roleWithAllPermissions(cdiapi.GroupName, stringListToSlice("cdis", "cdis/finalizers")),
×
534
                roleWithAllPermissions(sspapi.GroupVersion.Group, stringListToSlice("ssps", "ssps/finalizers")),
×
535
                roleWithAllPermissions(cnaoapi.GroupVersion.Group, stringListToSlice("networkaddonsconfigs", "networkaddonsconfigs/finalizers")),
×
536
                roleWithAllPermissions(aaqapi.GroupName, stringListToSlice("aaqs", "aaqs/finalizers")),
×
537
                roleWithAllPermissions("", stringListToSlice("configmaps")),
×
538
                {
×
539
                        APIGroups: emptyAPIGroup,
×
540
                        Resources: stringListToSlice("events"),
×
541
                        Verbs:     stringListToSlice("get", "list", "watch", "create", "patch"),
×
542
                },
×
543
                roleWithAllPermissions("", stringListToSlice("services")),
×
544
                {
×
545
                        APIGroups: emptyAPIGroup,
×
546
                        Resources: stringListToSlice("pods", "nodes"),
×
NEW
547
                        Verbs:     stringListToSlice("get", "list", "watch", "update"),
×
548
                },
×
549
                {
×
550
                        APIGroups: emptyAPIGroup,
×
551
                        Resources: stringListToSlice("secrets"),
×
552
                        Verbs:     stringListToSlice("get", "list", "watch", "create", "update", "delete"),
×
553
                },
×
554
                {
×
555
                        APIGroups: emptyAPIGroup,
×
556
                        Resources: stringListToSlice("endpoints"),
×
557
                        Verbs:     stringListToSlice("get", "list", "delete", "watch"),
×
558
                },
×
559
                {
×
560
                        APIGroups: emptyAPIGroup,
×
561
                        Resources: stringListToSlice("namespaces"),
×
562
                        Verbs:     stringListToSlice("get", "list", "watch", "patch", "update"),
×
563
                },
×
564
                {
×
565
                        APIGroups: stringListToSlice("apps"),
×
566
                        Resources: stringListToSlice("deployments", "replicasets", "daemonsets"),
×
567
                        Verbs:     stringListToSlice("get", "list", "watch", "create", "update", "delete"),
×
568
                },
×
569
                roleWithAllPermissions("rbac.authorization.k8s.io",
×
570
                        stringListToSlice("roles", "clusterroles", "rolebindings", "clusterrolebindings")),
×
571
                {
×
572
                        APIGroups: stringListToSlice("apiextensions.k8s.io"),
×
573
                        Resources: stringListToSlice("customresourcedefinitions"),
×
574
                        Verbs:     stringListToSlice("get", "list", "watch", "delete"),
×
575
                },
×
576
                {
×
577
                        APIGroups: stringListToSlice("apiextensions.k8s.io"),
×
578
                        Resources: stringListToSlice("customresourcedefinitions/status"),
×
579
                        Verbs:     stringListToSlice("get", "list", "watch", "patch", "update"),
×
580
                },
×
581
                roleWithAllPermissions("monitoring.coreos.com", stringListToSlice("servicemonitors", "prometheusrules")),
×
582
                {
×
583
                        APIGroups: stringListToSlice("operators.coreos.com"),
×
584
                        Resources: stringListToSlice("clusterserviceversions"),
×
585
                        Verbs:     stringListToSlice("get", "list", "watch", "update", "patch"),
×
586
                },
×
587
                {
×
588
                        APIGroups: stringListToSlice("scheduling.k8s.io"),
×
589
                        Resources: stringListToSlice("priorityclasses"),
×
590
                        Verbs:     stringListToSlice("get", "list", "watch", "create", "delete", "patch"),
×
591
                },
×
592
                {
×
593
                        APIGroups: stringListToSlice("admissionregistration.k8s.io"),
×
594
                        Resources: stringListToSlice("validatingwebhookconfigurations"),
×
595
                        Verbs:     stringListToSlice("list", "watch", "update", "patch"),
×
596
                },
×
597
                roleWithAllPermissions("console.openshift.io", stringListToSlice("consoleclidownloads", "consolequickstarts")),
×
598
                {
×
599
                        APIGroups: stringListToSlice(configOpenshiftIO),
×
600
                        Resources: stringListToSlice("clusterversions", "infrastructures", "networks"),
×
601
                        Verbs:     stringListToSlice("get", "list"),
×
602
                },
×
603
                {
×
604
                        APIGroups: stringListToSlice(configOpenshiftIO),
×
605
                        Resources: stringListToSlice("ingresses"),
×
606
                        Verbs:     stringListToSlice("get", "list", "watch"),
×
607
                },
×
608
                {
×
609
                        APIGroups: stringListToSlice(configOpenshiftIO),
×
610
                        Resources: stringListToSlice("ingresses/status"),
×
611
                        Verbs:     stringListToSlice("update"),
×
612
                },
×
613
                {
×
614
                        APIGroups: stringListToSlice(configOpenshiftIO),
×
615
                        Resources: stringListToSlice("apiservers"),
×
616
                        Verbs:     stringListToSlice("get", "list", "watch"),
×
617
                },
×
618
                {
×
619
                        APIGroups: stringListToSlice(operatorOpenshiftIO),
×
620
                        Resources: stringListToSlice("kubedeschedulers"),
×
621
                        Verbs:     stringListToSlice("get", "list", "watch"),
×
622
                },
×
623
                {
×
624
                        APIGroups: stringListToSlice(configOpenshiftIO),
×
625
                        Resources: stringListToSlice("dnses"),
×
626
                        Verbs:     stringListToSlice("get"),
×
627
                },
×
628
                roleWithAllPermissions("coordination.k8s.io", stringListToSlice("leases")),
×
629
                roleWithAllPermissions("route.openshift.io", stringListToSlice("routes")),
×
630
                {
×
631
                        APIGroups: stringListToSlice("route.openshift.io"),
×
632
                        Resources: stringListToSlice("routes/custom-host"),
×
633
                        Verbs:     stringListToSlice("create", "update", "patch"),
×
634
                },
×
635
                {
×
636
                        APIGroups: stringListToSlice("operators.coreos.com"),
×
637
                        Resources: stringListToSlice("operatorconditions"),
×
638
                        Verbs:     stringListToSlice("get", "list", "watch", "update", "patch"),
×
639
                },
×
640
                roleWithAllPermissions("image.openshift.io", stringListToSlice("imagestreams")),
×
641
                roleWithAllPermissions("console.openshift.io", stringListToSlice("consoleplugins")),
×
642
                {
×
643
                        APIGroups: stringListToSlice("operator.openshift.io"),
×
644
                        Resources: stringListToSlice("consoles"),
×
645
                        Verbs:     stringListToSlice("get", "list", "watch", "update"),
×
646
                },
×
647
                {
×
648
                        APIGroups: stringListToSlice("monitoring.coreos.com"),
×
649
                        Resources: stringListToSlice("alertmanagers", "alertmanagers/api"),
×
650
                        Verbs:     stringListToSlice("get", "list", "create", "delete"),
×
651
                },
×
652
                {
×
653
                        APIGroups: stringListToSlice(""),
×
654
                        Resources: stringListToSlice("serviceaccounts"),
×
655
                        Verbs:     stringListToSlice("get", "list", "watch", "create", "update", "delete"),
×
656
                },
×
657
                {
×
658
                        APIGroups: stringListToSlice("k8s.cni.cncf.io"),
×
659
                        Resources: stringListToSlice("network-attachment-definitions"),
×
660
                        Verbs:     stringListToSlice("get", "list", "watch", "create", "update", "delete"),
×
661
                },
×
662
                {
×
663
                        APIGroups: stringListToSlice("security.openshift.io"),
×
664
                        Resources: stringListToSlice("securitycontextconstraints"),
×
665
                        Verbs:     stringListToSlice("get", "list", "watch", "create", "update", "delete"),
×
666
                },
×
667
                {
×
668
                        APIGroups: stringListToSlice(networkingv1.GroupName),
×
669
                        Resources: stringListToSlice("networkpolicies"),
×
670
                        Verbs:     stringListToSlice("get", "list", "watch", "create", "update", "delete"),
×
671
                },
×
672
        }
×
673
}
×
674

675
func roleWithAllPermissions(apiGroup string, resources []string) rbacv1.PolicyRule {
×
676
        return rbacv1.PolicyRule{
×
677
                APIGroups: stringListToSlice(apiGroup),
×
678
                Resources: resources,
×
679
                Verbs:     stringListToSlice("get", "list", "watch", "create", "update", "delete", "patch"),
×
680
        }
×
681
}
×
682

683
func GetServiceAccount(namespace string) corev1.ServiceAccount {
×
684
        return createServiceAccount(namespace, util.HCOOperatorName)
×
685
}
×
686

687
func GetCLIDownloadServiceAccount(namespace string) corev1.ServiceAccount {
×
688
        return createServiceAccount(namespace, util.CLIDownloadsName)
×
689
}
×
690

691
func createServiceAccount(namespace, name string) corev1.ServiceAccount {
×
692
        return corev1.ServiceAccount{
×
693
                TypeMeta: metav1.TypeMeta{
×
694
                        APIVersion: "v1",
×
695
                        Kind:       "ServiceAccount",
×
696
                },
×
697
                ObjectMeta: metav1.ObjectMeta{
×
698
                        Name:      name,
×
699
                        Namespace: namespace,
×
700
                        Labels: map[string]string{
×
701
                                "name": name,
×
702
                        },
×
703
                },
×
704
        }
×
705
}
×
706

707
func GetClusterRoleBinding(namespace string) rbacv1.ClusterRoleBinding {
×
708
        return rbacv1.ClusterRoleBinding{
×
709
                TypeMeta: metav1.TypeMeta{
×
710
                        APIVersion: rbacVersionV1,
×
711
                        Kind:       "ClusterRoleBinding",
×
712
                },
×
713
                ObjectMeta: metav1.ObjectMeta{
×
714
                        Name: util.HCOOperatorName,
×
715
                        Labels: map[string]string{
×
716
                                "name": util.HCOOperatorName,
×
717
                        },
×
718
                },
×
719
                RoleRef: rbacv1.RoleRef{
×
720
                        APIGroup: "rbac.authorization.k8s.io",
×
721
                        Kind:     "ClusterRole",
×
722
                        Name:     util.HCOOperatorName,
×
723
                },
×
724
                Subjects: []rbacv1.Subject{
×
725
                        {
×
726
                                Kind:      "ServiceAccount",
×
727
                                Name:      util.HCOOperatorName,
×
728
                                Namespace: namespace,
×
729
                        },
×
730
                },
×
731
        }
×
732
}
×
733

734
func GetOperatorCR() *hcov1beta1.HyperConverged {
13✔
735
        defaultScheme := runtime.NewScheme()
13✔
736
        _ = hcov1beta1.AddToScheme(defaultScheme)
13✔
737
        _ = hcov1beta1.RegisterDefaults(defaultScheme)
13✔
738
        defaultHco := &hcov1beta1.HyperConverged{
13✔
739
                TypeMeta: metav1.TypeMeta{
13✔
740
                        APIVersion: util.APIVersion,
13✔
741
                        Kind:       util.HyperConvergedKind,
13✔
742
                },
13✔
743
                ObjectMeta: metav1.ObjectMeta{
13✔
744
                        Name: crName,
13✔
745
                }}
13✔
746
        defaultScheme.Default(defaultHco)
13✔
747
        return defaultHco
13✔
748
}
13✔
749

750
// GetInstallStrategyBase returns the basics of an HCO InstallStrategy
751
func GetInstallStrategyBase(params *DeploymentOperatorParams) *csvv1alpha1.StrategyDetailsDeployment {
×
752
        return &csvv1alpha1.StrategyDetailsDeployment{
×
753

×
754
                DeploymentSpecs: []csvv1alpha1.StrategyDeploymentSpec{
×
755
                        {
×
756
                                Name:  hcoDeploymentName,
×
757
                                Spec:  GetDeploymentSpecOperator(params),
×
758
                                Label: getLabels(util.HCOOperatorName, params.HcoKvIoVersion),
×
759
                        },
×
760
                        {
×
761
                                Name:  hcoWhDeploymentName,
×
762
                                Spec:  GetDeploymentSpecWebhook(params),
×
763
                                Label: getLabels(util.HCOWebhookName, params.HcoKvIoVersion),
×
764
                        },
×
765
                        {
×
766
                                Name:  util.CLIDownloadsName,
×
767
                                Spec:  GetDeploymentSpecCliDownloads(params),
×
768
                                Label: getLabels(util.CLIDownloadsName, params.HcoKvIoVersion),
×
769
                        },
×
770
                },
×
771
                Permissions: []csvv1alpha1.StrategyDeploymentPermissions{},
×
772
                ClusterPermissions: []csvv1alpha1.StrategyDeploymentPermissions{
×
773
                        {
×
774
                                ServiceAccountName: util.HCOOperatorName,
×
775
                                Rules:              GetClusterPermissions(),
×
776
                        },
×
777
                        {
×
778
                                ServiceAccountName: util.CLIDownloadsName,
×
779
                                Rules:              []rbacv1.PolicyRule{},
×
780
                        },
×
781
                },
×
782
        }
×
783
}
×
784

785
type CSVBaseParams struct {
786
        Name            string
787
        Namespace       string
788
        DisplayName     string
789
        MetaDescription string
790
        Description     string
791
        Image           string
792
        Version         semver.Version
793
        CrdDisplay      string
794
        Icon            string
795
}
796

797
// GetCSVBase returns a base HCO CSV without an InstallStrategy
798
func GetCSVBase(params *CSVBaseParams) *csvv1alpha1.ClusterServiceVersion {
×
799
        almExamples, _ := json.Marshal(
×
800
                map[string]interface{}{
×
801
                        "apiVersion": util.APIVersion,
×
802
                        "kind":       util.HyperConvergedKind,
×
803
                        "metadata": map[string]interface{}{
×
804
                                "name":      packageName,
×
805
                                "namespace": params.Namespace,
×
806
                                "annotations": map[string]string{
×
807
                                        "deployOVS": "false",
×
808
                                },
×
809
                        },
×
810
                        "spec": map[string]interface{}{},
×
811
                })
×
812

×
813
        // Explicitly fail on unvalidated (for any reason) requests:
×
814
        // this can make removing HCO CR harder if HCO webhook is not able
×
815
        // to really validate the requests.
×
816
        // In that case the user can only directly remove the
×
817
        // ValidatingWebhookConfiguration object first (eventually bypassing the OLM if needed).
×
818
        // so failurePolicy = admissionregistrationv1.Fail
×
819

×
820
        validatingWebhook := csvv1alpha1.WebhookDescription{
×
821
                GenerateName:            util.HcoValidatingWebhook,
×
822
                Type:                    csvv1alpha1.ValidatingAdmissionWebhook,
×
823
                DeploymentName:          hcoWhDeploymentName,
×
824
                ContainerPort:           util.WebhookPort,
×
825
                AdmissionReviewVersions: stringListToSlice("v1beta1", "v1"),
×
826
                SideEffects:             ptr.To(admissionregistrationv1.SideEffectClassNone),
×
827
                FailurePolicy:           ptr.To(admissionregistrationv1.Fail),
×
828
                TimeoutSeconds:          ptr.To[int32](10),
×
829
                Rules: []admissionregistrationv1.RuleWithOperations{
×
830
                        {
×
831
                                Operations: []admissionregistrationv1.OperationType{
×
832
                                        admissionregistrationv1.Create,
×
833
                                        admissionregistrationv1.Delete,
×
834
                                        admissionregistrationv1.Update,
×
835
                                },
×
836
                                Rule: admissionregistrationv1.Rule{
×
837
                                        APIGroups:   stringListToSlice(util.APIVersionGroup),
×
838
                                        APIVersions: stringListToSlice(util.APIVersionBeta),
×
839
                                        Resources:   stringListToSlice("hyperconvergeds"),
×
840
                                },
×
841
                        },
×
842
                },
×
843
                WebhookPath: ptr.To(util.HCOWebhookPath),
×
844
        }
×
845

×
846
        mutatingNamespaceWebhook := csvv1alpha1.WebhookDescription{
×
847
                GenerateName:            util.HcoMutatingWebhookNS,
×
848
                Type:                    csvv1alpha1.MutatingAdmissionWebhook,
×
849
                DeploymentName:          hcoWhDeploymentName,
×
850
                ContainerPort:           util.WebhookPort,
×
851
                AdmissionReviewVersions: stringListToSlice("v1beta1", "v1"),
×
852
                SideEffects:             ptr.To(admissionregistrationv1.SideEffectClassNoneOnDryRun),
×
853
                FailurePolicy:           ptr.To(admissionregistrationv1.Fail),
×
854
                TimeoutSeconds:          ptr.To[int32](10),
×
855
                ObjectSelector: &metav1.LabelSelector{
×
856
                        MatchLabels: map[string]string{util.KubernetesMetadataName: params.Namespace},
×
857
                },
×
858
                Rules: []admissionregistrationv1.RuleWithOperations{
×
859
                        {
×
860
                                Operations: []admissionregistrationv1.OperationType{
×
861
                                        admissionregistrationv1.Delete,
×
862
                                },
×
863
                                Rule: admissionregistrationv1.Rule{
×
864
                                        APIGroups:   []string{""},
×
865
                                        APIVersions: stringListToSlice("v1"),
×
866
                                        Resources:   stringListToSlice("namespaces"),
×
867
                                },
×
868
                        },
×
869
                },
×
870
                WebhookPath: ptr.To(util.HCONSWebhookPath),
×
871
        }
×
872

×
873
        mutatingHyperConvergedWebhook := csvv1alpha1.WebhookDescription{
×
874
                GenerateName:            util.HcoMutatingWebhookHyperConverged,
×
875
                Type:                    csvv1alpha1.MutatingAdmissionWebhook,
×
876
                DeploymentName:          hcoWhDeploymentName,
×
877
                ContainerPort:           util.WebhookPort,
×
878
                AdmissionReviewVersions: stringListToSlice("v1beta1", "v1"),
×
879
                SideEffects:             ptr.To(admissionregistrationv1.SideEffectClassNoneOnDryRun),
×
880
                FailurePolicy:           ptr.To(admissionregistrationv1.Fail),
×
881
                TimeoutSeconds:          ptr.To[int32](10),
×
882
                Rules: []admissionregistrationv1.RuleWithOperations{
×
883
                        {
×
884
                                Operations: []admissionregistrationv1.OperationType{
×
885
                                        admissionregistrationv1.Create,
×
886
                                        admissionregistrationv1.Update,
×
887
                                },
×
888
                                Rule: admissionregistrationv1.Rule{
×
889
                                        APIGroups:   stringListToSlice(util.APIVersionGroup),
×
890
                                        APIVersions: stringListToSlice(util.APIVersionBeta),
×
891
                                        Resources:   stringListToSlice("hyperconvergeds"),
×
892
                                },
×
893
                        },
×
894
                },
×
895
                WebhookPath: ptr.To(util.HCOMutatingWebhookPath),
×
896
        }
×
897

×
898
        return &csvv1alpha1.ClusterServiceVersion{
×
899
                TypeMeta: metav1.TypeMeta{
×
900
                        APIVersion: "operators.coreos.com/v1alpha1",
×
901
                        Kind:       "ClusterServiceVersion",
×
902
                },
×
903
                ObjectMeta: metav1.ObjectMeta{
×
904
                        Name:      fmt.Sprintf("%v.v%v", params.Name, params.Version.String()),
×
905
                        Namespace: params.Namespace,
×
906
                        Annotations: map[string]string{
×
907
                                "alm-examples":                   string(almExamples),
×
908
                                "capabilities":                   "Deep Insights",
×
909
                                "certified":                      "false",
×
910
                                "categories":                     "OpenShift Optional",
×
911
                                "containerImage":                 params.Image,
×
912
                                DisableOperandDeletionAnnotation: "true",
×
913
                                "createdAt":                      time.Now().Format("2006-01-02 15:04:05"),
×
914
                                "description":                    params.MetaDescription,
×
915
                                "repository":                     "https://github.com/kubevirt/hyperconverged-cluster-operator",
×
916
                                "support":                        "false",
×
917
                                "operatorframework.io/suggested-namespace":         params.Namespace,
×
918
                                "operatorframework.io/initialization-resource":     string(almExamples),
×
919
                                "operators.openshift.io/infrastructure-features":   `["disconnected","proxy-aware"]`, // TODO: deprecated, remove once all the tools support "features.operators.openshift.io/*"
×
920
                                "features.operators.openshift.io/disconnected":     "true",
×
921
                                "features.operators.openshift.io/fips-compliant":   "false",
×
922
                                "features.operators.openshift.io/proxy-aware":      "true",
×
923
                                "features.operators.openshift.io/cnf":              "false",
×
924
                                "features.operators.openshift.io/cni":              "true",
×
925
                                "features.operators.openshift.io/csi":              "true",
×
926
                                "features.operators.openshift.io/tls-profiles":     "true",
×
927
                                "features.operators.openshift.io/token-auth-aws":   "false",
×
928
                                "features.operators.openshift.io/token-auth-azure": "false",
×
929
                                "features.operators.openshift.io/token-auth-gcp":   "false",
×
930
                                "openshift.io/required-scc":                        "restricted-v2",
×
931
                        },
×
932
                },
×
933
                Spec: csvv1alpha1.ClusterServiceVersionSpec{
×
934
                        DisplayName: params.DisplayName,
×
935
                        Description: params.Description,
×
936
                        Keywords:    stringListToSlice("KubeVirt", "Virtualization"),
×
937
                        Version:     csvVersion.OperatorVersion{Version: params.Version},
×
938
                        Maintainers: []csvv1alpha1.Maintainer{
×
939
                                {
×
940
                                        Name:  kubevirtProjectName,
×
941
                                        Email: "kubevirt-dev@googlegroups.com",
×
942
                                },
×
943
                        },
×
944
                        Maturity: "alpha",
×
945
                        Provider: csvv1alpha1.AppLink{
×
946
                                Name: kubevirtProjectName,
×
947
                                // https://github.com/operator-framework/operator-courier/issues/173
×
948
                                // URL:  "https://kubevirt.io",
×
949
                        },
×
950
                        Links: []csvv1alpha1.AppLink{
×
951
                                {
×
952
                                        Name: kubevirtProjectName,
×
953
                                        URL:  "https://kubevirt.io",
×
954
                                },
×
955
                                {
×
956
                                        Name: "Source Code",
×
957
                                        URL:  "https://github.com/kubevirt/hyperconverged-cluster-operator",
×
958
                                },
×
959
                        },
×
960
                        Icon: []csvv1alpha1.Icon{
×
961
                                {
×
962
                                        MediaType: "image/svg+xml",
×
963
                                        Data:      params.Icon,
×
964
                                },
×
965
                        },
×
966
                        Labels: map[string]string{
×
967
                                "alm-owner-kubevirt": packageName,
×
968
                                "operated-by":        packageName,
×
969
                        },
×
970
                        Selector: &metav1.LabelSelector{
×
971
                                MatchLabels: map[string]string{
×
972
                                        "alm-owner-kubevirt": packageName,
×
973
                                        "operated-by":        packageName,
×
974
                                },
×
975
                        },
×
976
                        InstallModes: []csvv1alpha1.InstallMode{
×
977
                                {
×
978
                                        Type:      csvv1alpha1.InstallModeTypeOwnNamespace,
×
979
                                        Supported: false,
×
980
                                },
×
981
                                {
×
982
                                        Type:      csvv1alpha1.InstallModeTypeSingleNamespace,
×
983
                                        Supported: false,
×
984
                                },
×
985
                                {
×
986
                                        Type:      csvv1alpha1.InstallModeTypeMultiNamespace,
×
987
                                        Supported: false,
×
988
                                },
×
989
                                {
×
990
                                        Type:      csvv1alpha1.InstallModeTypeAllNamespaces,
×
991
                                        Supported: true,
×
992
                                },
×
993
                        },
×
994
                        // Skip this in favor of having a separate function to get
×
995
                        // the actual StrategyDetailsDeployment when merging CSVs
×
996
                        InstallStrategy: csvv1alpha1.NamedInstallStrategy{},
×
997
                        WebhookDefinitions: []csvv1alpha1.WebhookDescription{
×
998
                                validatingWebhook,
×
999
                                mutatingNamespaceWebhook,
×
1000
                                mutatingHyperConvergedWebhook,
×
1001
                        },
×
1002
                        CustomResourceDefinitions: csvv1alpha1.CustomResourceDefinitions{
×
1003
                                Owned: []csvv1alpha1.CRDDescription{
×
1004
                                        {
×
1005
                                                Name:        "hyperconvergeds.hco.kubevirt.io",
×
1006
                                                Version:     util.CurrentAPIVersion,
×
1007
                                                Kind:        util.HyperConvergedKind,
×
1008
                                                DisplayName: params.CrdDisplay + " Deployment",
×
1009
                                                Description: "Represents the deployment of " + params.CrdDisplay,
×
1010
                                                // TODO: move this to annotations on hyperconverged_types.go once kubebuilder
×
1011
                                                // properly supports SpecDescriptors as the operator-sdk already does
×
1012
                                                SpecDescriptors: []csvv1alpha1.SpecDescriptor{
×
1013
                                                        {
×
1014
                                                                DisplayName: "Infra components node affinity",
×
1015
                                                                Description: "nodeAffinity describes node affinity scheduling rules for the infra pods.",
×
1016
                                                                Path:        "infra.nodePlacement.affinity.nodeAffinity",
×
1017
                                                                XDescriptors: stringListToSlice(
×
1018
                                                                        "urn:alm:descriptor:com.tectonic.ui:nodeAffinity",
×
1019
                                                                ),
×
1020
                                                        },
×
1021
                                                        {
×
1022
                                                                DisplayName: "Infra components pod affinity",
×
1023
                                                                Description: "podAffinity describes pod affinity scheduling rules for the infra pods.",
×
1024
                                                                Path:        "infra.nodePlacement.affinity.podAffinity",
×
1025
                                                                XDescriptors: stringListToSlice(
×
1026
                                                                        "urn:alm:descriptor:com.tectonic.ui:podAffinity",
×
1027
                                                                ),
×
1028
                                                        },
×
1029
                                                        {
×
1030
                                                                DisplayName: "Infra components pod anti-affinity",
×
1031
                                                                Description: "podAntiAffinity describes pod anti affinity scheduling rules for the infra pods.",
×
1032
                                                                Path:        "infra.nodePlacement.affinity.podAntiAffinity",
×
1033
                                                                XDescriptors: stringListToSlice(
×
1034
                                                                        "urn:alm:descriptor:com.tectonic.ui:podAntiAffinity",
×
1035
                                                                ),
×
1036
                                                        },
×
1037
                                                        {
×
1038
                                                                DisplayName: "Workloads components node affinity",
×
1039
                                                                Description: "nodeAffinity describes node affinity scheduling rules for the workloads pods.",
×
1040
                                                                Path:        "workloads.nodePlacement.affinity.nodeAffinity",
×
1041
                                                                XDescriptors: stringListToSlice(
×
1042
                                                                        "urn:alm:descriptor:com.tectonic.ui:nodeAffinity",
×
1043
                                                                ),
×
1044
                                                        },
×
1045
                                                        {
×
1046
                                                                DisplayName: "Workloads components pod affinity",
×
1047
                                                                Description: "podAffinity describes pod affinity scheduling rules for the workloads pods.",
×
1048
                                                                Path:        "workloads.nodePlacement.affinity.podAffinity",
×
1049
                                                                XDescriptors: stringListToSlice(
×
1050
                                                                        "urn:alm:descriptor:com.tectonic.ui:podAffinity",
×
1051
                                                                ),
×
1052
                                                        },
×
1053
                                                        {
×
1054
                                                                DisplayName: "Workloads components pod anti-affinity",
×
1055
                                                                Description: "podAntiAffinity describes pod anti affinity scheduling rules for the workloads pods.",
×
1056
                                                                Path:        "workloads.nodePlacement.affinity.podAntiAffinity",
×
1057
                                                                XDescriptors: stringListToSlice(
×
1058
                                                                        "urn:alm:descriptor:com.tectonic.ui:podAntiAffinity",
×
1059
                                                                ),
×
1060
                                                        },
×
1061
                                                        {
×
1062
                                                                DisplayName: "HIDDEN FIELDS - operator version",
×
1063
                                                                Description: "HIDDEN FIELDS - operator version.",
×
1064
                                                                Path:        "version",
×
1065
                                                                XDescriptors: stringListToSlice(
×
1066
                                                                        "urn:alm:descriptor:com.tectonic.ui:hidden",
×
1067
                                                                ),
×
1068
                                                        },
×
1069
                                                },
×
1070
                                                StatusDescriptors: []csvv1alpha1.StatusDescriptor{},
×
1071
                                        },
×
1072
                                },
×
1073
                                Required: []csvv1alpha1.CRDDescription{},
×
1074
                        },
×
1075
                },
×
1076
        }
×
1077
}
×
1078

1079
func InjectVolumesForWebHookCerts(deploy *appsv1.Deployment) {
×
1080
        // check if there is already a volume for api certificates
×
1081
        for _, vol := range deploy.Spec.Template.Spec.Volumes {
×
1082
                if vol.Name == certVolume {
×
1083
                        return
×
1084
                }
×
1085
        }
1086

1087
        volume := corev1.Volume{
×
1088
                Name: certVolume,
×
1089
                VolumeSource: corev1.VolumeSource{
×
1090
                        Secret: &corev1.SecretVolumeSource{
×
1091
                                SecretName:  deploy.Name + "-service-cert",
×
1092
                                DefaultMode: ptr.To[int32](420),
×
1093
                                Items: []corev1.KeyToPath{
×
1094
                                        {
×
1095
                                                Key:  "tls.crt",
×
1096
                                                Path: util.WebhookCertName,
×
1097
                                        },
×
1098
                                        {
×
1099
                                                Key:  "tls.key",
×
1100
                                                Path: util.WebhookKeyName,
×
1101
                                        },
×
1102
                                },
×
1103
                        },
×
1104
                },
×
1105
        }
×
1106
        deploy.Spec.Template.Spec.Volumes = append(deploy.Spec.Template.Spec.Volumes, volume)
×
1107

×
1108
        for index, container := range deploy.Spec.Template.Spec.Containers {
×
1109
                deploy.Spec.Template.Spec.Containers[index].VolumeMounts = append(container.VolumeMounts,
×
1110
                        corev1.VolumeMount{
×
1111
                                Name:      certVolume,
×
1112
                                MountPath: util.DefaultWebhookCertDir,
×
1113
                        })
×
1114
        }
×
1115
}
1116

1117
func getReadinessProbe(endpoint string, port int32) *corev1.Probe {
×
1118
        return &corev1.Probe{
×
1119
                ProbeHandler: corev1.ProbeHandler{
×
1120
                        HTTPGet: &corev1.HTTPGetAction{
×
1121
                                Path: endpoint,
×
1122
                                Port: intstr.IntOrString{
×
1123
                                        Type:   intstr.Int,
×
1124
                                        IntVal: port,
×
1125
                                },
×
1126
                                Scheme: corev1.URISchemeHTTP,
×
1127
                        },
×
1128
                },
×
1129
                InitialDelaySeconds: 5,
×
1130
                PeriodSeconds:       5,
×
1131
                FailureThreshold:    1,
×
1132
        }
×
1133
}
×
1134

1135
func getLivenessProbe(endpoint string, port int32) *corev1.Probe {
×
1136
        return &corev1.Probe{
×
1137
                ProbeHandler: corev1.ProbeHandler{
×
1138
                        HTTPGet: &corev1.HTTPGetAction{
×
1139
                                Path: endpoint,
×
1140
                                Port: intstr.IntOrString{
×
1141
                                        Type:   intstr.Int,
×
1142
                                        IntVal: port,
×
1143
                                },
×
1144
                                Scheme: corev1.URISchemeHTTP,
×
1145
                        },
×
1146
                },
×
1147
                InitialDelaySeconds: 30,
×
1148
                PeriodSeconds:       5,
×
1149
                FailureThreshold:    1,
×
1150
        }
×
1151
}
×
1152

1153
func getMetricsPort() corev1.ContainerPort {
×
1154
        return corev1.ContainerPort{
×
1155
                Name:          util.MetricsPortName,
×
1156
                ContainerPort: util.MetricsPort,
×
1157
                Protocol:      corev1.ProtocolTCP,
×
1158
        }
×
1159
}
×
1160

1161
func getWebhookPort() corev1.ContainerPort {
×
1162
        return corev1.ContainerPort{
×
1163
                Name:          util.WebhookPortName,
×
1164
                ContainerPort: util.WebhookPort,
×
1165
                Protocol:      corev1.ProtocolTCP,
×
1166
        }
×
1167
}
×
1168

1169
func stringListToSlice(words ...string) []string {
×
1170
        return words
×
1171
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc