Skip to content

Commit 6acca52

Browse files
awgreenenjhale
authored andcommitted
Update OG and CSV for Webhooks
1 parent 8a0d74f commit 6acca52

File tree

5 files changed

+340
-8
lines changed

5 files changed

+340
-8
lines changed

crds/operators.coreos.com_clusterserviceversions.yaml

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8374,6 +8374,148 @@ spec:
83748374
description: OperatorVersion is a wrapper around semver.Version which
83758375
supports correct marshaling to YAML and JSON.
83768376
type: string
8377+
webhookdefinitions:
8378+
type: array
8379+
items:
8380+
description: WebhookDescription provides details to OLM about required
8381+
webhooks
8382+
type: object
8383+
required:
8384+
- admissionReviewVersions
8385+
- name
8386+
- sideEffects
8387+
- type
8388+
properties:
8389+
admissionReviewVersions:
8390+
type: array
8391+
items:
8392+
type: string
8393+
containerPort:
8394+
type: integer
8395+
format: int32
8396+
deploymentName:
8397+
type: string
8398+
failurePolicy:
8399+
type: string
8400+
matchPolicy:
8401+
description: MatchPolicyType specifies the type of match policy
8402+
type: string
8403+
name:
8404+
type: string
8405+
objectSelector:
8406+
description: A label selector is a label query over a set of resources.
8407+
The result of matchLabels and matchExpressions are ANDed. An
8408+
empty label selector matches all objects. A null label selector
8409+
matches no objects.
8410+
type: object
8411+
properties:
8412+
matchExpressions:
8413+
description: matchExpressions is a list of label selector
8414+
requirements. The requirements are ANDed.
8415+
type: array
8416+
items:
8417+
description: A label selector requirement is a selector
8418+
that contains values, a key, and an operator that relates
8419+
the key and values.
8420+
type: object
8421+
required:
8422+
- key
8423+
- operator
8424+
properties:
8425+
key:
8426+
description: key is the label key that the selector
8427+
applies to.
8428+
type: string
8429+
operator:
8430+
description: operator represents a key's relationship
8431+
to a set of values. Valid operators are In, NotIn,
8432+
Exists and DoesNotExist.
8433+
type: string
8434+
values:
8435+
description: values is an array of string values. If
8436+
the operator is In or NotIn, the values array must
8437+
be non-empty. If the operator is Exists or DoesNotExist,
8438+
the values array must be empty. This array is replaced
8439+
during a strategic merge patch.
8440+
type: array
8441+
items:
8442+
type: string
8443+
matchLabels:
8444+
description: matchLabels is a map of {key,value} pairs. A
8445+
single {key,value} in the matchLabels map is equivalent
8446+
to an element of matchExpressions, whose key field is "key",
8447+
the operator is "In", and the values array contains only
8448+
"value". The requirements are ANDed.
8449+
type: object
8450+
additionalProperties:
8451+
type: string
8452+
reinvocationPolicy:
8453+
description: ReinvocationPolicyType specifies what type of policy
8454+
the admission hook uses.
8455+
type: string
8456+
rules:
8457+
type: array
8458+
items:
8459+
description: RuleWithOperations is a tuple of Operations and
8460+
Resources. It is recommended to make sure that all the tuple
8461+
expansions are valid.
8462+
type: object
8463+
properties:
8464+
apiGroups:
8465+
description: APIGroups is the API groups the resources belong
8466+
to. '*' is all groups. If '*' is present, the length of
8467+
the slice must be one. Required.
8468+
type: array
8469+
items:
8470+
type: string
8471+
apiVersions:
8472+
description: APIVersions is the API versions the resources
8473+
belong to. '*' is all versions. If '*' is present, the
8474+
length of the slice must be one. Required.
8475+
type: array
8476+
items:
8477+
type: string
8478+
operations:
8479+
description: Operations is the operations the admission
8480+
hook cares about - CREATE, UPDATE, or * for all operations.
8481+
If '*' is present, the length of the slice must be one.
8482+
Required.
8483+
type: array
8484+
items:
8485+
type: string
8486+
resources:
8487+
description: "Resources is a list of resources this rule
8488+
applies to. \n For example: 'pods' means pods. 'pods/log'
8489+
means the log subresource of pods. '*' means all resources,
8490+
but not subresources. 'pods/*' means all subresources
8491+
of pods. '*/scale' means all scale subresources. '*/*'
8492+
means all resources and their subresources. \n If wildcard
8493+
is present, the validation rule will ensure resources
8494+
do not overlap with each other. \n Depending on the enclosing
8495+
object, subresources might not be allowed. Required."
8496+
type: array
8497+
items:
8498+
type: string
8499+
scope:
8500+
description: scope specifies the scope of this rule. Valid
8501+
values are "Cluster", "Namespaced", and "*" "Cluster"
8502+
means that only cluster-scoped resources will match this
8503+
rule. Namespace API objects are cluster-scoped. "Namespaced"
8504+
means that only namespaced resources will match this rule.
8505+
"*" means that there are no scope restrictions. Subresources
8506+
match the scope of their parent resource. Default is "*".
8507+
type: string
8508+
sideEffects:
8509+
type: string
8510+
timeoutSeconds:
8511+
type: integer
8512+
format: int32
8513+
type:
8514+
description: WebhookAdmissionType is the type of admission webhooks
8515+
supported by OLM
8516+
type: string
8517+
webhookPath:
8518+
type: string
83778519
status:
83788520
description: ClusterServiceVersionStatus represents information about the
83798521
status of a pod. Status may trail the actual state of a system.

crds/zz_defs.go

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/operators/v1/operatorgroup_types.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,32 @@ func (o *OperatorGroup) HasServiceAccountSynced() bool {
108108
// GetLabel returns a label that is applied to Namespaces to signify that the
109109
// namespace is a part of the OperatorGroup using selectors.
110110
func (o *OperatorGroup) GetLabel() string {
111-
return fmt.Sprintf(OperatorGroupLabelTemplate, o.GetNamespace(), o.GetName())
111+
key, _ := o.OGLabelKeyAndValue()
112+
return key
113+
}
114+
115+
// OGLabelKeyAndValue returns a key and value that should be applied to namespaces listed in the OperatorGroup.
116+
func (o *OperatorGroup) OGLabelKeyAndValue() (string, string) {
117+
return fmt.Sprintf(OperatorGroupLabelTemplate, o.GetNamespace(), o.GetName()), ""
118+
}
119+
120+
// NamespaceLabelSelector provides a selector that can be used to filter namespaces that belong to the OperatorGroup.
121+
func (o *OperatorGroup) NamespaceLabelSelector() *metav1.LabelSelector {
122+
if len(o.Spec.TargetNamespaces) == 0 {
123+
// If no target namespaces are set, check if a selector exists.
124+
if o.Spec.Selector != nil {
125+
return o.Spec.Selector
126+
}
127+
// No selector exists, return nil which should be used to select EVERYTHING.
128+
return nil
129+
}
130+
// Return a label that should be present on all namespaces defined in the OperatorGroup.Spec.TargetNamespaces field.
131+
ogKey, ogValue := o.OGLabelKeyAndValue()
132+
return &metav1.LabelSelector{
133+
MatchLabels: map[string]string{
134+
ogKey: ogValue,
135+
},
136+
}
112137
}
113138

114139
// IsOperatorGroupLabel returns true if the label is an OperatorGroup label.

pkg/operators/v1alpha1/clusterserviceversion_types.go

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import (
44
"encoding/json"
55
"fmt"
66
"sort"
7+
"strings"
8+
9+
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
710

811
appsv1 "k8s.io/api/apps/v1"
912
rbac "k8s.io/api/rbac/v1"
@@ -148,6 +151,87 @@ func (d APIServiceDescription) GetName() string {
148151
return fmt.Sprintf("%s.%s", d.Version, d.Group)
149152
}
150153

154+
// WebhookAdmissionType is the type of admission webhooks supported by OLM
155+
type WebhookAdmissionType string
156+
157+
const (
158+
// ValidatingAdmissionWebhook is for validating admission webhooks
159+
ValidatingAdmissionWebhook WebhookAdmissionType = "ValidatingAdmissionWebhook"
160+
// MutatingAdmissionWebhook is for mutating admission webhooks
161+
MutatingAdmissionWebhook WebhookAdmissionType = "MutatingAdmissionWebhook"
162+
)
163+
164+
// WebhookDescription provides details to OLM about required webhooks
165+
// +k8s:openapi-gen=true
166+
type WebhookDescription struct {
167+
Name string `json:"name"`
168+
Type WebhookAdmissionType `json:"type"`
169+
DeploymentName string `json:"deploymentName,omitempty"`
170+
ContainerPort int32 `json:"containerPort,omitempty"`
171+
Rules []admissionregistrationv1.RuleWithOperations `json:"rules,omitempty"`
172+
FailurePolicy *admissionregistrationv1.FailurePolicyType `json:"failurePolicy,omitempty"`
173+
MatchPolicy *admissionregistrationv1.MatchPolicyType `json:"matchPolicy,omitempty"`
174+
ObjectSelector *metav1.LabelSelector `json:"objectSelector,omitempty"`
175+
SideEffects *admissionregistrationv1.SideEffectClass `json:"sideEffects"`
176+
TimeoutSeconds *int32 `json:"timeoutSeconds,omitempty"`
177+
AdmissionReviewVersions []string `json:"admissionReviewVersions"`
178+
ReinvocationPolicy *admissionregistrationv1.ReinvocationPolicyType `json:"reinvocationPolicy,omitempty"`
179+
WebhookPath *string `json:"webhookPath,omitempty"`
180+
}
181+
182+
// GetValidatingWebhook returns a ValidatingWebhook generated from the WebhookDescription
183+
func (w *WebhookDescription) GetValidatingWebhook(namespace string, namespaceSelector *metav1.LabelSelector, caBundle []byte) admissionregistrationv1.ValidatingWebhook {
184+
return admissionregistrationv1.ValidatingWebhook{
185+
Name: w.Name,
186+
Rules: w.Rules,
187+
FailurePolicy: w.FailurePolicy,
188+
MatchPolicy: w.MatchPolicy,
189+
NamespaceSelector: namespaceSelector,
190+
ObjectSelector: w.ObjectSelector,
191+
SideEffects: w.SideEffects,
192+
TimeoutSeconds: w.TimeoutSeconds,
193+
AdmissionReviewVersions: w.AdmissionReviewVersions,
194+
ClientConfig: admissionregistrationv1.WebhookClientConfig{
195+
Service: &admissionregistrationv1.ServiceReference{
196+
Name: w.DomainName() + "-service",
197+
Namespace: namespace,
198+
Path: w.WebhookPath,
199+
},
200+
CABundle: caBundle,
201+
},
202+
}
203+
}
204+
205+
// GetMutatingWebhook returns a MutatingWebhook generated from the WebhookDescription
206+
func (w *WebhookDescription) GetMutatingWebhook(namespace string, namespaceSelector *metav1.LabelSelector, caBundle []byte) admissionregistrationv1.MutatingWebhook {
207+
return admissionregistrationv1.MutatingWebhook{
208+
Name: w.Name,
209+
Rules: w.Rules,
210+
FailurePolicy: w.FailurePolicy,
211+
MatchPolicy: w.MatchPolicy,
212+
NamespaceSelector: namespaceSelector,
213+
ObjectSelector: w.ObjectSelector,
214+
SideEffects: w.SideEffects,
215+
TimeoutSeconds: w.TimeoutSeconds,
216+
AdmissionReviewVersions: w.AdmissionReviewVersions,
217+
ClientConfig: admissionregistrationv1.WebhookClientConfig{
218+
Service: &admissionregistrationv1.ServiceReference{
219+
Name: w.DomainName() + "-service",
220+
Namespace: namespace,
221+
Path: w.WebhookPath,
222+
},
223+
CABundle: caBundle,
224+
},
225+
ReinvocationPolicy: w.ReinvocationPolicy,
226+
}
227+
}
228+
229+
// DomainName returns the result of replacing all periods in the given Webhook name with hyphens
230+
func (w *WebhookDescription) DomainName() string {
231+
// Replace all '.'s with "-"s to convert to a DNS-1035 label
232+
return strings.Replace(w.DeploymentName, ".", "-", -1)
233+
}
234+
151235
// CustomResourceDefinitions declares all of the CRDs managed or required by
152236
// an operator being ran by ClusterServiceVersion.
153237
//
@@ -174,6 +258,7 @@ type ClusterServiceVersionSpec struct {
174258
Maturity string `json:"maturity,omitempty"`
175259
CustomResourceDefinitions CustomResourceDefinitions `json:"customresourcedefinitions,omitempty"`
176260
APIServiceDefinitions APIServiceDefinitions `json:"apiservicedefinitions,omitempty"`
261+
WebhookDefinitions []WebhookDescription `json:"webhookdefinitions,omitempty"`
177262
NativeAPIs []metav1.GroupVersionKind `json:"nativeAPIs,omitempty"`
178263
MinKubeVersion string `json:"minKubeVersion,omitempty"`
179264
DisplayName string `json:"displayName"`
@@ -280,8 +365,18 @@ const (
280365
CSVReasonInterOperatorGroupOwnerConflict ConditionReason = "InterOperatorGroupOwnerConflict"
281366
CSVReasonCannotModifyStaticOperatorGroupProvidedAPIs ConditionReason = "CannotModifyStaticOperatorGroupProvidedAPIs"
282367
CSVReasonDetectedClusterChange ConditionReason = "DetectedClusterChange"
368+
CSVReasonUnsupportedWebhookRules ConditionReason = "UnsupportedWebhookRules"
283369
)
284370

371+
// HasCaResources returns true if the CSV has owned APIServices or Webhooks.
372+
func (c *ClusterServiceVersion) HasCAResources() bool {
373+
// Return early if there are no owned APIServices
374+
if len(c.Spec.APIServiceDefinitions.Owned)+len(c.Spec.WebhookDefinitions) == 0 {
375+
return false
376+
}
377+
return true
378+
}
379+
285380
// Conditions appear in the status as a record of state transitions on the ClusterServiceVersion
286381
type ClusterServiceVersionCondition struct {
287382
// Condition of the ClusterServiceVersion

pkg/operators/v1alpha1/zz_generated.deepcopy.go

Lines changed: 70 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)