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

kubevirt / hyperconverged-cluster-operator / 13113994127

03 Feb 2025 12:57PM UTC coverage: 71.921% (-0.01%) from 71.931%
13113994127

push

github

web-flow
Add 'openshift.io/required-scc' annotation to pods (#3284)

The OpenShift API dictates that a workload should require an SCC by using the  annotation:
https://docs.openshift.com/container-platform/4.17/authentication/managing-security-context-constraints.html#security-context-constraints-requiring_configuring-internal-oauth

'required-scc' prevents customers (or other extension provided) SCCs from being auto-selected by pods. The auto selection can fail in multiple ways: not enough permissions, changes of UID. When combined with pod security admission (on in new clusters in 4.19), this can result in SCCs being selected based on RBAC permissions that violate PSA and results in pods not running.

Signed-off-by: Oren Cohen <ocohen@redhat.com>

# Conflicts:
#	deploy/olm-catalog/community-kubevirt-hyperconverged/1.15.0/manifests/kubevirt-hyperconverged-operator.v1.15.0.clusterserviceversion.yaml

# Conflicts:
#	deploy/olm-catalog/community-kubevirt-hyperconverged/1.15.0/manifests/kubevirt-hyperconverged-operator.v1.15.0.clusterserviceversion.yaml

3 of 4 new or added lines in 2 files covered. (75.0%)

1 existing line in 1 file now uncovered.

6160 of 8565 relevant lines covered (71.92%)

0.79 hits per line

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

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

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

9
        "k8s.io/utils/ptr"
10

11
        "github.com/blang/semver/v4"
12
        csvVersion "github.com/operator-framework/api/pkg/lib/version"
13
        csvv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
14
        "golang.org/x/tools/go/packages"
15
        admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
16
        appsv1 "k8s.io/api/apps/v1"
17
        corev1 "k8s.io/api/core/v1"
18
        v1 "k8s.io/api/core/v1"
19
        rbacv1 "k8s.io/api/rbac/v1"
20
        extv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
21
        "k8s.io/apimachinery/pkg/api/resource"
22
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
23
        "k8s.io/apimachinery/pkg/runtime"
24
        "k8s.io/apimachinery/pkg/runtime/schema"
25
        "k8s.io/apimachinery/pkg/util/intstr"
26
        crdgen "sigs.k8s.io/controller-tools/pkg/crd"
27
        crdmarkers "sigs.k8s.io/controller-tools/pkg/crd/markers"
28
        "sigs.k8s.io/controller-tools/pkg/loader"
29
        "sigs.k8s.io/controller-tools/pkg/markers"
30

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

37
        hcov1beta1 "github.com/kubevirt/hyperconverged-cluster-operator/api/v1beta1"
38
        "github.com/kubevirt/hyperconverged-cluster-operator/pkg/util"
39
        hcoutil "github.com/kubevirt/hyperconverged-cluster-operator/pkg/util"
40
)
41

42
const DisableOperandDeletionAnnotation = "console.openshift.io/disable-operand-delete"
43

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

53
        cliDownloadsName = "hyperconverged-cluster-cli-download"
54

55
        kubevirtProjectName = "KubeVirt project"
56
        rbacVersionV1       = "rbac.authorization.k8s.io/v1"
57
)
58

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

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

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

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

×
117
        InjectVolumesForWebHookCerts(&deploy)
×
118
        return deploy
×
119
}
×
120

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

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

160
func GetDeploymentSpecOperator(params *DeploymentOperatorParams) appsv1.DeploymentSpec {
×
161
        envs := buildEnvVars(params)
×
162

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

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

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

308
        return envs
×
309
}
310

311
func GetDeploymentSpecCliDownloads(params *DeploymentOperatorParams) appsv1.DeploymentSpec {
×
312
        return appsv1.DeploymentSpec{
×
313
                Replicas: int32Ptr(1),
×
314
                Selector: &metav1.LabelSelector{
×
315
                        MatchLabels: map[string]string{
×
316
                                "name": cliDownloadsName,
×
317
                        },
×
318
                },
×
319
                Strategy: appsv1.DeploymentStrategy{
×
320
                        Type: appsv1.RollingUpdateDeploymentStrategyType,
×
321
                },
×
322
                Template: corev1.PodTemplateSpec{
×
323
                        ObjectMeta: metav1.ObjectMeta{
×
324
                                Labels: getLabels(cliDownloadsName, params.HcoKvIoVersion),
×
325
                        },
×
326
                        Spec: corev1.PodSpec{
×
327
                                SecurityContext: GetStdPodSecurityContext(),
×
328
                                Containers: []corev1.Container{
×
329
                                        {
×
330
                                                Name:            "server",
×
331
                                                Image:           params.CliDownloadsImage,
×
332
                                                ImagePullPolicy: corev1.PullPolicy(params.ImagePullPolicy),
×
333
                                                Resources: v1.ResourceRequirements{
×
334
                                                        Requests: map[v1.ResourceName]resource.Quantity{
×
335
                                                                v1.ResourceCPU:    resource.MustParse("10m"),
×
336
                                                                v1.ResourceMemory: resource.MustParse("96Mi"),
×
337
                                                        },
×
338
                                                },
×
339
                                                Ports: []v1.ContainerPort{
×
340
                                                        {
×
341
                                                                Protocol:      v1.ProtocolTCP,
×
342
                                                                ContainerPort: int32(8080),
×
343
                                                        },
×
344
                                                },
×
345
                                                SecurityContext: GetStdContainerSecurityContext(),
×
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
                hcoutil.AppLabelVersion:   hcoKvIoVersion,
×
358
                hcoutil.AppLabelPartOf:    hcoutil.HyperConvergedCluster,
×
359
                hcoutil.AppLabelComponent: string(hcoutil.AppComponentDeployment),
×
360
        }
×
361
}
×
362

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

372
func GetStdContainerSecurityContext() *v1.SecurityContext {
1✔
373
        return &v1.SecurityContext{
1✔
374
                AllowPrivilegeEscalation: ptr.To(false),
1✔
375
                Capabilities: &v1.Capabilities{
1✔
376
                        Drop: []v1.Capability{"ALL"},
1✔
377
                },
1✔
378
        }
1✔
379
}
1✔
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: int32Ptr(1),
×
396
                Selector: &metav1.LabelSelector{
×
397
                        MatchLabels: map[string]string{
×
398
                                "name": hcoNameWebhook,
×
399
                        },
×
400
                },
×
401
                Strategy: appsv1.DeploymentStrategy{
×
402
                        Type: appsv1.RollingUpdateDeploymentStrategyType,
×
403
                },
×
404
                Template: corev1.PodTemplateSpec{
×
405
                        ObjectMeta: metav1.ObjectMeta{
×
406
                                Labels: getLabels(hcoNameWebhook, hcoKvIoVersion),
×
407
                        },
×
408
                        Spec: corev1.PodSpec{
×
409
                                ServiceAccountName: hcoName,
×
410
                                SecurityContext:    GetStdPodSecurityContext(),
×
411
                                Containers: []corev1.Container{
×
412
                                        {
×
413
                                                Name:            hcoNameWebhook,
×
414
                                                Image:           image,
×
415
                                                ImagePullPolicy: corev1.PullPolicy(imagePullPolicy),
×
416
                                                Command:         stringListToSlice(hcoNameWebhook),
×
417
                                                ReadinessProbe:  getReadinessProbe(),
×
418
                                                LivenessProbe:   getLivenessProbe(),
×
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: hcoNameWebhook,
×
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
                                                }, env...),
×
450
                                                Resources: v1.ResourceRequirements{
×
451
                                                        Requests: map[v1.ResourceName]resource.Quantity{
×
452
                                                                v1.ResourceCPU:    resource.MustParse("5m"),
×
453
                                                                v1.ResourceMemory: resource.MustParse("48Mi"),
×
454
                                                        },
×
455
                                                },
×
456
                                                SecurityContext: GetStdContainerSecurityContext(),
×
457
                                        },
×
458
                                },
×
459
                                PriorityClassName: "system-node-critical",
×
460
                        },
×
461
                },
×
462
        }
×
463
}
×
464

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

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

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

606
func roleWithAllPermissions(apiGroup string, resources []string) rbacv1.PolicyRule {
×
607
        return rbacv1.PolicyRule{
×
608
                APIGroups: stringListToSlice(apiGroup),
×
609
                Resources: resources,
×
610
                Verbs:     stringListToSlice("get", "list", "watch", "create", "update", "delete", "patch"),
×
611
        }
×
612
}
×
613

614
func GetServiceAccount(namespace string) v1.ServiceAccount {
×
615
        return v1.ServiceAccount{
×
616
                TypeMeta: metav1.TypeMeta{
×
617
                        APIVersion: "v1",
×
618
                        Kind:       "ServiceAccount",
×
619
                },
×
620
                ObjectMeta: metav1.ObjectMeta{
×
621
                        Name:      hcoName,
×
622
                        Namespace: namespace,
×
623
                        Labels: map[string]string{
×
624
                                "name": hcoName,
×
625
                        },
×
626
                },
×
627
        }
×
628
}
×
629

630
func GetClusterRoleBinding(namespace string) rbacv1.ClusterRoleBinding {
×
631
        return rbacv1.ClusterRoleBinding{
×
632
                TypeMeta: metav1.TypeMeta{
×
633
                        APIVersion: rbacVersionV1,
×
634
                        Kind:       "ClusterRoleBinding",
×
635
                },
×
636
                ObjectMeta: metav1.ObjectMeta{
×
637
                        Name: hcoName,
×
638
                        Labels: map[string]string{
×
639
                                "name": hcoName,
×
640
                        },
×
641
                },
×
642
                RoleRef: rbacv1.RoleRef{
×
643
                        APIGroup: "rbac.authorization.k8s.io",
×
644
                        Kind:     "ClusterRole",
×
645
                        Name:     hcoName,
×
646
                },
×
647
                Subjects: []rbacv1.Subject{
×
648
                        {
×
649
                                Kind:      "ServiceAccount",
×
650
                                Name:      hcoName,
×
651
                                Namespace: namespace,
×
652
                        },
×
653
                },
×
654
        }
×
655
}
×
656

657
func packageErrors(pkg *loader.Package, filterKinds ...packages.ErrorKind) error {
×
658
        toSkip := make(map[packages.ErrorKind]struct{})
×
659
        for _, errKind := range filterKinds {
×
660
                toSkip[errKind] = struct{}{}
×
661
        }
×
662
        var outErr error
×
663
        packages.Visit([]*packages.Package{pkg.Package}, nil, func(pkgRaw *packages.Package) {
×
664
                for _, err := range pkgRaw.Errors {
×
665
                        if _, skip := toSkip[err.Kind]; skip {
×
666
                                continue
×
667
                        }
668
                        outErr = err
×
669
                }
670
        })
671
        return outErr
×
672
}
673

674
const objectType = "object"
675

676
func GetOperatorCRD(relPath string) *extv1.CustomResourceDefinition {
×
677
        pkgs, err := loader.LoadRoots(relPath)
×
678
        if err != nil {
×
679
                panic(err)
×
680
        }
681
        reg := &markers.Registry{}
×
682
        panicOnError(crdmarkers.Register(reg))
×
683

×
684
        parser := &crdgen.Parser{
×
685
                Collector:                  &markers.Collector{Registry: reg},
×
686
                Checker:                    &loader.TypeChecker{},
×
687
                GenerateEmbeddedObjectMeta: true,
×
688
        }
×
689

×
690
        crdgen.AddKnownTypes(parser)
×
691
        if len(pkgs) == 0 {
×
692
                panic("Failed identifying packages")
×
693
        }
694
        for _, p := range pkgs {
×
695
                parser.NeedPackage(p)
×
696
        }
×
697
        groupKind := schema.GroupKind{Kind: util.HyperConvergedKind, Group: util.APIVersionGroup}
×
698
        parser.NeedCRDFor(groupKind, nil)
×
699
        for _, p := range pkgs {
×
700
                err = packageErrors(p, packages.TypeError)
×
701
                if err != nil {
×
702
                        panic(err)
×
703
                }
704
        }
705
        c := parser.CustomResourceDefinitions[groupKind]
×
706
        // enforce validation of CR name to prevent multiple CRs
×
707
        for _, v := range c.Spec.Versions {
×
708
                v.Schema.OpenAPIV3Schema.Properties["metadata"] = extv1.JSONSchemaProps{
×
709
                        Type: objectType,
×
710
                        Properties: map[string]extv1.JSONSchemaProps{
×
711
                                "name": {
×
712
                                        Type:    "string",
×
713
                                        Pattern: hcov1beta1.HyperConvergedName,
×
714
                                },
×
715
                        },
×
716
                }
×
717
        }
×
718
        return &c
×
719
}
720

721
func GetOperatorCR() *hcov1beta1.HyperConverged {
1✔
722
        defaultScheme := runtime.NewScheme()
1✔
723
        _ = hcov1beta1.AddToScheme(defaultScheme)
1✔
724
        _ = hcov1beta1.RegisterDefaults(defaultScheme)
1✔
725
        defaultHco := &hcov1beta1.HyperConverged{
1✔
726
                TypeMeta: metav1.TypeMeta{
1✔
727
                        APIVersion: util.APIVersion,
1✔
728
                        Kind:       util.HyperConvergedKind,
1✔
729
                },
1✔
730
                ObjectMeta: metav1.ObjectMeta{
1✔
731
                        Name: crName,
1✔
732
                }}
1✔
733
        defaultScheme.Default(defaultHco)
1✔
734
        return defaultHco
1✔
735
}
1✔
736

737
// GetInstallStrategyBase returns the basics of an HCO InstallStrategy
738
func GetInstallStrategyBase(params *DeploymentOperatorParams) *csvv1alpha1.StrategyDetailsDeployment {
×
739
        return &csvv1alpha1.StrategyDetailsDeployment{
×
740

×
741
                DeploymentSpecs: []csvv1alpha1.StrategyDeploymentSpec{
×
742
                        {
×
743
                                Name:  hcoDeploymentName,
×
744
                                Spec:  GetDeploymentSpecOperator(params),
×
745
                                Label: getLabels(hcoName, params.HcoKvIoVersion),
×
746
                        },
×
747
                        {
×
748
                                Name:  hcoWhDeploymentName,
×
749
                                Spec:  GetDeploymentSpecWebhook(params.Namespace, params.WebhookImage, params.ImagePullPolicy, params.HcoKvIoVersion, params.Env),
×
750
                                Label: getLabels(hcoNameWebhook, params.HcoKvIoVersion),
×
751
                        },
×
752
                        {
×
753
                                Name:  cliDownloadsName,
×
754
                                Spec:  GetDeploymentSpecCliDownloads(params),
×
755
                                Label: getLabels(cliDownloadsName, params.HcoKvIoVersion),
×
756
                        },
×
757
                },
×
758
                Permissions: []csvv1alpha1.StrategyDeploymentPermissions{},
×
759
                ClusterPermissions: []csvv1alpha1.StrategyDeploymentPermissions{
×
760
                        {
×
761
                                ServiceAccountName: hcoName,
×
762
                                Rules:              GetClusterPermissions(),
×
763
                        },
×
764
                },
×
765
        }
×
766
}
×
767

768
type CSVBaseParams struct {
769
        Name            string
770
        Namespace       string
771
        DisplayName     string
772
        MetaDescription string
773
        Description     string
774
        Image           string
775
        Replaces        string
776
        Version         semver.Version
777
        CrdDisplay      string
778
}
779

780
// GetCSVBase returns a base HCO CSV without an InstallStrategy
781
func GetCSVBase(params *CSVBaseParams) *csvv1alpha1.ClusterServiceVersion {
×
782
        almExamples, _ := json.Marshal(
×
783
                map[string]interface{}{
×
784
                        "apiVersion": util.APIVersion,
×
785
                        "kind":       util.HyperConvergedKind,
×
786
                        "metadata": map[string]interface{}{
×
787
                                "name":      packageName,
×
788
                                "namespace": params.Namespace,
×
789
                                "annotations": map[string]string{
×
790
                                        "deployOVS": "false",
×
791
                                },
×
792
                        },
×
793
                        "spec": map[string]interface{}{},
×
794
                })
×
795

×
796
        // Explicitly fail on unvalidated (for any reason) requests:
×
797
        // this can make removing HCO CR harder if HCO webhook is not able
×
798
        // to really validate the requests.
×
799
        // In that case the user can only directly remove the
×
800
        // ValidatingWebhookConfiguration object first (eventually bypassing the OLM if needed).
×
801
        // so failurePolicy = admissionregistrationv1.Fail
×
802

×
803
        validatingWebhook := csvv1alpha1.WebhookDescription{
×
804
                GenerateName:            util.HcoValidatingWebhook,
×
805
                Type:                    csvv1alpha1.ValidatingAdmissionWebhook,
×
806
                DeploymentName:          hcoWhDeploymentName,
×
807
                ContainerPort:           util.WebhookPort,
×
808
                AdmissionReviewVersions: stringListToSlice("v1beta1", "v1"),
×
809
                SideEffects:             ptr.To(admissionregistrationv1.SideEffectClassNone),
×
810
                FailurePolicy:           ptr.To(admissionregistrationv1.Fail),
×
811
                TimeoutSeconds:          ptr.To[int32](10),
×
812
                Rules: []admissionregistrationv1.RuleWithOperations{
×
813
                        {
×
814
                                Operations: []admissionregistrationv1.OperationType{
×
815
                                        admissionregistrationv1.Create,
×
816
                                        admissionregistrationv1.Delete,
×
817
                                        admissionregistrationv1.Update,
×
818
                                },
×
819
                                Rule: admissionregistrationv1.Rule{
×
820
                                        APIGroups:   stringListToSlice(util.APIVersionGroup),
×
821
                                        APIVersions: stringListToSlice(util.APIVersionAlpha, util.APIVersionBeta),
×
822
                                        Resources:   stringListToSlice("hyperconvergeds"),
×
823
                                },
×
824
                        },
×
825
                },
×
826
                WebhookPath: ptr.To(util.HCOWebhookPath),
×
827
        }
×
828

×
829
        mutatingNamespaceWebhook := csvv1alpha1.WebhookDescription{
×
830
                GenerateName:            util.HcoMutatingWebhookNS,
×
831
                Type:                    csvv1alpha1.MutatingAdmissionWebhook,
×
832
                DeploymentName:          hcoWhDeploymentName,
×
833
                ContainerPort:           util.WebhookPort,
×
834
                AdmissionReviewVersions: stringListToSlice("v1beta1", "v1"),
×
835
                SideEffects:             ptr.To(admissionregistrationv1.SideEffectClassNoneOnDryRun),
×
836
                FailurePolicy:           ptr.To(admissionregistrationv1.Fail),
×
837
                TimeoutSeconds:          ptr.To[int32](10),
×
838
                ObjectSelector: &metav1.LabelSelector{
×
839
                        MatchLabels: map[string]string{util.KubernetesMetadataName: params.Namespace},
×
840
                },
×
841
                Rules: []admissionregistrationv1.RuleWithOperations{
×
842
                        {
×
843
                                Operations: []admissionregistrationv1.OperationType{
×
844
                                        admissionregistrationv1.Delete,
×
845
                                },
×
846
                                Rule: admissionregistrationv1.Rule{
×
847
                                        APIGroups:   []string{""},
×
848
                                        APIVersions: stringListToSlice("v1"),
×
849
                                        Resources:   stringListToSlice("namespaces"),
×
850
                                },
×
851
                        },
×
852
                },
×
853
                WebhookPath: ptr.To(util.HCONSWebhookPath),
×
854
        }
×
855

×
856
        mutatingHyperConvergedWebhook := csvv1alpha1.WebhookDescription{
×
857
                GenerateName:            util.HcoMutatingWebhookHyperConverged,
×
858
                Type:                    csvv1alpha1.MutatingAdmissionWebhook,
×
859
                DeploymentName:          hcoWhDeploymentName,
×
860
                ContainerPort:           util.WebhookPort,
×
861
                AdmissionReviewVersions: stringListToSlice("v1beta1", "v1"),
×
862
                SideEffects:             ptr.To(admissionregistrationv1.SideEffectClassNoneOnDryRun),
×
863
                FailurePolicy:           ptr.To(admissionregistrationv1.Fail),
×
864
                TimeoutSeconds:          ptr.To[int32](10),
×
865
                Rules: []admissionregistrationv1.RuleWithOperations{
×
866
                        {
×
867
                                Operations: []admissionregistrationv1.OperationType{
×
868
                                        admissionregistrationv1.Create,
×
869
                                        admissionregistrationv1.Update,
×
870
                                },
×
871
                                Rule: admissionregistrationv1.Rule{
×
872
                                        APIGroups:   stringListToSlice(util.APIVersionGroup),
×
873
                                        APIVersions: stringListToSlice(util.APIVersionAlpha, util.APIVersionBeta),
×
874
                                        Resources:   stringListToSlice("hyperconvergeds"),
×
875
                                },
×
876
                        },
×
877
                },
×
878
                WebhookPath: ptr.To(util.HCOMutatingWebhookPath),
×
879
        }
×
880

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

1063
func InjectVolumesForWebHookCerts(deploy *appsv1.Deployment) {
×
1064
        // check if there is already a volume for api certificates
×
1065
        for _, vol := range deploy.Spec.Template.Spec.Volumes {
×
1066
                if vol.Name == certVolume {
×
1067
                        return
×
1068
                }
×
1069
        }
1070

1071
        volume := v1.Volume{
×
1072
                Name: certVolume,
×
1073
                VolumeSource: corev1.VolumeSource{
×
1074
                        Secret: &corev1.SecretVolumeSource{
×
1075
                                SecretName:  deploy.Name + "-service-cert",
×
1076
                                DefaultMode: ptr.To[int32](420),
×
1077
                                Items: []corev1.KeyToPath{
×
1078
                                        {
×
1079
                                                Key:  "tls.crt",
×
1080
                                                Path: hcoutil.WebhookCertName,
×
1081
                                        },
×
1082
                                        {
×
1083
                                                Key:  "tls.key",
×
1084
                                                Path: hcoutil.WebhookKeyName,
×
1085
                                        },
×
1086
                                },
×
1087
                        },
×
1088
                },
×
1089
        }
×
1090
        deploy.Spec.Template.Spec.Volumes = append(deploy.Spec.Template.Spec.Volumes, volume)
×
1091

×
1092
        for index, container := range deploy.Spec.Template.Spec.Containers {
×
1093
                deploy.Spec.Template.Spec.Containers[index].VolumeMounts = append(container.VolumeMounts,
×
1094
                        corev1.VolumeMount{
×
1095
                                Name:      certVolume,
×
1096
                                MountPath: hcoutil.DefaultWebhookCertDir,
×
1097
                        })
×
1098
        }
×
1099
}
1100

1101
func getReadinessProbe() *corev1.Probe {
×
1102
        return &corev1.Probe{
×
1103
                ProbeHandler: corev1.ProbeHandler{
×
1104
                        HTTPGet: &corev1.HTTPGetAction{
×
1105
                                Path: hcoutil.ReadinessEndpointName,
×
1106
                                Port: intstr.IntOrString{
×
1107
                                        Type:   intstr.Int,
×
1108
                                        IntVal: hcoutil.HealthProbePort,
×
1109
                                },
×
1110
                                Scheme: corev1.URISchemeHTTP,
×
1111
                        },
×
1112
                },
×
1113
                InitialDelaySeconds: 5,
×
1114
                PeriodSeconds:       5,
×
1115
                FailureThreshold:    1,
×
1116
        }
×
1117
}
×
1118

1119
func getLivenessProbe() *corev1.Probe {
×
1120
        return &corev1.Probe{
×
1121
                ProbeHandler: corev1.ProbeHandler{
×
1122
                        HTTPGet: &corev1.HTTPGetAction{
×
1123
                                Path: hcoutil.LivenessEndpointName,
×
1124
                                Port: intstr.IntOrString{
×
1125
                                        Type:   intstr.Int,
×
1126
                                        IntVal: hcoutil.HealthProbePort,
×
1127
                                },
×
1128
                                Scheme: corev1.URISchemeHTTP,
×
1129
                        },
×
1130
                },
×
1131
                InitialDelaySeconds: 30,
×
1132
                PeriodSeconds:       5,
×
1133
                FailureThreshold:    1,
×
1134
        }
×
1135
}
×
1136

1137
func stringListToSlice(words ...string) []string {
×
1138
        return words
×
1139
}
×
1140

1141
func int32Ptr(i int32) *int32 {
×
1142
        return &i
×
1143
}
×
1144

1145
func panicOnError(err error) {
×
1146
        if err != nil {
×
1147
                panic(err)
×
1148
        }
1149
}
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