Skip to content
This repository was archived by the owner on Mar 22, 2024. It is now read-only.

Commit d9bd0ee

Browse files
naemonopebrc
andauthored
Support/Enable Operator Lifecycle Manager Webhooks (elastic#5043)
* Allow hack/operatorhub/main.go to read webhooks defined in operator.yaml Use GenerateName instead of Name Pass the 'enable-webhook' flag to the deployment switch containerport and targetport in webhook definition to create service properly * Adjust name of conversion func * Add some helpful comments * Correct correspond spelling Co-authored-by: Peter Brachwitz <[email protected]> * Don't preallocate, just define var Co-authored-by: Peter Brachwitz <[email protected]> * Remove pre-allocation of slices Co-authored-by: Peter Brachwitz <[email protected]>
1 parent b3f4ae2 commit d9bd0ee

File tree

2 files changed

+88
-22
lines changed

2 files changed

+88
-22
lines changed

hack/operatorhub/main.go

Lines changed: 80 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/Masterminds/sprig/v3"
2424
gyaml "github.com/ghodss/yaml"
2525
"github.com/spf13/cobra"
26+
admissionv1 "k8s.io/api/admissionregistration/v1"
2627
rbacv1 "k8s.io/api/rbac/v1"
2728
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
2829
apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
@@ -232,9 +233,26 @@ type CRD struct {
232233
Def []byte
233234
}
234235

236+
// WebhookDefinition corresponds to a WebhookDefinition within an OLM
237+
// ClusterServiceVersion.
238+
// See https://olm.operatorframework.io/docs/advanced-tasks/adding-admission-and-conversion-webhooks/
239+
type WebhookDefinition struct {
240+
AdmissionReviewVersions []string `json:"admissionReviewVersions"`
241+
ContainerPort int `json:"containerPort"`
242+
DeploymentName string `json:"deploymentName"`
243+
FailurePolicy *admissionv1.FailurePolicyType `json:"failurePolicy"`
244+
GenerateName string `json:"generateName"`
245+
Rules []admissionv1.RuleWithOperations `json:"rules"`
246+
SideEffects *admissionv1.SideEffectClass `json:"sideEffects"`
247+
TargetPort int `json:"targetPort"`
248+
Type string `json:"type"`
249+
WebhookPath *string `json:"webhookPath"`
250+
}
251+
235252
type yamlExtracts struct {
236-
crds map[string]*CRD
237-
operatorRBAC []rbacv1.PolicyRule
253+
crds map[string]*CRD
254+
operatorRBAC []rbacv1.PolicyRule
255+
operatorWebhooks []admissionv1.ValidatingWebhookConfiguration
238256
}
239257

240258
func extractYAMLParts(stream io.Reader) (*yamlExtracts, error) {
@@ -246,6 +264,10 @@ func extractYAMLParts(stream io.Reader) (*yamlExtracts, error) {
246264
return nil, fmt.Errorf("failed to register apiextensions/v1: %w", err)
247265
}
248266

267+
if err := admissionv1.AddToScheme(scheme.Scheme); err != nil {
268+
return nil, fmt.Errorf("failed to register admissionregistration/v1: %w", err)
269+
}
270+
249271
decoder := scheme.Codecs.UniversalDeserializer()
250272
yamlReader := yaml.NewYAMLReader(bufio.NewReader(stream))
251273

@@ -289,21 +311,24 @@ func extractYAMLParts(stream io.Reader) (*yamlExtracts, error) {
289311
if obj.Name == operatorName {
290312
parts.operatorRBAC = obj.Rules
291313
}
314+
case *admissionv1.ValidatingWebhookConfiguration:
315+
parts.operatorWebhooks = append(parts.operatorWebhooks, *obj)
292316
}
293317
}
294318
}
295319

296320
type RenderParams struct {
297-
NewVersion string
298-
ShortVersion string
299-
PrevVersion string
300-
StackVersion string
301-
OperatorRepo string
302-
OperatorRBAC string
303-
AdditionalArgs []string
304-
CRDList []*CRD
305-
PackageName string
306-
UbiOnly bool
321+
NewVersion string
322+
ShortVersion string
323+
PrevVersion string
324+
StackVersion string
325+
OperatorRepo string
326+
OperatorRBAC string
327+
AdditionalArgs []string
328+
CRDList []*CRD
329+
OperatorWebhooks string
330+
PackageName string
331+
UbiOnly bool
307332
}
308333

309334
func buildRenderParams(conf *config, packageIndex int, extracts *yamlExtracts) (*RenderParams, error) {
@@ -334,6 +359,17 @@ func buildRenderParams(conf *config, packageIndex int, extracts *yamlExtracts) (
334359
return crdList[i].Name <= crdList[j].Name
335360
})
336361

362+
var webhookDefinitionList []WebhookDefinition
363+
364+
for _, webhook := range extracts.operatorWebhooks {
365+
webhookDefinitionList = append(webhookDefinitionList, validatingWebhookConfigurationToWebhookDefinition(webhook)...)
366+
}
367+
368+
webhooks, err := gyaml.Marshal(webhookDefinitionList)
369+
if err != nil {
370+
return nil, fmt.Errorf("failed to marshal operator webhook rules: %w", err)
371+
}
372+
337373
versionParts := strings.Split(conf.NewVersion, ".")
338374
if len(versionParts) < 2 {
339375
return nil, fmt.Errorf("newVersion in config file appears to be invalid [%s]", conf.NewVersion)
@@ -352,19 +388,41 @@ func buildRenderParams(conf *config, packageIndex int, extracts *yamlExtracts) (
352388
additionalArgs = append(additionalArgs, "--distribution-channel="+conf.Packages[packageIndex].DistributionChannel)
353389

354390
return &RenderParams{
355-
NewVersion: conf.NewVersion,
356-
ShortVersion: strings.Join(versionParts[:2], "."),
357-
PrevVersion: conf.PrevVersion,
358-
StackVersion: conf.StackVersion,
359-
OperatorRepo: conf.Packages[packageIndex].OperatorRepo,
360-
AdditionalArgs: additionalArgs,
361-
CRDList: crdList,
362-
OperatorRBAC: string(rbac),
363-
PackageName: conf.Packages[packageIndex].PackageName,
364-
UbiOnly: conf.Packages[packageIndex].UbiOnly,
391+
NewVersion: conf.NewVersion,
392+
ShortVersion: strings.Join(versionParts[:2], "."),
393+
PrevVersion: conf.PrevVersion,
394+
StackVersion: conf.StackVersion,
395+
OperatorRepo: conf.Packages[packageIndex].OperatorRepo,
396+
AdditionalArgs: additionalArgs,
397+
CRDList: crdList,
398+
OperatorWebhooks: string(webhooks),
399+
OperatorRBAC: string(rbac),
400+
PackageName: conf.Packages[packageIndex].PackageName,
401+
UbiOnly: conf.Packages[packageIndex].UbiOnly,
365402
}, nil
366403
}
367404

405+
// validatingWebhookConfigurationToWebhookDefinition converts a standard validating webhook configuration resource
406+
// to an OLM webhook definition resource.
407+
func validatingWebhookConfigurationToWebhookDefinition(webhookConfiguration admissionv1.ValidatingWebhookConfiguration) []WebhookDefinition {
408+
var webhookDefinitions []WebhookDefinition
409+
for _, webhook := range webhookConfiguration.Webhooks {
410+
webhookDefinitions = append(webhookDefinitions, WebhookDefinition{
411+
Type: "ValidatingAdmissionWebhook",
412+
AdmissionReviewVersions: webhook.AdmissionReviewVersions,
413+
TargetPort: 9443,
414+
ContainerPort: 443,
415+
DeploymentName: "elastic-operator",
416+
FailurePolicy: webhook.FailurePolicy,
417+
GenerateName: webhook.Name,
418+
Rules: webhook.Rules,
419+
SideEffects: webhook.SideEffects,
420+
WebhookPath: webhook.ClientConfig.Service.Path,
421+
})
422+
}
423+
return webhookDefinitions
424+
}
425+
368426
func render(params *RenderParams, templatesDir, outDir string) error {
369427
versionDir := filepath.Join(outDir, params.NewVersion)
370428

hack/operatorhub/templates/csv.tpl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,8 @@ spec:
317317
args:
318318
- "manager"
319319
- "--config=/conf/eck.yaml"
320+
- "--manage-webhook-certs=false"
321+
- "--enable-webhook"
320322
{{- range .AdditionalArgs }}
321323
- "{{.}}"
322324
{{- end }}
@@ -338,6 +340,10 @@ spec:
338340
requests:
339341
cpu: 100m
340342
memory: 150Mi
343+
ports:
344+
- containerPort: 9443
345+
name: https-webhook
346+
protocol: TCP
341347
terminationGracePeriodSeconds: 10
342348
permissions:
343349
- rules:
@@ -372,3 +378,5 @@ spec:
372378
name: Elastic
373379
replaces: {{ .PackageName }}.v{{ .PrevVersion }}
374380
version: {{ .NewVersion }}
381+
webhookdefinitions:
382+
{{- .OperatorWebhooks | nindent 4 }}

0 commit comments

Comments
 (0)