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

kubevirt / hyperconverged-cluster-operator / 20689766013

04 Jan 2026 07:51AM UTC coverage: 72.789% (-0.03%) from 72.821%
20689766013

push

github

web-flow
[release-1.15] Fix issue with validating admission policy (#3949)

In clusters where the OwnerReferencesPermissionEnforcement policy is
applied, HCO fails to reconcile the owner reference of the
validitingAdmissionPolicy and the validitingAdmissionPolicyBinding.

This PR adds the finilizers rbac permissions for crd/finilizers, so now
HCO is allowd to set the owner reference properly.

Signed-off-by: Nahshon Unna Tsameret <nahsh.ut@gmail.com>

0 of 1 new or added line in 1 file covered. (0.0%)

3 existing lines in 1 file now uncovered.

6947 of 9544 relevant lines covered (72.79%)

0.97 hits per line

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

2.99
/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
        hcoDeploymentName   = "hco-operator"
45
        hcoWhDeploymentName = "hco-webhook"
46
        certVolume          = "apiservice-cert"
47

48
        kubevirtProjectName = "KubeVirt project"
49
        rbacVersionV1       = "rbac.authorization.k8s.io/v1"
50
)
51

52
var deploymentType = metav1.TypeMeta{
53
        APIVersion: "apps/v1",
54
        Kind:       "Deployment",
55
}
56

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

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

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

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

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

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

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

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

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

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

303
        return envs
×
304
}
305

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

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

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

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

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

474
func GetClusterRole() rbacv1.ClusterRole {
×
475
        return rbacv1.ClusterRole{
×
476
                TypeMeta: metav1.TypeMeta{
×
477
                        APIVersion: rbacVersionV1,
×
478
                        Kind:       "ClusterRole",
×
479
                },
×
480
                ObjectMeta: metav1.ObjectMeta{
×
481
                        Name: util.HCOOperatorName,
×
482
                        Labels: map[string]string{
×
483
                                "name": util.HCOOperatorName,
×
484
                        },
×
485
                },
×
486
                Rules: GetClusterPermissions(),
×
487
        }
×
488
}
×
489

490
var (
491
        emptyAPIGroup = []string{""}
492
)
493

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

635
func roleWithAllPermissions(apiGroup string, resources []string) rbacv1.PolicyRule {
×
636
        return rbacv1.PolicyRule{
×
637
                APIGroups: stringListToSlice(apiGroup),
×
638
                Resources: resources,
×
639
                Verbs:     stringListToSlice("get", "list", "watch", "create", "update", "delete", "patch"),
×
640
        }
×
641
}
×
642

643
func GetServiceAccount(namespace string) corev1.ServiceAccount {
×
644
        return createServiceAccount(namespace, util.HCOOperatorName)
×
645
}
×
646

647
func GetCLIDownloadServiceAccount(namespace string) corev1.ServiceAccount {
×
648
        return createServiceAccount(namespace, util.CLIDownloadsName)
×
649
}
×
650

651
func createServiceAccount(namespace, name string) corev1.ServiceAccount {
×
652
        return corev1.ServiceAccount{
×
653
                TypeMeta: metav1.TypeMeta{
×
654
                        APIVersion: "v1",
×
655
                        Kind:       "ServiceAccount",
×
656
                },
×
657
                ObjectMeta: metav1.ObjectMeta{
×
658
                        Name:      name,
×
659
                        Namespace: namespace,
×
660
                        Labels: map[string]string{
×
661
                                "name": name,
×
662
                        },
×
663
                },
×
664
        }
×
665
}
×
666

667
func GetClusterRoleBinding(namespace string) rbacv1.ClusterRoleBinding {
×
668
        return rbacv1.ClusterRoleBinding{
×
669
                TypeMeta: metav1.TypeMeta{
×
670
                        APIVersion: rbacVersionV1,
×
671
                        Kind:       "ClusterRoleBinding",
×
672
                },
×
673
                ObjectMeta: metav1.ObjectMeta{
×
674
                        Name: util.HCOOperatorName,
×
675
                        Labels: map[string]string{
×
676
                                "name": util.HCOOperatorName,
×
677
                        },
×
678
                },
×
679
                RoleRef: rbacv1.RoleRef{
×
680
                        APIGroup: "rbac.authorization.k8s.io",
×
681
                        Kind:     "ClusterRole",
×
682
                        Name:     util.HCOOperatorName,
×
683
                },
×
684
                Subjects: []rbacv1.Subject{
×
685
                        {
×
686
                                Kind:      "ServiceAccount",
×
687
                                Name:      util.HCOOperatorName,
×
688
                                Namespace: namespace,
×
689
                        },
×
690
                },
×
691
        }
×
692
}
×
693

694
func packageErrors(pkg *loader.Package, filterKinds ...packages.ErrorKind) error {
×
695
        toSkip := make(map[packages.ErrorKind]struct{})
×
696
        for _, errKind := range filterKinds {
×
697
                toSkip[errKind] = struct{}{}
×
698
        }
×
699
        var outErr error
×
700
        packages.Visit([]*packages.Package{pkg.Package}, nil, func(pkgRaw *packages.Package) {
×
701
                for _, err := range pkgRaw.Errors {
×
702
                        if _, skip := toSkip[err.Kind]; skip {
×
703
                                continue
×
704
                        }
705
                        outErr = err
×
706
                }
707
        })
708
        return outErr
×
709
}
710

711
const objectType = "object"
712

713
func GetOperatorCRD(relPath string) *extv1.CustomResourceDefinition {
×
714
        pkgs, err := loader.LoadRoots(relPath)
×
715
        if err != nil {
×
716
                panic(err)
×
717
        }
718
        reg := &markers.Registry{}
×
719
        panicOnError(crdmarkers.Register(reg))
×
720

×
721
        parser := &crdgen.Parser{
×
722
                Collector:                  &markers.Collector{Registry: reg},
×
723
                Checker:                    &loader.TypeChecker{},
×
724
                GenerateEmbeddedObjectMeta: true,
×
725
        }
×
726

×
727
        crdgen.AddKnownTypes(parser)
×
728
        if len(pkgs) == 0 {
×
729
                panic("Failed identifying packages")
×
730
        }
731
        for _, p := range pkgs {
×
732
                parser.NeedPackage(p)
×
733
        }
×
734
        groupKind := schema.GroupKind{Kind: util.HyperConvergedKind, Group: util.APIVersionGroup}
×
735
        parser.NeedCRDFor(groupKind, nil)
×
736
        for _, p := range pkgs {
×
737
                err = packageErrors(p, packages.TypeError)
×
738
                if err != nil {
×
739
                        panic(err)
×
740
                }
741
        }
742
        c := parser.CustomResourceDefinitions[groupKind]
×
743
        // enforce validation of CR name to prevent multiple CRs
×
744
        for _, v := range c.Spec.Versions {
×
745
                v.Schema.OpenAPIV3Schema.Properties["metadata"] = extv1.JSONSchemaProps{
×
746
                        Type: objectType,
×
747
                        Properties: map[string]extv1.JSONSchemaProps{
×
748
                                "name": {
×
749
                                        Type:    "string",
×
750
                                        Pattern: hcov1beta1.HyperConvergedName,
×
751
                                },
×
752
                        },
×
753
                }
×
754
        }
×
755
        return &c
×
756
}
757

758
func GetOperatorCR() *hcov1beta1.HyperConverged {
8✔
759
        defaultScheme := runtime.NewScheme()
8✔
760
        _ = hcov1beta1.AddToScheme(defaultScheme)
8✔
761
        _ = hcov1beta1.RegisterDefaults(defaultScheme)
8✔
762
        defaultHco := &hcov1beta1.HyperConverged{
8✔
763
                TypeMeta: metav1.TypeMeta{
8✔
764
                        APIVersion: util.APIVersion,
8✔
765
                        Kind:       util.HyperConvergedKind,
8✔
766
                },
8✔
767
                ObjectMeta: metav1.ObjectMeta{
8✔
768
                        Name: crName,
8✔
769
                }}
8✔
770
        defaultScheme.Default(defaultHco)
8✔
771
        return defaultHco
8✔
772
}
8✔
773

774
// GetInstallStrategyBase returns the basics of an HCO InstallStrategy
775
func GetInstallStrategyBase(params *DeploymentOperatorParams) *csvv1alpha1.StrategyDetailsDeployment {
×
776
        return &csvv1alpha1.StrategyDetailsDeployment{
×
777

×
778
                DeploymentSpecs: []csvv1alpha1.StrategyDeploymentSpec{
×
779
                        {
×
780
                                Name:  hcoDeploymentName,
×
781
                                Spec:  GetDeploymentSpecOperator(params),
×
782
                                Label: getLabels(util.HCOOperatorName, params.HcoKvIoVersion),
×
783
                        },
×
784
                        {
×
785
                                Name:  hcoWhDeploymentName,
×
786
                                Spec:  GetDeploymentSpecWebhook(params.Namespace, params.WebhookImage, params.ImagePullPolicy, params.HcoKvIoVersion, params.Env),
×
787
                                Label: getLabels(util.HCOWebhookName, params.HcoKvIoVersion),
×
788
                        },
×
789
                        {
×
790
                                Name:  util.CLIDownloadsName,
×
791
                                Spec:  GetDeploymentSpecCliDownloads(params),
×
792
                                Label: getLabels(util.CLIDownloadsName, params.HcoKvIoVersion),
×
793
                        },
×
794
                },
×
795
                Permissions: []csvv1alpha1.StrategyDeploymentPermissions{},
×
796
                ClusterPermissions: []csvv1alpha1.StrategyDeploymentPermissions{
×
797
                        {
×
798
                                ServiceAccountName: util.HCOOperatorName,
×
799
                                Rules:              GetClusterPermissions(),
×
800
                        },
×
801
                        {
×
802
                                ServiceAccountName: util.CLIDownloadsName,
×
803
                                Rules:              []rbacv1.PolicyRule{},
×
804
                        },
×
805
                },
×
806
        }
×
807
}
×
808

809
type CSVBaseParams struct {
810
        Name            string
811
        Namespace       string
812
        DisplayName     string
813
        MetaDescription string
814
        Description     string
815
        Image           string
816
        Version         semver.Version
817
        CrdDisplay      string
818
}
819

820
// GetCSVBase returns a base HCO CSV without an InstallStrategy
821
func GetCSVBase(params *CSVBaseParams) *csvv1alpha1.ClusterServiceVersion {
×
822
        almExamples, _ := json.Marshal(
×
823
                map[string]interface{}{
×
824
                        "apiVersion": util.APIVersion,
×
825
                        "kind":       util.HyperConvergedKind,
×
826
                        "metadata": map[string]interface{}{
×
827
                                "name":      packageName,
×
828
                                "namespace": params.Namespace,
×
829
                                "annotations": map[string]string{
×
830
                                        "deployOVS": "false",
×
831
                                },
×
832
                        },
×
833
                        "spec": map[string]interface{}{},
×
834
                })
×
835

×
836
        // Explicitly fail on unvalidated (for any reason) requests:
×
837
        // this can make removing HCO CR harder if HCO webhook is not able
×
838
        // to really validate the requests.
×
839
        // In that case the user can only directly remove the
×
840
        // ValidatingWebhookConfiguration object first (eventually bypassing the OLM if needed).
×
841
        // so failurePolicy = admissionregistrationv1.Fail
×
842

×
843
        validatingWebhook := csvv1alpha1.WebhookDescription{
×
844
                GenerateName:            util.HcoValidatingWebhook,
×
845
                Type:                    csvv1alpha1.ValidatingAdmissionWebhook,
×
846
                DeploymentName:          hcoWhDeploymentName,
×
847
                ContainerPort:           util.WebhookPort,
×
848
                AdmissionReviewVersions: stringListToSlice("v1beta1", "v1"),
×
849
                SideEffects:             ptr.To(admissionregistrationv1.SideEffectClassNone),
×
850
                FailurePolicy:           ptr.To(admissionregistrationv1.Fail),
×
851
                TimeoutSeconds:          ptr.To[int32](10),
×
852
                Rules: []admissionregistrationv1.RuleWithOperations{
×
853
                        {
×
854
                                Operations: []admissionregistrationv1.OperationType{
×
855
                                        admissionregistrationv1.Create,
×
856
                                        admissionregistrationv1.Delete,
×
857
                                        admissionregistrationv1.Update,
×
858
                                },
×
859
                                Rule: admissionregistrationv1.Rule{
×
860
                                        APIGroups:   stringListToSlice(util.APIVersionGroup),
×
861
                                        APIVersions: stringListToSlice(util.APIVersionAlpha, util.APIVersionBeta),
×
862
                                        Resources:   stringListToSlice("hyperconvergeds"),
×
863
                                },
×
864
                        },
×
865
                },
×
866
                WebhookPath: ptr.To(util.HCOWebhookPath),
×
867
        }
×
868

×
869
        mutatingNamespaceWebhook := csvv1alpha1.WebhookDescription{
×
870
                GenerateName:            util.HcoMutatingWebhookNS,
×
871
                Type:                    csvv1alpha1.MutatingAdmissionWebhook,
×
872
                DeploymentName:          hcoWhDeploymentName,
×
873
                ContainerPort:           util.WebhookPort,
×
874
                AdmissionReviewVersions: stringListToSlice("v1beta1", "v1"),
×
875
                SideEffects:             ptr.To(admissionregistrationv1.SideEffectClassNoneOnDryRun),
×
876
                FailurePolicy:           ptr.To(admissionregistrationv1.Fail),
×
877
                TimeoutSeconds:          ptr.To[int32](10),
×
878
                ObjectSelector: &metav1.LabelSelector{
×
879
                        MatchLabels: map[string]string{util.KubernetesMetadataName: params.Namespace},
×
880
                },
×
881
                Rules: []admissionregistrationv1.RuleWithOperations{
×
882
                        {
×
883
                                Operations: []admissionregistrationv1.OperationType{
×
884
                                        admissionregistrationv1.Delete,
×
885
                                },
×
886
                                Rule: admissionregistrationv1.Rule{
×
887
                                        APIGroups:   []string{""},
×
888
                                        APIVersions: stringListToSlice("v1"),
×
889
                                        Resources:   stringListToSlice("namespaces"),
×
890
                                },
×
891
                        },
×
892
                },
×
893
                WebhookPath: ptr.To(util.HCONSWebhookPath),
×
894
        }
×
895

×
896
        mutatingHyperConvergedWebhook := csvv1alpha1.WebhookDescription{
×
897
                GenerateName:            util.HcoMutatingWebhookHyperConverged,
×
898
                Type:                    csvv1alpha1.MutatingAdmissionWebhook,
×
899
                DeploymentName:          hcoWhDeploymentName,
×
900
                ContainerPort:           util.WebhookPort,
×
901
                AdmissionReviewVersions: stringListToSlice("v1beta1", "v1"),
×
902
                SideEffects:             ptr.To(admissionregistrationv1.SideEffectClassNoneOnDryRun),
×
903
                FailurePolicy:           ptr.To(admissionregistrationv1.Fail),
×
904
                TimeoutSeconds:          ptr.To[int32](10),
×
905
                Rules: []admissionregistrationv1.RuleWithOperations{
×
906
                        {
×
907
                                Operations: []admissionregistrationv1.OperationType{
×
908
                                        admissionregistrationv1.Create,
×
909
                                        admissionregistrationv1.Update,
×
910
                                },
×
911
                                Rule: admissionregistrationv1.Rule{
×
912
                                        APIGroups:   stringListToSlice(util.APIVersionGroup),
×
913
                                        APIVersions: stringListToSlice(util.APIVersionAlpha, util.APIVersionBeta),
×
914
                                        Resources:   stringListToSlice("hyperconvergeds"),
×
915
                                },
×
916
                        },
×
917
                },
×
918
                WebhookPath: ptr.To(util.HCOMutatingWebhookPath),
×
919
        }
×
920

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

1102
func InjectVolumesForWebHookCerts(deploy *appsv1.Deployment) {
×
1103
        // check if there is already a volume for api certificates
×
1104
        for _, vol := range deploy.Spec.Template.Spec.Volumes {
×
1105
                if vol.Name == certVolume {
×
1106
                        return
×
1107
                }
×
1108
        }
1109

1110
        volume := corev1.Volume{
×
1111
                Name: certVolume,
×
1112
                VolumeSource: corev1.VolumeSource{
×
1113
                        Secret: &corev1.SecretVolumeSource{
×
1114
                                SecretName:  deploy.Name + "-service-cert",
×
1115
                                DefaultMode: ptr.To[int32](420),
×
1116
                                Items: []corev1.KeyToPath{
×
1117
                                        {
×
1118
                                                Key:  "tls.crt",
×
1119
                                                Path: util.WebhookCertName,
×
1120
                                        },
×
1121
                                        {
×
1122
                                                Key:  "tls.key",
×
1123
                                                Path: util.WebhookKeyName,
×
1124
                                        },
×
1125
                                },
×
1126
                        },
×
1127
                },
×
1128
        }
×
1129
        deploy.Spec.Template.Spec.Volumes = append(deploy.Spec.Template.Spec.Volumes, volume)
×
1130

×
1131
        for index, container := range deploy.Spec.Template.Spec.Containers {
×
1132
                deploy.Spec.Template.Spec.Containers[index].VolumeMounts = append(container.VolumeMounts,
×
1133
                        corev1.VolumeMount{
×
1134
                                Name:      certVolume,
×
1135
                                MountPath: util.DefaultWebhookCertDir,
×
1136
                        })
×
1137
        }
×
1138
}
1139

1140
func getReadinessProbe(endpoint string, port int32) *corev1.Probe {
×
1141
        return &corev1.Probe{
×
1142
                ProbeHandler: corev1.ProbeHandler{
×
1143
                        HTTPGet: &corev1.HTTPGetAction{
×
1144
                                Path: endpoint,
×
1145
                                Port: intstr.IntOrString{
×
1146
                                        Type:   intstr.Int,
×
1147
                                        IntVal: port,
×
1148
                                },
×
1149
                                Scheme: corev1.URISchemeHTTP,
×
1150
                        },
×
1151
                },
×
1152
                InitialDelaySeconds: 5,
×
1153
                PeriodSeconds:       5,
×
1154
                FailureThreshold:    1,
×
1155
        }
×
1156
}
×
1157

1158
func getLivenessProbe(endpoint string, port int32) *corev1.Probe {
×
1159
        return &corev1.Probe{
×
1160
                ProbeHandler: corev1.ProbeHandler{
×
1161
                        HTTPGet: &corev1.HTTPGetAction{
×
1162
                                Path: endpoint,
×
1163
                                Port: intstr.IntOrString{
×
1164
                                        Type:   intstr.Int,
×
1165
                                        IntVal: port,
×
1166
                                },
×
1167
                                Scheme: corev1.URISchemeHTTP,
×
1168
                        },
×
1169
                },
×
1170
                InitialDelaySeconds: 30,
×
1171
                PeriodSeconds:       5,
×
1172
                FailureThreshold:    1,
×
1173
        }
×
1174
}
×
1175

1176
func getMetricsPort() corev1.ContainerPort {
×
1177
        return corev1.ContainerPort{
×
1178
                Name:          util.MetricsPortName,
×
1179
                ContainerPort: util.MetricsPort,
×
1180
                Protocol:      corev1.ProtocolTCP,
×
1181
        }
×
1182
}
×
1183

1184
func getWebhookPort() corev1.ContainerPort {
×
1185
        return corev1.ContainerPort{
×
1186
                Name:          util.WebhookPortName,
×
1187
                ContainerPort: util.WebhookPort,
×
1188
                Protocol:      corev1.ProtocolTCP,
×
1189
        }
×
1190
}
×
1191

1192
func stringListToSlice(words ...string) []string {
×
1193
        return words
×
1194
}
×
1195

1196
func panicOnError(err error) {
×
1197
        if err != nil {
×
1198
                panic(err)
×
1199
        }
1200
}
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