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

kubevirt / hyperconverged-cluster-operator / 16339590247

17 Jul 2025 08:01AM UTC coverage: 75.103% (-0.02%) from 75.124%
16339590247

Pull #3601

github

web-flow
Merge bcff6906b into cb8d4dd66
Pull Request #3601: network,passt: Deploy Passt required objects

391 of 521 new or added lines in 10 files covered. (75.05%)

97 existing lines in 2 files now uncovered.

6908 of 9198 relevant lines covered (75.1%)

1.77 hits per line

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

2.91
/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/v1beta3"
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
        // labels to apply network policies:
56
        allowEgressToDNSAndAPIServerLabel  = "hco.kubevirt.io/allow-access-cluster-services"
57
        allowIngressToMetricsEndpointLabel = "hco.kubevirt.io/allow-prometheus-access"
58
)
59

60
var deploymentType = metav1.TypeMeta{
61
        APIVersion: "apps/v1",
62
        Kind:       "Deployment",
63
}
64

65
type DeploymentOperatorParams struct {
66
        Namespace              string
67
        Image                  string
68
        WebhookImage           string
69
        CliDownloadsImage      string
70
        KVUIPluginImage        string
71
        KVUIProxyImage         string
72
        PasstImage             string
73
        PasstCNIImage          string
74
        ImagePullPolicy        string
75
        ConversionContainer    string
76
        VmwareContainer        string
77
        VirtIOWinContainer     string
78
        Smbios                 string
79
        Machinetype            string
80
        Amd64MachineType       string
81
        Arm64MachineType       string
82
        HcoKvIoVersion         string
83
        KubevirtVersion        string
84
        KvVirtLancherOsVersion string
85
        CdiVersion             string
86
        CnaoVersion            string
87
        SspVersion             string
88
        HppoVersion            string
89
        MtqVersion             string
90
        AaqVersion             string
91
        Env                    []corev1.EnvVar
92
        AddNetworkPolicyLabels bool
93
}
94

95
func GetDeploymentOperator(params *DeploymentOperatorParams) appsv1.Deployment {
×
96
        return appsv1.Deployment{
×
97
                TypeMeta: deploymentType,
×
98
                ObjectMeta: metav1.ObjectMeta{
×
99
                        Name: hcoName,
×
100
                        Labels: map[string]string{
×
101
                                "name": hcoName,
×
102
                        },
×
103
                },
×
104
                Spec: GetDeploymentSpecOperator(params),
×
105
        }
×
UNCOV
106
}
×
107

108
func GetDeploymentWebhook(params *DeploymentOperatorParams) appsv1.Deployment {
×
109
        deploy := appsv1.Deployment{
×
110
                TypeMeta: deploymentType,
×
111
                ObjectMeta: metav1.ObjectMeta{
×
112
                        Name: hcoNameWebhook,
×
113
                        Labels: map[string]string{
×
114
                                "name": hcoNameWebhook,
×
115
                        },
×
116
                },
×
117
                Spec: GetDeploymentSpecWebhook(params),
×
118
        }
×
119

×
120
        InjectVolumesForWebHookCerts(&deploy)
×
121
        return deploy
×
UNCOV
122
}
×
123

124
func GetDeploymentCliDownloads(params *DeploymentOperatorParams) appsv1.Deployment {
×
125
        return appsv1.Deployment{
×
126
                TypeMeta: deploymentType,
×
127
                ObjectMeta: metav1.ObjectMeta{
×
128
                        Name: cliDownloadsName,
×
129
                        Labels: map[string]string{
×
130
                                "name": cliDownloadsName,
×
131
                        },
×
132
                },
×
133
                Spec: GetDeploymentSpecCliDownloads(params),
×
134
        }
×
UNCOV
135
}
×
136

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

163
func GetDeploymentSpecOperator(params *DeploymentOperatorParams) appsv1.DeploymentSpec {
×
164
        envs := buildEnvVars(params)
×
165

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

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

×
312
        if params.KvVirtLancherOsVersion != "" {
×
UNCOV
313
                envs = append(envs, corev1.EnvVar{
×
314
                        Name:  util.KvVirtLauncherOSVersionEnvV,
×
UNCOV
315
                        Value: params.KvVirtLancherOsVersion,
×
UNCOV
316
                })
×
317
        }
×
318

319
        return envs
×
320
}
321

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

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

379
func getLabelsWithNetworkPolicies(deploymentName string, params *DeploymentOperatorParams) map[string]string {
×
UNCOV
380
        labels := getLabels(deploymentName, params.HcoKvIoVersion)
×
381
        if params.AddNetworkPolicyLabels {
×
UNCOV
382
                labels[allowEgressToDNSAndAPIServerLabel] = "true"
×
UNCOV
383
                labels[allowIngressToMetricsEndpointLabel] = "true"
×
UNCOV
384
        }
×
385

UNCOV
386
        return labels
×
387
}
388

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

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

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

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

512
var (
513
        emptyAPIGroup = []string{""}
514
)
515

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

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

680
func GetServiceAccount(namespace string) corev1.ServiceAccount {
×
681
        return createServiceAccount(namespace, hcoName)
×
682
}
×
683

684
func GetCLIDownloadServiceAccount(namespace string) corev1.ServiceAccount {
×
685
        return createServiceAccount(namespace, cliDownloadsName)
×
686
}
×
687

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

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

UNCOV
731
func packageErrors(pkg *loader.Package, filterKinds ...packages.ErrorKind) error {
×
732
        toSkip := make(map[packages.ErrorKind]struct{})
×
UNCOV
733
        for _, errKind := range filterKinds {
×
UNCOV
734
                toSkip[errKind] = struct{}{}
×
735
        }
×
UNCOV
736
        var outErr error
×
UNCOV
737
        packages.Visit([]*packages.Package{pkg.Package}, nil, func(pkgRaw *packages.Package) {
×
UNCOV
738
                for _, err := range pkgRaw.Errors {
×
UNCOV
739
                        if _, skip := toSkip[err.Kind]; skip {
×
740
                                continue
×
741
                        }
742
                        outErr = err
×
743
                }
744
        })
745
        return outErr
×
746
}
747

748
const objectType = "object"
749

750
func GetOperatorCRD(relPath string) *extv1.CustomResourceDefinition {
×
751
        pkgs, err := loader.LoadRoots(relPath)
×
752
        if err != nil {
×
753
                panic(err)
×
754
        }
755
        reg := &markers.Registry{}
×
756
        panicOnError(crdmarkers.Register(reg))
×
UNCOV
757

×
758
        parser := &crdgen.Parser{
×
759
                Collector:                  &markers.Collector{Registry: reg},
×
760
                Checker:                    &loader.TypeChecker{},
×
761
                GenerateEmbeddedObjectMeta: true,
×
762
        }
×
763

×
764
        crdgen.AddKnownTypes(parser)
×
765
        if len(pkgs) == 0 {
×
766
                panic("Failed identifying packages")
×
767
        }
UNCOV
768
        for _, p := range pkgs {
×
769
                parser.NeedPackage(p)
×
770
        }
×
771
        groupKind := schema.GroupKind{Kind: util.HyperConvergedKind, Group: util.APIVersionGroup}
×
772
        parser.NeedCRDFor(groupKind, nil)
×
773
        for _, p := range pkgs {
×
774
                err = packageErrors(p, packages.TypeError)
×
775
                if err != nil {
×
776
                        panic(err)
×
777
                }
778
        }
779
        c := parser.CustomResourceDefinitions[groupKind]
×
780
        // enforce validation of CR name to prevent multiple CRs
×
781
        for _, v := range c.Spec.Versions {
×
782
                v.Schema.OpenAPIV3Schema.Properties["metadata"] = extv1.JSONSchemaProps{
×
UNCOV
783
                        Type: objectType,
×
UNCOV
784
                        Properties: map[string]extv1.JSONSchemaProps{
×
UNCOV
785
                                "name": {
×
UNCOV
786
                                        Type:    "string",
×
UNCOV
787
                                        Pattern: hcov1beta1.HyperConvergedName,
×
UNCOV
788
                                },
×
UNCOV
789
                        },
×
UNCOV
790
                }
×
UNCOV
791
        }
×
UNCOV
792
        return &c
×
793
}
794

795
func GetOperatorCR() *hcov1beta1.HyperConverged {
11✔
796
        defaultScheme := runtime.NewScheme()
11✔
797
        _ = hcov1beta1.AddToScheme(defaultScheme)
11✔
798
        _ = hcov1beta1.RegisterDefaults(defaultScheme)
11✔
799
        defaultHco := &hcov1beta1.HyperConverged{
11✔
800
                TypeMeta: metav1.TypeMeta{
11✔
801
                        APIVersion: util.APIVersion,
11✔
802
                        Kind:       util.HyperConvergedKind,
11✔
803
                },
11✔
804
                ObjectMeta: metav1.ObjectMeta{
11✔
805
                        Name: crName,
11✔
806
                }}
11✔
807
        defaultScheme.Default(defaultHco)
11✔
808
        return defaultHco
11✔
809
}
11✔
810

811
// GetInstallStrategyBase returns the basics of an HCO InstallStrategy
812
func GetInstallStrategyBase(params *DeploymentOperatorParams) *csvv1alpha1.StrategyDetailsDeployment {
×
813
        return &csvv1alpha1.StrategyDetailsDeployment{
×
814

×
815
                DeploymentSpecs: []csvv1alpha1.StrategyDeploymentSpec{
×
816
                        {
×
817
                                Name:  hcoDeploymentName,
×
818
                                Spec:  GetDeploymentSpecOperator(params),
×
819
                                Label: getLabels(hcoName, params.HcoKvIoVersion),
×
820
                        },
×
821
                        {
×
822
                                Name:  hcoWhDeploymentName,
×
823
                                Spec:  GetDeploymentSpecWebhook(params),
×
824
                                Label: getLabels(hcoNameWebhook, params.HcoKvIoVersion),
×
825
                        },
×
826
                        {
×
827
                                Name:  cliDownloadsName,
×
828
                                Spec:  GetDeploymentSpecCliDownloads(params),
×
829
                                Label: getLabels(cliDownloadsName, params.HcoKvIoVersion),
×
830
                        },
×
831
                },
×
832
                Permissions: []csvv1alpha1.StrategyDeploymentPermissions{},
×
833
                ClusterPermissions: []csvv1alpha1.StrategyDeploymentPermissions{
×
834
                        {
×
UNCOV
835
                                ServiceAccountName: hcoName,
×
UNCOV
836
                                Rules:              GetClusterPermissions(),
×
UNCOV
837
                        },
×
UNCOV
838
                        {
×
UNCOV
839
                                ServiceAccountName: cliDownloadsName,
×
UNCOV
840
                                Rules:              []rbacv1.PolicyRule{},
×
UNCOV
841
                        },
×
UNCOV
842
                },
×
UNCOV
843
        }
×
UNCOV
844
}
×
845

846
type CSVBaseParams struct {
847
        Name            string
848
        Namespace       string
849
        DisplayName     string
850
        MetaDescription string
851
        Description     string
852
        Image           string
853
        Replaces        string
854
        Version         semver.Version
855
        CrdDisplay      string
856
}
857

858
// GetCSVBase returns a base HCO CSV without an InstallStrategy
859
func GetCSVBase(params *CSVBaseParams) *csvv1alpha1.ClusterServiceVersion {
×
860
        almExamples, _ := json.Marshal(
×
861
                map[string]interface{}{
×
862
                        "apiVersion": util.APIVersion,
×
863
                        "kind":       util.HyperConvergedKind,
×
864
                        "metadata": map[string]interface{}{
×
865
                                "name":      packageName,
×
866
                                "namespace": params.Namespace,
×
867
                                "annotations": map[string]string{
×
868
                                        "deployOVS": "false",
×
869
                                },
×
870
                        },
×
871
                        "spec": map[string]interface{}{},
×
872
                })
×
873

×
874
        // Explicitly fail on unvalidated (for any reason) requests:
×
875
        // this can make removing HCO CR harder if HCO webhook is not able
×
876
        // to really validate the requests.
×
877
        // In that case the user can only directly remove the
×
878
        // ValidatingWebhookConfiguration object first (eventually bypassing the OLM if needed).
×
879
        // so failurePolicy = admissionregistrationv1.Fail
×
880

×
881
        validatingWebhook := csvv1alpha1.WebhookDescription{
×
882
                GenerateName:            util.HcoValidatingWebhook,
×
883
                Type:                    csvv1alpha1.ValidatingAdmissionWebhook,
×
884
                DeploymentName:          hcoWhDeploymentName,
×
885
                ContainerPort:           util.WebhookPort,
×
886
                AdmissionReviewVersions: stringListToSlice("v1beta1", "v1"),
×
887
                SideEffects:             ptr.To(admissionregistrationv1.SideEffectClassNone),
×
888
                FailurePolicy:           ptr.To(admissionregistrationv1.Fail),
×
889
                TimeoutSeconds:          ptr.To[int32](10),
×
890
                Rules: []admissionregistrationv1.RuleWithOperations{
×
891
                        {
×
892
                                Operations: []admissionregistrationv1.OperationType{
×
893
                                        admissionregistrationv1.Create,
×
894
                                        admissionregistrationv1.Delete,
×
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.HCOWebhookPath),
×
905
        }
×
906

×
907
        mutatingNamespaceWebhook := csvv1alpha1.WebhookDescription{
×
908
                GenerateName:            util.HcoMutatingWebhookNS,
×
909
                Type:                    csvv1alpha1.MutatingAdmissionWebhook,
×
910
                DeploymentName:          hcoWhDeploymentName,
×
911
                ContainerPort:           util.WebhookPort,
×
912
                AdmissionReviewVersions: stringListToSlice("v1beta1", "v1"),
×
913
                SideEffects:             ptr.To(admissionregistrationv1.SideEffectClassNoneOnDryRun),
×
914
                FailurePolicy:           ptr.To(admissionregistrationv1.Fail),
×
915
                TimeoutSeconds:          ptr.To[int32](10),
×
916
                ObjectSelector: &metav1.LabelSelector{
×
917
                        MatchLabels: map[string]string{util.KubernetesMetadataName: params.Namespace},
×
918
                },
×
919
                Rules: []admissionregistrationv1.RuleWithOperations{
×
920
                        {
×
921
                                Operations: []admissionregistrationv1.OperationType{
×
922
                                        admissionregistrationv1.Delete,
×
923
                                },
×
924
                                Rule: admissionregistrationv1.Rule{
×
925
                                        APIGroups:   []string{""},
×
926
                                        APIVersions: stringListToSlice("v1"),
×
927
                                        Resources:   stringListToSlice("namespaces"),
×
928
                                },
×
929
                        },
×
930
                },
×
931
                WebhookPath: ptr.To(util.HCONSWebhookPath),
×
932
        }
×
933

×
934
        mutatingHyperConvergedWebhook := csvv1alpha1.WebhookDescription{
×
935
                GenerateName:            util.HcoMutatingWebhookHyperConverged,
×
936
                Type:                    csvv1alpha1.MutatingAdmissionWebhook,
×
937
                DeploymentName:          hcoWhDeploymentName,
×
938
                ContainerPort:           util.WebhookPort,
×
939
                AdmissionReviewVersions: stringListToSlice("v1beta1", "v1"),
×
940
                SideEffects:             ptr.To(admissionregistrationv1.SideEffectClassNoneOnDryRun),
×
941
                FailurePolicy:           ptr.To(admissionregistrationv1.Fail),
×
942
                TimeoutSeconds:          ptr.To[int32](10),
×
943
                Rules: []admissionregistrationv1.RuleWithOperations{
×
944
                        {
×
945
                                Operations: []admissionregistrationv1.OperationType{
×
946
                                        admissionregistrationv1.Create,
×
947
                                        admissionregistrationv1.Update,
×
948
                                },
×
949
                                Rule: admissionregistrationv1.Rule{
×
950
                                        APIGroups:   stringListToSlice(util.APIVersionGroup),
×
951
                                        APIVersions: stringListToSlice(util.APIVersionAlpha, util.APIVersionBeta),
×
952
                                        Resources:   stringListToSlice("hyperconvergeds"),
×
953
                                },
×
954
                        },
×
955
                },
×
956
                WebhookPath: ptr.To(util.HCOMutatingWebhookPath),
×
957
        }
×
958

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

1141
func InjectVolumesForWebHookCerts(deploy *appsv1.Deployment) {
×
1142
        // check if there is already a volume for api certificates
×
1143
        for _, vol := range deploy.Spec.Template.Spec.Volumes {
×
1144
                if vol.Name == certVolume {
×
1145
                        return
×
1146
                }
×
1147
        }
1148

1149
        volume := corev1.Volume{
×
1150
                Name: certVolume,
×
1151
                VolumeSource: corev1.VolumeSource{
×
1152
                        Secret: &corev1.SecretVolumeSource{
×
1153
                                SecretName:  deploy.Name + "-service-cert",
×
1154
                                DefaultMode: ptr.To[int32](420),
×
1155
                                Items: []corev1.KeyToPath{
×
1156
                                        {
×
1157
                                                Key:  "tls.crt",
×
1158
                                                Path: util.WebhookCertName,
×
1159
                                        },
×
1160
                                        {
×
1161
                                                Key:  "tls.key",
×
1162
                                                Path: util.WebhookKeyName,
×
1163
                                        },
×
1164
                                },
×
1165
                        },
×
1166
                },
×
UNCOV
1167
        }
×
UNCOV
1168
        deploy.Spec.Template.Spec.Volumes = append(deploy.Spec.Template.Spec.Volumes, volume)
×
1169

×
1170
        for index, container := range deploy.Spec.Template.Spec.Containers {
×
1171
                deploy.Spec.Template.Spec.Containers[index].VolumeMounts = append(container.VolumeMounts,
×
1172
                        corev1.VolumeMount{
×
1173
                                Name:      certVolume,
×
1174
                                MountPath: util.DefaultWebhookCertDir,
×
1175
                        })
×
1176
        }
×
1177
}
1178

1179
func getReadinessProbe(endpoint string, port int32) *corev1.Probe {
×
1180
        return &corev1.Probe{
×
1181
                ProbeHandler: corev1.ProbeHandler{
×
1182
                        HTTPGet: &corev1.HTTPGetAction{
×
1183
                                Path: endpoint,
×
1184
                                Port: intstr.IntOrString{
×
1185
                                        Type:   intstr.Int,
×
UNCOV
1186
                                        IntVal: port,
×
1187
                                },
×
1188
                                Scheme: corev1.URISchemeHTTP,
×
1189
                        },
×
1190
                },
×
1191
                InitialDelaySeconds: 5,
×
1192
                PeriodSeconds:       5,
×
1193
                FailureThreshold:    1,
×
1194
        }
×
1195
}
×
1196

1197
func getLivenessProbe(endpoint string, port int32) *corev1.Probe {
×
1198
        return &corev1.Probe{
×
1199
                ProbeHandler: corev1.ProbeHandler{
×
1200
                        HTTPGet: &corev1.HTTPGetAction{
×
1201
                                Path: endpoint,
×
1202
                                Port: intstr.IntOrString{
×
1203
                                        Type:   intstr.Int,
×
UNCOV
1204
                                        IntVal: port,
×
1205
                                },
×
1206
                                Scheme: corev1.URISchemeHTTP,
×
1207
                        },
×
1208
                },
×
1209
                InitialDelaySeconds: 30,
×
1210
                PeriodSeconds:       5,
×
1211
                FailureThreshold:    1,
×
UNCOV
1212
        }
×
1213
}
×
1214

1215
func getMetricsPort() corev1.ContainerPort {
×
1216
        return corev1.ContainerPort{
×
1217
                Name:          util.MetricsPortName,
×
1218
                ContainerPort: util.MetricsPort,
×
1219
                Protocol:      corev1.ProtocolTCP,
×
UNCOV
1220
        }
×
1221
}
×
1222

1223
func getWebhookPort() corev1.ContainerPort {
×
UNCOV
1224
        return corev1.ContainerPort{
×
1225
                Name:          util.WebhookPortName,
×
1226
                ContainerPort: util.WebhookPort,
×
1227
                Protocol:      corev1.ProtocolTCP,
×
UNCOV
1228
        }
×
UNCOV
1229
}
×
1230

UNCOV
1231
func stringListToSlice(words ...string) []string {
×
UNCOV
1232
        return words
×
UNCOV
1233
}
×
1234

UNCOV
1235
func panicOnError(err error) {
×
UNCOV
1236
        if err != nil {
×
UNCOV
1237
                panic(err)
×
1238
        }
1239
}
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