4
4
"encoding/json"
5
5
"fmt"
6
6
"sort"
7
+ "strings"
8
+
9
+ admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
7
10
8
11
appsv1 "k8s.io/api/apps/v1"
9
12
rbac "k8s.io/api/rbac/v1"
@@ -148,6 +151,87 @@ func (d APIServiceDescription) GetName() string {
148
151
return fmt .Sprintf ("%s.%s" , d .Version , d .Group )
149
152
}
150
153
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
+
151
235
// CustomResourceDefinitions declares all of the CRDs managed or required by
152
236
// an operator being ran by ClusterServiceVersion.
153
237
//
@@ -174,6 +258,7 @@ type ClusterServiceVersionSpec struct {
174
258
Maturity string `json:"maturity,omitempty"`
175
259
CustomResourceDefinitions CustomResourceDefinitions `json:"customresourcedefinitions,omitempty"`
176
260
APIServiceDefinitions APIServiceDefinitions `json:"apiservicedefinitions,omitempty"`
261
+ WebhookDefinitions []WebhookDescription `json:"webhookdefinitions,omitempty"`
177
262
NativeAPIs []metav1.GroupVersionKind `json:"nativeAPIs,omitempty"`
178
263
MinKubeVersion string `json:"minKubeVersion,omitempty"`
179
264
DisplayName string `json:"displayName"`
@@ -280,8 +365,18 @@ const (
280
365
CSVReasonInterOperatorGroupOwnerConflict ConditionReason = "InterOperatorGroupOwnerConflict"
281
366
CSVReasonCannotModifyStaticOperatorGroupProvidedAPIs ConditionReason = "CannotModifyStaticOperatorGroupProvidedAPIs"
282
367
CSVReasonDetectedClusterChange ConditionReason = "DetectedClusterChange"
368
+ CSVReasonUnsupportedWebhookRules ConditionReason = "UnsupportedWebhookRules"
283
369
)
284
370
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
+
285
380
// Conditions appear in the status as a record of state transitions on the ClusterServiceVersion
286
381
type ClusterServiceVersionCondition struct {
287
382
// Condition of the ClusterServiceVersion
0 commit comments