@@ -3,15 +3,17 @@ package install
3
3
import (
4
4
"context"
5
5
"fmt"
6
+ "hash/fnv"
6
7
7
8
"github.com/operator-framework/api/pkg/operators/v1alpha1"
9
+ hashutil "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/util/hash"
8
10
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil"
9
11
10
12
log "github.com/sirupsen/logrus"
11
13
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
12
- k8serrors "k8s.io/apimachinery/pkg/api/errors"
13
14
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
14
15
"k8s.io/apimachinery/pkg/labels"
16
+ "k8s.io/apimachinery/pkg/util/rand"
15
17
)
16
18
17
19
func ValidWebhookRules (rules []admissionregistrationv1.RuleWithOperations ) error {
@@ -69,80 +71,115 @@ func (i *StrategyDeploymentInstaller) createOrUpdateWebhook(caPEM []byte, desc v
69
71
}
70
72
71
73
func (i * StrategyDeploymentInstaller ) createOrUpdateMutatingWebhook (ogNamespacelabelSelector * metav1.LabelSelector , caPEM []byte , desc v1alpha1.WebhookDescription ) error {
72
- webhooks := []admissionregistrationv1.MutatingWebhook {
73
- desc .GetMutatingWebhook (i .owner .GetNamespace (), ogNamespacelabelSelector , caPEM ),
74
- }
75
- existingHook , err := i .strategyClient .GetOpClient ().KubernetesInterface ().AdmissionregistrationV1 ().MutatingWebhookConfigurations ().Get (context .TODO (), desc .Name , metav1.GetOptions {})
76
- if err == nil {
77
- // Check if the only owners are this CSV or in this CSV's replacement chain
78
- if ownerutil .Adoptable (i .owner , existingHook .GetOwnerReferences ()) {
79
- ownerutil .AddNonBlockingOwner (existingHook , i .owner )
80
- }
74
+ webhookLabels := ownerutil .OwnerLabel (i .owner , i .owner .GetObjectKind ().GroupVersionKind ().Kind )
75
+ webhookLabels [WebhookLabelKey ] = HashWebhookDesc (desc )
76
+ webhookSelector := labels .SelectorFromSet (webhookLabels ).String ()
81
77
82
- // Update the list of webhooks
83
- existingHook .Webhooks = webhooks
78
+ existingWebhooks , err := i .strategyClient .GetOpClient ().KubernetesInterface ().AdmissionregistrationV1 ().MutatingWebhookConfigurations ().List (context .TODO (), metav1.ListOptions {LabelSelector : webhookSelector })
79
+ if err != nil {
80
+ return err
81
+ }
84
82
85
- // Attempt an update
86
- if _ , err := i .strategyClient .GetOpClient ().KubernetesInterface ().AdmissionregistrationV1 ().MutatingWebhookConfigurations ().Update (context .TODO (), existingHook , metav1.UpdateOptions {}); err != nil {
87
- log .Warnf ("could not update MutatingWebhookConfiguration %s" , existingHook .GetName ())
88
- return err
89
- }
90
- } else if k8serrors .IsNotFound (err ) {
83
+ if len (existingWebhooks .Items ) == 0 {
84
+ // Create a ValidatingWebhookConfiguration
91
85
hook := admissionregistrationv1.MutatingWebhookConfiguration {
92
- ObjectMeta : metav1.ObjectMeta {Name : desc .Name ,
93
- Namespace : i .owner .GetNamespace (),
86
+ ObjectMeta : metav1.ObjectMeta {
87
+ GenerateName : desc .Name + "-" ,
88
+ Namespace : i .owner .GetNamespace (),
89
+ Labels : ownerutil .OwnerLabel (i .owner , i .owner .GetObjectKind ().GroupVersionKind ().Kind ),
90
+ },
91
+ Webhooks : []admissionregistrationv1.MutatingWebhook {
92
+ desc .GetMutatingWebhook (i .owner .GetNamespace (), ogNamespacelabelSelector , caPEM ),
94
93
},
95
- Webhooks : webhooks ,
96
94
}
97
- // Add an owner
98
- ownerutil . AddNonBlockingOwner ( & hook , i . owner )
95
+ addWebhookLabels ( & hook , desc )
96
+
99
97
if _ , err := i .strategyClient .GetOpClient ().KubernetesInterface ().AdmissionregistrationV1 ().MutatingWebhookConfigurations ().Create (context .TODO (), & hook , metav1.CreateOptions {}); err != nil {
100
- log .Errorf ("Webhooks: Error creating mutating MutatingVebhookConfiguration : %v" , err )
98
+ log .Errorf ("Webhooks: Error creating ValidationWebhookConfiguration : %v" , err )
101
99
return err
102
100
}
103
101
} else {
104
- return err
105
- }
102
+ for _ , webhook := range existingWebhooks .Items {
103
+ // Update the list of webhooks
104
+ webhook .Webhooks = []admissionregistrationv1.MutatingWebhook {
105
+ desc .GetMutatingWebhook (i .owner .GetNamespace (), ogNamespacelabelSelector , caPEM ),
106
+ }
106
107
108
+ // Attempt an update
109
+ if _ , err := i .strategyClient .GetOpClient ().KubernetesInterface ().AdmissionregistrationV1 ().MutatingWebhookConfigurations ().Update (context .TODO (), & webhook , metav1.UpdateOptions {}); err != nil {
110
+ log .Warnf ("could not update MutatingWebhookConfiguration %s" , webhook .GetName ())
111
+ return err
112
+ }
113
+
114
+ }
115
+ }
107
116
return nil
108
117
}
109
118
110
119
func (i * StrategyDeploymentInstaller ) createOrUpdateValidatingWebhook (ogNamespacelabelSelector * metav1.LabelSelector , caPEM []byte , desc v1alpha1.WebhookDescription ) error {
111
- webhooks := []admissionregistrationv1.ValidatingWebhook {
112
- desc .GetValidatingWebhook (i .owner .GetNamespace (), ogNamespacelabelSelector , caPEM ),
113
- }
114
- existingHook , err := i .strategyClient .GetOpClient ().KubernetesInterface ().AdmissionregistrationV1 ().ValidatingWebhookConfigurations ().Get (context .TODO (), desc .Name , metav1.GetOptions {})
115
- if err == nil {
116
- // Check if the only owners are this CSV or in this CSV's replacement chain
117
- if ownerutil .Adoptable (i .owner , existingHook .GetOwnerReferences ()) {
118
- ownerutil .AddNonBlockingOwner (existingHook , i .owner )
119
- }
120
+ webhookLabels := ownerutil .OwnerLabel (i .owner , i .owner .GetObjectKind ().GroupVersionKind ().Kind )
121
+ webhookLabels [WebhookLabelKey ] = HashWebhookDesc (desc )
122
+ webhookSelector := labels .SelectorFromSet (webhookLabels ).String ()
120
123
121
- // Update the list of webhooks
122
- existingHook .Webhooks = webhooks
124
+ existingWebhooks , err := i .strategyClient .GetOpClient ().KubernetesInterface ().AdmissionregistrationV1 ().ValidatingWebhookConfigurations ().List (context .TODO (), metav1.ListOptions {LabelSelector : webhookSelector })
125
+ if err != nil {
126
+ return err
127
+ }
123
128
124
- // Attempt an update
125
- if _ , err := i .strategyClient .GetOpClient ().KubernetesInterface ().AdmissionregistrationV1 ().ValidatingWebhookConfigurations ().Update (context .TODO (), existingHook , metav1.UpdateOptions {}); err != nil {
126
- log .Warnf ("could not update ValidatingWebhookConfiguration %s" , existingHook .GetName ())
127
- return err
128
- }
129
- } else if k8serrors .IsNotFound (err ) {
129
+ if len (existingWebhooks .Items ) == 0 {
130
130
// Create a ValidatingWebhookConfiguration
131
131
hook := admissionregistrationv1.ValidatingWebhookConfiguration {
132
- ObjectMeta : metav1.ObjectMeta {Name : desc .Name ,
133
- Namespace : i .owner .GetNamespace (),
132
+ ObjectMeta : metav1.ObjectMeta {
133
+ GenerateName : desc .Name + "-" ,
134
+ Namespace : i .owner .GetNamespace (),
135
+ Labels : ownerutil .OwnerLabel (i .owner , i .owner .GetObjectKind ().GroupVersionKind ().Kind ),
136
+ },
137
+ Webhooks : []admissionregistrationv1.ValidatingWebhook {
138
+ desc .GetValidatingWebhook (i .owner .GetNamespace (), ogNamespacelabelSelector , caPEM ),
134
139
},
135
- Webhooks : webhooks ,
136
140
}
141
+ addWebhookLabels (& hook , desc )
137
142
138
- // Add an owner
139
- ownerutil .AddNonBlockingOwner (& hook , i .owner )
140
143
if _ , err := i .strategyClient .GetOpClient ().KubernetesInterface ().AdmissionregistrationV1 ().ValidatingWebhookConfigurations ().Create (context .TODO (), & hook , metav1.CreateOptions {}); err != nil {
141
- log .Errorf ("Webhooks: Error create creating ValidationVebhookConfiguration : %v" , err )
144
+ log .Errorf ("Webhooks: Error creating ValidatingWebhookConfiguration : %v" , err )
142
145
return err
143
146
}
144
147
} else {
145
- return err
148
+ for _ , webhook := range existingWebhooks .Items {
149
+
150
+ // Update the list of webhooks
151
+ webhook .Webhooks = []admissionregistrationv1.ValidatingWebhook {
152
+ desc .GetValidatingWebhook (i .owner .GetNamespace (), ogNamespacelabelSelector , caPEM ),
153
+ }
154
+
155
+ // Attempt an update
156
+ if _ , err := i .strategyClient .GetOpClient ().KubernetesInterface ().AdmissionregistrationV1 ().ValidatingWebhookConfigurations ().Update (context .TODO (), & webhook , metav1.UpdateOptions {}); err != nil {
157
+ log .Warnf ("could not update ValidatingWebhookConfiguration %s" , webhook .GetName ())
158
+ return err
159
+ }
160
+
161
+ }
146
162
}
147
163
return nil
148
164
}
165
+
166
+ const WebhookLabelKey = "webhookDescriptionSHA"
167
+
168
+ // addWebhookLabels adds webhook labels to an object
169
+ func addWebhookLabels (object metav1.Object , webhookDesc v1alpha1.WebhookDescription ) error {
170
+ labels := object .GetLabels ()
171
+ if labels == nil {
172
+ labels = map [string ]string {}
173
+ }
174
+ labels [WebhookLabelKey ] = HashWebhookDesc (webhookDesc )
175
+ object .SetLabels (labels )
176
+
177
+ return nil
178
+ }
179
+
180
+ // HashWebhookDesc calculates a hash given a webhookDescription
181
+ func HashWebhookDesc (webhookDesc v1alpha1.WebhookDescription ) string {
182
+ hasher := fnv .New32a ()
183
+ hashutil .DeepHashObject (hasher , & webhookDesc )
184
+ return rand .SafeEncodeString (fmt .Sprint (hasher .Sum32 ()))
185
+ }
0 commit comments