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

kubevirt / hyperconverged-cluster-operator / 14350314198

09 Apr 2025 06:16AM UTC coverage: 72.262%. First build
14350314198

Pull #3386

github

web-flow
Merge 5292e1051 into 9ffa79842
Pull Request #3386: Set terminationMessagePolicy=FallbackToLogsOnError

1 of 9 new or added lines in 2 files covered. (11.11%)

6531 of 9038 relevant lines covered (72.26%)

0.95 hits per line

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

3.07
/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
        "golang.org/x/tools/go/packages"
13
        admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
14
        appsv1 "k8s.io/api/apps/v1"
15
        corev1 "k8s.io/api/core/v1"
16
        rbacv1 "k8s.io/api/rbac/v1"
17
        extv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
18
        "k8s.io/apimachinery/pkg/api/resource"
19
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
20
        "k8s.io/apimachinery/pkg/runtime"
21
        "k8s.io/apimachinery/pkg/runtime/schema"
22
        "k8s.io/apimachinery/pkg/util/intstr"
23
        "k8s.io/utils/ptr"
24
        crdgen "sigs.k8s.io/controller-tools/pkg/crd"
25
        crdmarkers "sigs.k8s.io/controller-tools/pkg/crd/markers"
26
        "sigs.k8s.io/controller-tools/pkg/loader"
27
        "sigs.k8s.io/controller-tools/pkg/markers"
28

29
        cnaoapi "github.com/kubevirt/cluster-network-addons-operator/pkg/apis/networkaddonsoperator/v1"
30
        kvapi "kubevirt.io/api/core"
31
        aaqapi "kubevirt.io/application-aware-quota/staging/src/kubevirt.io/application-aware-quota-api/pkg/apis/core"
32
        cdiapi "kubevirt.io/containerized-data-importer-api/pkg/apis/core"
33
        sspapi "kubevirt.io/ssp-operator/api/v1beta2"
34

35
        hcov1beta1 "github.com/kubevirt/hyperconverged-cluster-operator/api/v1beta1"
36
        "github.com/kubevirt/hyperconverged-cluster-operator/pkg/util"
37
)
38

39
const DisableOperandDeletionAnnotation = "console.openshift.io/disable-operand-delete"
40

41
const (
42
        crName              = util.HyperConvergedName
43
        packageName         = util.HyperConvergedName
44
        hcoName             = "hyperconverged-cluster-operator"
45
        hcoNameWebhook      = "hyperconverged-cluster-webhook"
46
        hcoDeploymentName   = "hco-operator"
47
        hcoWhDeploymentName = "hco-webhook"
48
        certVolume          = "apiservice-cert"
49

50
        cliDownloadsName = "hyperconverged-cluster-cli-download"
51

52
        kubevirtProjectName = "KubeVirt project"
53
        rbacVersionV1       = "rbac.authorization.k8s.io/v1"
54
)
55

56
var deploymentType = metav1.TypeMeta{
57
        APIVersion: "apps/v1",
58
        Kind:       "Deployment",
59
}
60

61
type DeploymentOperatorParams struct {
62
        Namespace              string
63
        Image                  string
64
        WebhookImage           string
65
        CliDownloadsImage      string
66
        KVUIPluginImage        string
67
        KVUIProxyImage         string
68
        ImagePullPolicy        string
69
        ConversionContainer    string
70
        VmwareContainer        string
71
        VirtIOWinContainer     string
72
        Smbios                 string
73
        Machinetype            string
74
        Amd64MachineType       string
75
        Arm64MachineType       string
76
        HcoKvIoVersion         string
77
        KubevirtVersion        string
78
        KvVirtLancherOsVersion string
79
        CdiVersion             string
80
        CnaoVersion            string
81
        SspVersion             string
82
        HppoVersion            string
83
        MtqVersion             string
84
        AaqVersion             string
85
        Env                    []corev1.EnvVar
86
}
87

88
func GetDeploymentOperator(params *DeploymentOperatorParams) appsv1.Deployment {
×
89
        return appsv1.Deployment{
×
90
                TypeMeta: deploymentType,
×
91
                ObjectMeta: metav1.ObjectMeta{
×
92
                        Name: hcoName,
×
93
                        Labels: map[string]string{
×
94
                                "name": hcoName,
×
95
                        },
×
96
                },
×
97
                Spec: GetDeploymentSpecOperator(params),
×
98
        }
×
99
}
×
100

101
func GetDeploymentWebhook(namespace, image, imagePullPolicy, hcoKvIoVersion string, env []corev1.EnvVar) appsv1.Deployment {
×
102
        deploy := appsv1.Deployment{
×
103
                TypeMeta: deploymentType,
×
104
                ObjectMeta: metav1.ObjectMeta{
×
105
                        Name: hcoNameWebhook,
×
106
                        Labels: map[string]string{
×
107
                                "name": hcoNameWebhook,
×
108
                        },
×
109
                },
×
110
                Spec: GetDeploymentSpecWebhook(namespace, image, imagePullPolicy, hcoKvIoVersion, env),
×
111
        }
×
112

×
113
        InjectVolumesForWebHookCerts(&deploy)
×
114
        return deploy
×
115
}
×
116

117
func GetDeploymentCliDownloads(params *DeploymentOperatorParams) appsv1.Deployment {
×
118
        return appsv1.Deployment{
×
119
                TypeMeta: deploymentType,
×
120
                ObjectMeta: metav1.ObjectMeta{
×
121
                        Name: cliDownloadsName,
×
122
                        Labels: map[string]string{
×
123
                                "name": cliDownloadsName,
×
124
                        },
×
125
                },
×
126
                Spec: GetDeploymentSpecCliDownloads(params),
×
127
        }
×
128
}
×
129

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

156
func GetDeploymentSpecOperator(params *DeploymentOperatorParams) appsv1.DeploymentSpec {
×
157
        envs := buildEnvVars(params)
×
158

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

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

×
294
        if params.KvVirtLancherOsVersion != "" {
×
295
                envs = append(envs, corev1.EnvVar{
×
296
                        Name:  util.KvVirtLauncherOSVersionEnvV,
×
297
                        Value: params.KvVirtLancherOsVersion,
×
298
                })
×
299
        }
×
300

301
        return envs
×
302
}
303

304
func GetDeploymentSpecCliDownloads(params *DeploymentOperatorParams) appsv1.DeploymentSpec {
×
305
        return appsv1.DeploymentSpec{
×
306
                Replicas: ptr.To[int32](1),
×
307
                Selector: &metav1.LabelSelector{
×
308
                        MatchLabels: map[string]string{
×
309
                                "name": cliDownloadsName,
×
310
                        },
×
311
                },
×
312
                Strategy: appsv1.DeploymentStrategy{
×
313
                        Type: appsv1.RollingUpdateDeploymentStrategyType,
×
314
                },
×
315
                Template: corev1.PodTemplateSpec{
×
316
                        ObjectMeta: metav1.ObjectMeta{
×
317
                                Labels: getLabels(cliDownloadsName, params.HcoKvIoVersion),
×
318
                        },
×
319
                        Spec: corev1.PodSpec{
×
320
                                ServiceAccountName:           cliDownloadsName,
×
321
                                AutomountServiceAccountToken: ptr.To(false),
×
322
                                SecurityContext:              GetStdPodSecurityContext(),
×
323
                                Containers: []corev1.Container{
×
324
                                        {
×
325
                                                Name:            "server",
×
326
                                                Image:           params.CliDownloadsImage,
×
327
                                                ImagePullPolicy: corev1.PullPolicy(params.ImagePullPolicy),
×
328
                                                Resources: corev1.ResourceRequirements{
×
329
                                                        Requests: map[corev1.ResourceName]resource.Quantity{
×
330
                                                                corev1.ResourceCPU:    resource.MustParse("10m"),
×
331
                                                                corev1.ResourceMemory: resource.MustParse("96Mi"),
×
332
                                                        },
×
333
                                                },
×
334
                                                Ports: []corev1.ContainerPort{
×
335
                                                        {
×
336
                                                                Protocol:      corev1.ProtocolTCP,
×
337
                                                                ContainerPort: int32(8080),
×
338
                                                        },
×
339
                                                },
×
NEW
340
                                                SecurityContext:          GetStdContainerSecurityContext(),
×
NEW
341
                                                ReadinessProbe:           getReadinessProbe("/health", 8080),
×
NEW
342
                                                LivenessProbe:            getLivenessProbe("/health", 8080),
×
NEW
343
                                                TerminationMessagePolicy: corev1.TerminationMessageFallbackToLogsOnError,
×
344
                                        },
×
345
                                },
×
346
                                PriorityClassName: "system-cluster-critical",
×
347
                        },
×
348
                },
×
349
        }
×
350
}
×
351

352
func getLabels(name, hcoKvIoVersion string) map[string]string {
×
353
        return map[string]string{
×
354
                "name":                 name,
×
355
                util.AppLabelVersion:   hcoKvIoVersion,
×
356
                util.AppLabelPartOf:    util.HyperConvergedCluster,
×
357
                util.AppLabelComponent: string(util.AppComponentDeployment),
×
358
        }
×
359
}
×
360

361
func GetStdPodSecurityContext() *corev1.PodSecurityContext {
2✔
362
        return &corev1.PodSecurityContext{
2✔
363
                RunAsNonRoot: ptr.To(true),
2✔
364
                SeccompProfile: &corev1.SeccompProfile{
2✔
365
                        Type: corev1.SeccompProfileTypeRuntimeDefault,
2✔
366
                },
2✔
367
        }
2✔
368
}
2✔
369

370
func GetStdContainerSecurityContext() *corev1.SecurityContext {
2✔
371
        return &corev1.SecurityContext{
2✔
372
                AllowPrivilegeEscalation: ptr.To(false),
2✔
373
                Capabilities: &corev1.Capabilities{
2✔
374
                        Drop: []corev1.Capability{"ALL"},
2✔
375
                },
2✔
376
        }
2✔
377
}
2✔
378

379
// Currently we are abusing the pod readiness to signal to OLM that HCO is not ready
380
// for an upgrade. This has a lot of side effects, one of this is the validating webhook
381
// being not able to receive traffic when exposed by a pod that is not reporting ready=true.
382
// This can cause a lot of side effects if not deadlocks when the system reach a status where,
383
// for any possible reason, HCO pod cannot be ready and so HCO pod cannot validate any further update or
384
// delete request on HCO CR.
385
// A proper solution is properly use the readiness probe only to report the pod readiness and communicate
386
// status to OLM via conditions once OLM will be ready for:
387
// https://github.com/operator-framework/enhancements/blob/master/enhancements/operator-conditions.md
388
// in the meanwhile a quick (but dirty!) solution is to expose the same hco binary on two distinct pods:
389
// the first one will run only the controller and the second one (almost always ready) just the validating
390
// webhook one.
391
func GetDeploymentSpecWebhook(namespace, image, imagePullPolicy, hcoKvIoVersion string, env []corev1.EnvVar) appsv1.DeploymentSpec {
×
392
        return appsv1.DeploymentSpec{
×
393
                Replicas: ptr.To[int32](1),
×
394
                Selector: &metav1.LabelSelector{
×
395
                        MatchLabels: map[string]string{
×
396
                                "name": hcoNameWebhook,
×
397
                        },
×
398
                },
×
399
                Strategy: appsv1.DeploymentStrategy{
×
400
                        Type: appsv1.RollingUpdateDeploymentStrategyType,
×
401
                },
×
402
                Template: corev1.PodTemplateSpec{
×
403
                        ObjectMeta: metav1.ObjectMeta{
×
404
                                Labels: getLabels(hcoNameWebhook, hcoKvIoVersion),
×
405
                        },
×
406
                        Spec: corev1.PodSpec{
×
407
                                ServiceAccountName: hcoName,
×
408
                                SecurityContext:    GetStdPodSecurityContext(),
×
409
                                Containers: []corev1.Container{
×
410
                                        {
×
411
                                                Name:            hcoNameWebhook,
×
412
                                                Image:           image,
×
413
                                                ImagePullPolicy: corev1.PullPolicy(imagePullPolicy),
×
414
                                                Command:         stringListToSlice(hcoNameWebhook),
×
415
                                                ReadinessProbe:  getReadinessProbe(util.ReadinessEndpointName, util.HealthProbePort),
×
416
                                                LivenessProbe:   getLivenessProbe(util.LivenessEndpointName, util.HealthProbePort),
×
417
                                                Env: append([]corev1.EnvVar{
×
418
                                                        {
×
419
                                                                // deprecated: left here for CI test.
×
420
                                                                Name:  util.OperatorWebhookModeEnv,
×
421
                                                                Value: "true",
×
422
                                                        },
×
423
                                                        {
×
424
                                                                Name:  util.ContainerAppName,
×
425
                                                                Value: util.ContainerWebhookApp,
×
426
                                                        },
×
427
                                                        {
×
428
                                                                Name:  "OPERATOR_IMAGE",
×
429
                                                                Value: image,
×
430
                                                        },
×
431
                                                        {
×
432
                                                                Name:  "OPERATOR_NAME",
×
433
                                                                Value: hcoNameWebhook,
×
434
                                                        },
×
435
                                                        {
×
436
                                                                Name:  "OPERATOR_NAMESPACE",
×
437
                                                                Value: namespace,
×
438
                                                        },
×
439
                                                        {
×
440
                                                                Name: "POD_NAME",
×
441
                                                                ValueFrom: &corev1.EnvVarSource{
×
442
                                                                        FieldRef: &corev1.ObjectFieldSelector{
×
443
                                                                                FieldPath: "metadata.name",
×
444
                                                                        },
×
445
                                                                },
×
446
                                                        },
×
447
                                                }, env...),
×
448
                                                Resources: corev1.ResourceRequirements{
×
449
                                                        Requests: map[corev1.ResourceName]resource.Quantity{
×
450
                                                                corev1.ResourceCPU:    resource.MustParse("5m"),
×
451
                                                                corev1.ResourceMemory: resource.MustParse("48Mi"),
×
452
                                                        },
×
453
                                                },
×
NEW
454
                                                SecurityContext:          GetStdContainerSecurityContext(),
×
NEW
455
                                                TerminationMessagePolicy: corev1.TerminationMessageFallbackToLogsOnError,
×
456
                                        },
×
457
                                },
×
458
                                PriorityClassName: "system-node-critical",
×
459
                        },
×
460
                },
×
461
        }
×
462
}
×
463

464
func GetClusterRole() rbacv1.ClusterRole {
×
465
        return rbacv1.ClusterRole{
×
466
                TypeMeta: metav1.TypeMeta{
×
467
                        APIVersion: rbacVersionV1,
×
468
                        Kind:       "ClusterRole",
×
469
                },
×
470
                ObjectMeta: metav1.ObjectMeta{
×
471
                        Name: hcoName,
×
472
                        Labels: map[string]string{
×
473
                                "name": hcoName,
×
474
                        },
×
475
                },
×
476
                Rules: GetClusterPermissions(),
×
477
        }
×
478
}
×
479

480
var (
481
        emptyAPIGroup = []string{""}
482
)
483

484
func GetClusterPermissions() []rbacv1.PolicyRule {
×
485
        const configOpenshiftIO = "config.openshift.io"
×
486
        const operatorOpenshiftIO = "operator.openshift.io"
×
487
        return []rbacv1.PolicyRule{
×
488
                {
×
489
                        APIGroups: stringListToSlice(util.APIVersionGroup),
×
490
                        Resources: stringListToSlice("hyperconvergeds"),
×
491
                        Verbs:     stringListToSlice("get", "list", "update", "watch"),
×
492
                },
×
493
                {
×
494
                        APIGroups: stringListToSlice(util.APIVersionGroup),
×
495
                        Resources: stringListToSlice("hyperconvergeds/finalizers", "hyperconvergeds/status"),
×
496
                        Verbs:     stringListToSlice("get", "list", "create", "update", "watch"),
×
497
                },
×
498
                roleWithAllPermissions(kvapi.GroupName, stringListToSlice("kubevirts", "kubevirts/finalizers")),
×
499
                roleWithAllPermissions(cdiapi.GroupName, stringListToSlice("cdis", "cdis/finalizers")),
×
500
                roleWithAllPermissions(sspapi.GroupVersion.Group, stringListToSlice("ssps", "ssps/finalizers")),
×
501
                roleWithAllPermissions(cnaoapi.GroupVersion.Group, stringListToSlice("networkaddonsconfigs", "networkaddonsconfigs/finalizers")),
×
502
                roleWithAllPermissions(aaqapi.GroupName, stringListToSlice("aaqs", "aaqs/finalizers")),
×
503
                roleWithAllPermissions("", stringListToSlice("configmaps")),
×
504
                {
×
505
                        APIGroups: emptyAPIGroup,
×
506
                        Resources: stringListToSlice("events"),
×
507
                        Verbs:     stringListToSlice("get", "list", "watch", "create", "patch"),
×
508
                },
×
509
                roleWithAllPermissions("", stringListToSlice("services")),
×
510
                {
×
511
                        APIGroups: emptyAPIGroup,
×
512
                        Resources: stringListToSlice("pods", "nodes"),
×
513
                        Verbs:     stringListToSlice("get", "list", "watch"),
×
514
                },
×
515
                {
×
516
                        APIGroups: emptyAPIGroup,
×
517
                        Resources: stringListToSlice("secrets"),
×
518
                        Verbs:     stringListToSlice("get", "list", "watch", "create", "update"),
×
519
                },
×
520
                {
×
521
                        APIGroups: emptyAPIGroup,
×
522
                        Resources: stringListToSlice("endpoints"),
×
523
                        Verbs:     stringListToSlice("get", "list", "delete", "watch"),
×
524
                },
×
525
                {
×
526
                        APIGroups: emptyAPIGroup,
×
527
                        Resources: stringListToSlice("namespaces"),
×
528
                        Verbs:     stringListToSlice("get", "list", "watch", "patch", "update"),
×
529
                },
×
530
                {
×
531
                        APIGroups: stringListToSlice("apps"),
×
532
                        Resources: stringListToSlice("deployments", "replicasets"),
×
533
                        Verbs:     stringListToSlice("get", "list", "watch", "create", "update", "delete"),
×
534
                },
×
535
                roleWithAllPermissions("rbac.authorization.k8s.io", stringListToSlice("roles", "rolebindings")),
×
536
                {
×
537
                        APIGroups: stringListToSlice("apiextensions.k8s.io"),
×
538
                        Resources: stringListToSlice("customresourcedefinitions"),
×
539
                        Verbs:     stringListToSlice("get", "list", "watch", "delete"),
×
540
                },
×
541
                {
×
542
                        APIGroups: stringListToSlice("apiextensions.k8s.io"),
×
543
                        Resources: stringListToSlice("customresourcedefinitions/status"),
×
544
                        Verbs:     stringListToSlice("get", "list", "watch", "patch", "update"),
×
545
                },
×
546
                roleWithAllPermissions("monitoring.coreos.com", stringListToSlice("servicemonitors", "prometheusrules")),
×
547
                {
×
548
                        APIGroups: stringListToSlice("operators.coreos.com"),
×
549
                        Resources: stringListToSlice("clusterserviceversions"),
×
550
                        Verbs:     stringListToSlice("get", "list", "watch", "update", "patch"),
×
551
                },
×
552
                {
×
553
                        APIGroups: stringListToSlice("scheduling.k8s.io"),
×
554
                        Resources: stringListToSlice("priorityclasses"),
×
555
                        Verbs:     stringListToSlice("get", "list", "watch", "create", "delete", "patch"),
×
556
                },
×
557
                {
×
558
                        APIGroups: stringListToSlice("admissionregistration.k8s.io"),
×
559
                        Resources: stringListToSlice("validatingwebhookconfigurations"),
×
560
                        Verbs:     stringListToSlice("list", "watch", "update", "patch"),
×
561
                },
×
562
                roleWithAllPermissions("console.openshift.io", stringListToSlice("consoleclidownloads", "consolequickstarts")),
×
563
                {
×
564
                        APIGroups: stringListToSlice(configOpenshiftIO),
×
565
                        Resources: stringListToSlice("clusterversions", "infrastructures", "networks"),
×
566
                        Verbs:     stringListToSlice("get", "list"),
×
567
                },
×
568
                {
×
569
                        APIGroups: stringListToSlice(configOpenshiftIO),
×
570
                        Resources: stringListToSlice("ingresses"),
×
571
                        Verbs:     stringListToSlice("get", "list", "watch"),
×
572
                },
×
573
                {
×
574
                        APIGroups: stringListToSlice(configOpenshiftIO),
×
575
                        Resources: stringListToSlice("ingresses/status"),
×
576
                        Verbs:     stringListToSlice("update"),
×
577
                },
×
578
                {
×
579
                        APIGroups: stringListToSlice(configOpenshiftIO),
×
580
                        Resources: stringListToSlice("apiservers"),
×
581
                        Verbs:     stringListToSlice("get", "list", "watch"),
×
582
                },
×
583
                {
×
584
                        APIGroups: stringListToSlice(operatorOpenshiftIO),
×
585
                        Resources: stringListToSlice("kubedeschedulers"),
×
586
                        Verbs:     stringListToSlice("get", "list", "watch"),
×
587
                },
×
588
                {
×
589
                        APIGroups: stringListToSlice(configOpenshiftIO),
×
590
                        Resources: stringListToSlice("dnses"),
×
591
                        Verbs:     stringListToSlice("get"),
×
592
                },
×
593
                roleWithAllPermissions("coordination.k8s.io", stringListToSlice("leases")),
×
594
                roleWithAllPermissions("route.openshift.io", stringListToSlice("routes")),
×
595
                {
×
596
                        APIGroups: stringListToSlice("route.openshift.io"),
×
597
                        Resources: stringListToSlice("routes/custom-host"),
×
598
                        Verbs:     stringListToSlice("create", "update", "patch"),
×
599
                },
×
600
                {
×
601
                        APIGroups: stringListToSlice("operators.coreos.com"),
×
602
                        Resources: stringListToSlice("operatorconditions"),
×
603
                        Verbs:     stringListToSlice("get", "list", "watch", "update", "patch"),
×
604
                },
×
605
                roleWithAllPermissions("image.openshift.io", stringListToSlice("imagestreams")),
×
606
                roleWithAllPermissions("console.openshift.io", stringListToSlice("consoleplugins")),
×
607
                {
×
608
                        APIGroups: stringListToSlice("operator.openshift.io"),
×
609
                        Resources: stringListToSlice("consoles"),
×
610
                        Verbs:     stringListToSlice("get", "list", "watch", "update"),
×
611
                },
×
612
                {
×
613
                        APIGroups: stringListToSlice("monitoring.coreos.com"),
×
614
                        Resources: stringListToSlice("alertmanagers", "alertmanagers/api"),
×
615
                        Verbs:     stringListToSlice("get", "list", "create", "delete"),
×
616
                },
×
617
        }
×
618
}
×
619

620
func roleWithAllPermissions(apiGroup string, resources []string) rbacv1.PolicyRule {
×
621
        return rbacv1.PolicyRule{
×
622
                APIGroups: stringListToSlice(apiGroup),
×
623
                Resources: resources,
×
624
                Verbs:     stringListToSlice("get", "list", "watch", "create", "update", "delete", "patch"),
×
625
        }
×
626
}
×
627

628
func GetServiceAccount(namespace string) corev1.ServiceAccount {
×
629
        return createServiceAccount(namespace, hcoName)
×
630
}
×
631

632
func GetCLIDownloadServiceAccount(namespace string) corev1.ServiceAccount {
×
633
        return createServiceAccount(namespace, cliDownloadsName)
×
634
}
×
635

636
func createServiceAccount(namespace, name string) corev1.ServiceAccount {
×
637
        return corev1.ServiceAccount{
×
638
                TypeMeta: metav1.TypeMeta{
×
639
                        APIVersion: "v1",
×
640
                        Kind:       "ServiceAccount",
×
641
                },
×
642
                ObjectMeta: metav1.ObjectMeta{
×
643
                        Name:      name,
×
644
                        Namespace: namespace,
×
645
                        Labels: map[string]string{
×
646
                                "name": name,
×
647
                        },
×
648
                },
×
649
        }
×
650
}
×
651

652
func GetClusterRoleBinding(namespace string) rbacv1.ClusterRoleBinding {
×
653
        return rbacv1.ClusterRoleBinding{
×
654
                TypeMeta: metav1.TypeMeta{
×
655
                        APIVersion: rbacVersionV1,
×
656
                        Kind:       "ClusterRoleBinding",
×
657
                },
×
658
                ObjectMeta: metav1.ObjectMeta{
×
659
                        Name: hcoName,
×
660
                        Labels: map[string]string{
×
661
                                "name": hcoName,
×
662
                        },
×
663
                },
×
664
                RoleRef: rbacv1.RoleRef{
×
665
                        APIGroup: "rbac.authorization.k8s.io",
×
666
                        Kind:     "ClusterRole",
×
667
                        Name:     hcoName,
×
668
                },
×
669
                Subjects: []rbacv1.Subject{
×
670
                        {
×
671
                                Kind:      "ServiceAccount",
×
672
                                Name:      hcoName,
×
673
                                Namespace: namespace,
×
674
                        },
×
675
                },
×
676
        }
×
677
}
×
678

679
func packageErrors(pkg *loader.Package, filterKinds ...packages.ErrorKind) error {
×
680
        toSkip := make(map[packages.ErrorKind]struct{})
×
681
        for _, errKind := range filterKinds {
×
682
                toSkip[errKind] = struct{}{}
×
683
        }
×
684
        var outErr error
×
685
        packages.Visit([]*packages.Package{pkg.Package}, nil, func(pkgRaw *packages.Package) {
×
686
                for _, err := range pkgRaw.Errors {
×
687
                        if _, skip := toSkip[err.Kind]; skip {
×
688
                                continue
×
689
                        }
690
                        outErr = err
×
691
                }
692
        })
693
        return outErr
×
694
}
695

696
const objectType = "object"
697

698
func GetOperatorCRD(relPath string) *extv1.CustomResourceDefinition {
×
699
        pkgs, err := loader.LoadRoots(relPath)
×
700
        if err != nil {
×
701
                panic(err)
×
702
        }
703
        reg := &markers.Registry{}
×
704
        panicOnError(crdmarkers.Register(reg))
×
705

×
706
        parser := &crdgen.Parser{
×
707
                Collector:                  &markers.Collector{Registry: reg},
×
708
                Checker:                    &loader.TypeChecker{},
×
709
                GenerateEmbeddedObjectMeta: true,
×
710
        }
×
711

×
712
        crdgen.AddKnownTypes(parser)
×
713
        if len(pkgs) == 0 {
×
714
                panic("Failed identifying packages")
×
715
        }
716
        for _, p := range pkgs {
×
717
                parser.NeedPackage(p)
×
718
        }
×
719
        groupKind := schema.GroupKind{Kind: util.HyperConvergedKind, Group: util.APIVersionGroup}
×
720
        parser.NeedCRDFor(groupKind, nil)
×
721
        for _, p := range pkgs {
×
722
                err = packageErrors(p, packages.TypeError)
×
723
                if err != nil {
×
724
                        panic(err)
×
725
                }
726
        }
727
        c := parser.CustomResourceDefinitions[groupKind]
×
728
        // enforce validation of CR name to prevent multiple CRs
×
729
        for _, v := range c.Spec.Versions {
×
730
                v.Schema.OpenAPIV3Schema.Properties["metadata"] = extv1.JSONSchemaProps{
×
731
                        Type: objectType,
×
732
                        Properties: map[string]extv1.JSONSchemaProps{
×
733
                                "name": {
×
734
                                        Type:    "string",
×
735
                                        Pattern: hcov1beta1.HyperConvergedName,
×
736
                                },
×
737
                        },
×
738
                }
×
739
        }
×
740
        return &c
×
741
}
742

743
func GetOperatorCR() *hcov1beta1.HyperConverged {
8✔
744
        defaultScheme := runtime.NewScheme()
8✔
745
        _ = hcov1beta1.AddToScheme(defaultScheme)
8✔
746
        _ = hcov1beta1.RegisterDefaults(defaultScheme)
8✔
747
        defaultHco := &hcov1beta1.HyperConverged{
8✔
748
                TypeMeta: metav1.TypeMeta{
8✔
749
                        APIVersion: util.APIVersion,
8✔
750
                        Kind:       util.HyperConvergedKind,
8✔
751
                },
8✔
752
                ObjectMeta: metav1.ObjectMeta{
8✔
753
                        Name: crName,
8✔
754
                }}
8✔
755
        defaultScheme.Default(defaultHco)
8✔
756
        return defaultHco
8✔
757
}
8✔
758

759
// GetInstallStrategyBase returns the basics of an HCO InstallStrategy
760
func GetInstallStrategyBase(params *DeploymentOperatorParams) *csvv1alpha1.StrategyDetailsDeployment {
×
761
        return &csvv1alpha1.StrategyDetailsDeployment{
×
762

×
763
                DeploymentSpecs: []csvv1alpha1.StrategyDeploymentSpec{
×
764
                        {
×
765
                                Name:  hcoDeploymentName,
×
766
                                Spec:  GetDeploymentSpecOperator(params),
×
767
                                Label: getLabels(hcoName, params.HcoKvIoVersion),
×
768
                        },
×
769
                        {
×
770
                                Name:  hcoWhDeploymentName,
×
771
                                Spec:  GetDeploymentSpecWebhook(params.Namespace, params.WebhookImage, params.ImagePullPolicy, params.HcoKvIoVersion, params.Env),
×
772
                                Label: getLabels(hcoNameWebhook, params.HcoKvIoVersion),
×
773
                        },
×
774
                        {
×
775
                                Name:  cliDownloadsName,
×
776
                                Spec:  GetDeploymentSpecCliDownloads(params),
×
777
                                Label: getLabels(cliDownloadsName, params.HcoKvIoVersion),
×
778
                        },
×
779
                },
×
780
                Permissions: []csvv1alpha1.StrategyDeploymentPermissions{},
×
781
                ClusterPermissions: []csvv1alpha1.StrategyDeploymentPermissions{
×
782
                        {
×
783
                                ServiceAccountName: hcoName,
×
784
                                Rules:              GetClusterPermissions(),
×
785
                        },
×
786
                        {
×
787
                                ServiceAccountName: cliDownloadsName,
×
788
                                Rules:              []rbacv1.PolicyRule{},
×
789
                        },
×
790
                },
×
791
        }
×
792
}
×
793

794
type CSVBaseParams struct {
795
        Name            string
796
        Namespace       string
797
        DisplayName     string
798
        MetaDescription string
799
        Description     string
800
        Image           string
801
        Replaces        string
802
        Version         semver.Version
803
        CrdDisplay      string
804
}
805

806
// GetCSVBase returns a base HCO CSV without an InstallStrategy
807
func GetCSVBase(params *CSVBaseParams) *csvv1alpha1.ClusterServiceVersion {
×
808
        almExamples, _ := json.Marshal(
×
809
                map[string]interface{}{
×
810
                        "apiVersion": util.APIVersion,
×
811
                        "kind":       util.HyperConvergedKind,
×
812
                        "metadata": map[string]interface{}{
×
813
                                "name":      packageName,
×
814
                                "namespace": params.Namespace,
×
815
                                "annotations": map[string]string{
×
816
                                        "deployOVS": "false",
×
817
                                },
×
818
                        },
×
819
                        "spec": map[string]interface{}{},
×
820
                })
×
821

×
822
        // Explicitly fail on unvalidated (for any reason) requests:
×
823
        // this can make removing HCO CR harder if HCO webhook is not able
×
824
        // to really validate the requests.
×
825
        // In that case the user can only directly remove the
×
826
        // ValidatingWebhookConfiguration object first (eventually bypassing the OLM if needed).
×
827
        // so failurePolicy = admissionregistrationv1.Fail
×
828

×
829
        validatingWebhook := csvv1alpha1.WebhookDescription{
×
830
                GenerateName:            util.HcoValidatingWebhook,
×
831
                Type:                    csvv1alpha1.ValidatingAdmissionWebhook,
×
832
                DeploymentName:          hcoWhDeploymentName,
×
833
                ContainerPort:           util.WebhookPort,
×
834
                AdmissionReviewVersions: stringListToSlice("v1beta1", "v1"),
×
835
                SideEffects:             ptr.To(admissionregistrationv1.SideEffectClassNone),
×
836
                FailurePolicy:           ptr.To(admissionregistrationv1.Fail),
×
837
                TimeoutSeconds:          ptr.To[int32](10),
×
838
                Rules: []admissionregistrationv1.RuleWithOperations{
×
839
                        {
×
840
                                Operations: []admissionregistrationv1.OperationType{
×
841
                                        admissionregistrationv1.Create,
×
842
                                        admissionregistrationv1.Delete,
×
843
                                        admissionregistrationv1.Update,
×
844
                                },
×
845
                                Rule: admissionregistrationv1.Rule{
×
846
                                        APIGroups:   stringListToSlice(util.APIVersionGroup),
×
847
                                        APIVersions: stringListToSlice(util.APIVersionAlpha, util.APIVersionBeta),
×
848
                                        Resources:   stringListToSlice("hyperconvergeds"),
×
849
                                },
×
850
                        },
×
851
                },
×
852
                WebhookPath: ptr.To(util.HCOWebhookPath),
×
853
        }
×
854

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

×
882
        mutatingHyperConvergedWebhook := csvv1alpha1.WebhookDescription{
×
883
                GenerateName:            util.HcoMutatingWebhookHyperConverged,
×
884
                Type:                    csvv1alpha1.MutatingAdmissionWebhook,
×
885
                DeploymentName:          hcoWhDeploymentName,
×
886
                ContainerPort:           util.WebhookPort,
×
887
                AdmissionReviewVersions: stringListToSlice("v1beta1", "v1"),
×
888
                SideEffects:             ptr.To(admissionregistrationv1.SideEffectClassNoneOnDryRun),
×
889
                FailurePolicy:           ptr.To(admissionregistrationv1.Fail),
×
890
                TimeoutSeconds:          ptr.To[int32](10),
×
891
                Rules: []admissionregistrationv1.RuleWithOperations{
×
892
                        {
×
893
                                Operations: []admissionregistrationv1.OperationType{
×
894
                                        admissionregistrationv1.Create,
×
895
                                        admissionregistrationv1.Update,
×
896
                                },
×
897
                                Rule: admissionregistrationv1.Rule{
×
898
                                        APIGroups:   stringListToSlice(util.APIVersionGroup),
×
899
                                        APIVersions: stringListToSlice(util.APIVersionAlpha, util.APIVersionBeta),
×
900
                                        Resources:   stringListToSlice("hyperconvergeds"),
×
901
                                },
×
902
                        },
×
903
                },
×
904
                WebhookPath: ptr.To(util.HCOMutatingWebhookPath),
×
905
        }
×
906

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

1089
func InjectVolumesForWebHookCerts(deploy *appsv1.Deployment) {
×
1090
        // check if there is already a volume for api certificates
×
1091
        for _, vol := range deploy.Spec.Template.Spec.Volumes {
×
1092
                if vol.Name == certVolume {
×
1093
                        return
×
1094
                }
×
1095
        }
1096

1097
        volume := corev1.Volume{
×
1098
                Name: certVolume,
×
1099
                VolumeSource: corev1.VolumeSource{
×
1100
                        Secret: &corev1.SecretVolumeSource{
×
1101
                                SecretName:  deploy.Name + "-service-cert",
×
1102
                                DefaultMode: ptr.To[int32](420),
×
1103
                                Items: []corev1.KeyToPath{
×
1104
                                        {
×
1105
                                                Key:  "tls.crt",
×
1106
                                                Path: util.WebhookCertName,
×
1107
                                        },
×
1108
                                        {
×
1109
                                                Key:  "tls.key",
×
1110
                                                Path: util.WebhookKeyName,
×
1111
                                        },
×
1112
                                },
×
1113
                        },
×
1114
                },
×
1115
        }
×
1116
        deploy.Spec.Template.Spec.Volumes = append(deploy.Spec.Template.Spec.Volumes, volume)
×
1117

×
1118
        for index, container := range deploy.Spec.Template.Spec.Containers {
×
1119
                deploy.Spec.Template.Spec.Containers[index].VolumeMounts = append(container.VolumeMounts,
×
1120
                        corev1.VolumeMount{
×
1121
                                Name:      certVolume,
×
1122
                                MountPath: util.DefaultWebhookCertDir,
×
1123
                        })
×
1124
        }
×
1125
}
1126

1127
func getReadinessProbe(endpoint string, port int32) *corev1.Probe {
×
1128
        return &corev1.Probe{
×
1129
                ProbeHandler: corev1.ProbeHandler{
×
1130
                        HTTPGet: &corev1.HTTPGetAction{
×
1131
                                Path: endpoint,
×
1132
                                Port: intstr.IntOrString{
×
1133
                                        Type:   intstr.Int,
×
1134
                                        IntVal: port,
×
1135
                                },
×
1136
                                Scheme: corev1.URISchemeHTTP,
×
1137
                        },
×
1138
                },
×
1139
                InitialDelaySeconds: 5,
×
1140
                PeriodSeconds:       5,
×
1141
                FailureThreshold:    1,
×
1142
        }
×
1143
}
×
1144

1145
func getLivenessProbe(endpoint string, port int32) *corev1.Probe {
×
1146
        return &corev1.Probe{
×
1147
                ProbeHandler: corev1.ProbeHandler{
×
1148
                        HTTPGet: &corev1.HTTPGetAction{
×
1149
                                Path: endpoint,
×
1150
                                Port: intstr.IntOrString{
×
1151
                                        Type:   intstr.Int,
×
1152
                                        IntVal: port,
×
1153
                                },
×
1154
                                Scheme: corev1.URISchemeHTTP,
×
1155
                        },
×
1156
                },
×
1157
                InitialDelaySeconds: 30,
×
1158
                PeriodSeconds:       5,
×
1159
                FailureThreshold:    1,
×
1160
        }
×
1161
}
×
1162

1163
func stringListToSlice(words ...string) []string {
×
1164
        return words
×
1165
}
×
1166

1167
func panicOnError(err error) {
×
1168
        if err != nil {
×
1169
                panic(err)
×
1170
        }
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