@@ -2,13 +2,24 @@ package e2e
2
2
3
3
import (
4
4
"context"
5
+ "os"
6
+ "path/filepath"
7
+ "strconv"
5
8
"time"
6
9
7
10
. "github.com/onsi/ginkgo"
8
11
. "github.com/onsi/gomega"
9
-
12
+ apiv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
13
+ "k8s.io/apimachinery/pkg/api/errors"
10
14
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
11
-
15
+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
16
+ "k8s.io/apimachinery/pkg/runtime"
17
+ "k8s.io/apimachinery/pkg/runtime/serializer"
18
+ "k8s.io/kubectl/pkg/util"
19
+ "k8s.io/utils/pointer"
20
+
21
+ "github.com/openservicemesh/osm/pkg/constants"
22
+ "github.com/openservicemesh/osm/pkg/reconciler"
12
23
. "github.com/openservicemesh/osm/tests/framework"
13
24
)
14
25
@@ -106,7 +117,7 @@ var _ = OSMDescribe("Test OSM Reconciler",
106
117
Eventually (func () (string , error ) {
107
118
updatedVwhc , err := Td .Client .AdmissionregistrationV1 ().ValidatingWebhookConfigurations ().Get (context .Background (), "osm-validator-mesh-osm" , metav1.GetOptions {})
108
119
return updatedVwhc .Webhooks [0 ].ClientConfig .Service .Name , err
109
- }, 3 * time .Second ).Should (Equal (originalWebhookServiceName ))
120
+ }, 30 * time .Second ).Should (Equal (originalWebhookServiceName ))
110
121
111
122
// delete the validating webhook
112
123
err = Td .Client .AdmissionregistrationV1 ().ValidatingWebhookConfigurations ().Delete (context .Background (), "osm-validator-mesh-osm" , metav1.DeleteOptions {})
@@ -116,7 +127,107 @@ var _ = OSMDescribe("Test OSM Reconciler",
116
127
Eventually (func () error {
117
128
_ , err = Td .Client .AdmissionregistrationV1 ().ValidatingWebhookConfigurations ().Get (context .Background (), "osm-validator-mesh-osm" , metav1.GetOptions {})
118
129
return err
119
- }, 3 * time .Second ).Should (BeNil ())
130
+ }, 30 * time .Second ).Should (BeNil ())
131
+ })
132
+ })
133
+
134
+ Context ("Pre-existing reconciler with CRD conversion webhook change" , func () {
135
+ It ("Retries until CRD change is detected 3 times, waiting for 5 seconds each time" , func () {
136
+ // Install CRDs with a conversion webhook
137
+ crdFiles , err := filepath .Glob ("../../cmd/osm-bootstrap/crds/*.yaml" )
138
+
139
+ Expect (err ).NotTo (HaveOccurred ())
140
+
141
+ scheme := runtime .NewScheme ()
142
+ codecs := serializer .NewCodecFactory (scheme )
143
+ decode := codecs .UniversalDeserializer ().Decode
144
+
145
+ for _ , file := range crdFiles {
146
+ yaml , err := os .ReadFile (filepath .Clean (file ))
147
+ if err != nil {
148
+ Expect (err ).NotTo (HaveOccurred ())
149
+ }
150
+
151
+ crd := & apiv1.CustomResourceDefinition {}
152
+ _ , _ , err = decode (yaml , nil , crd )
153
+ if err != nil {
154
+ Expect (err ).NotTo (HaveOccurred ())
155
+ }
156
+
157
+ // imitate older version of OSM who set the reconcile label to a (stringified) bool
158
+ crd .Labels [constants .ReconcileLabel ] = strconv .FormatBool (true )
159
+
160
+ crd .Spec .Conversion = & apiv1.CustomResourceConversion {
161
+ Strategy : apiv1 .WebhookConverter ,
162
+ Webhook : & apiv1.WebhookConversion {
163
+ ClientConfig : & apiv1.WebhookClientConfig {
164
+ Service : & apiv1.ServiceReference {
165
+ Namespace : "osm-system" ,
166
+ Name : "osm-bootstrap" ,
167
+ Path : pointer .StringPtr ("/convert" ),
168
+ Port : pointer .Int32Ptr (9443 ),
169
+ },
170
+ },
171
+ ConversionReviewVersions : []string {"v1alpha1" , "v1alpha2" , "v1alpha3" , "v1beta1" , "v1" },
172
+ },
173
+ }
174
+
175
+ err = util .CreateApplyAnnotation (crd , unstructured .UnstructuredJSONScheme )
176
+ Expect (err ).NotTo (HaveOccurred ())
177
+
178
+ _ , err = Td .APIServerClient .ApiextensionsV1 ().CustomResourceDefinitions ().Create (context .Background (), crd , metav1.CreateOptions {})
179
+ if errors .IsAlreadyExists (err ) {
180
+ existingCRD , err := Td .APIServerClient .ApiextensionsV1 ().CustomResourceDefinitions ().Get (context .Background (), "meshconfigs.config.openservicemesh.io" , metav1.GetOptions {})
181
+ Expect (err ).NotTo (HaveOccurred ())
182
+ existingCRD .Spec .Conversion = crd .Spec .Conversion
183
+ existingCRD .Labels [constants .ReconcileLabel ] = strconv .FormatBool (true )
184
+ _ , err = Td .APIServerClient .ApiextensionsV1 ().CustomResourceDefinitions ().Update (context .Background (), existingCRD , metav1.UpdateOptions {})
185
+ Expect (err ).NotTo (HaveOccurred ())
186
+ } else {
187
+ Expect (err ).NotTo (HaveOccurred ())
188
+ }
189
+ }
190
+ // Add existing reconciler to watch the cluster
191
+ _ , cancel := context .WithCancel (context .Background ())
192
+ defer cancel ()
193
+ stop := make (chan struct {})
194
+ Expect (err ).NotTo (HaveOccurred ())
195
+
196
+ // The current reconciler code matches the version to the label value, which is a stringified bool
197
+ err = reconciler .NewReconcilerClient (Td .Client , Td .APIServerClient , "osm" , "true" , stop , reconciler .CrdInformerKey )
198
+ Expect (err ).NotTo (HaveOccurred ())
199
+
200
+ // Confirm that the CRD conversion webhook is set to WebhookConverter
201
+ crd , err := Td .APIServerClient .ApiextensionsV1 ().CustomResourceDefinitions ().Get (context .Background (), "meshconfigs.config.openservicemesh.io" , metav1.GetOptions {})
202
+ Expect (err ).NotTo (HaveOccurred ())
203
+ Expect (crd .Spec .Conversion .Strategy ).To (Equal (apiv1 .WebhookConverter ))
204
+
205
+ // Install OSM with reconciler enabled
206
+ installOpts := Td .GetOSMInstallOpts ()
207
+ installOpts .EnableReconciler = true
208
+ Expect (Td .InstallOSM (installOpts )).To (Succeed ())
209
+
210
+ Eventually (func () int {
211
+ // Make sure the CRD conversion webhook is set to NoneConverter 3 times in a row
212
+ var attempts int
213
+ for i := 0 ; i < 3 ; attempts ++ {
214
+ if attempts >= 30 { // Gomega doesn't stop the function at the timeout, so prevent an infinite loop
215
+ break
216
+ }
217
+ crd , err := Td .APIServerClient .ApiextensionsV1 ().CustomResourceDefinitions ().Get (context .Background (), "meshconfigs.config.openservicemesh.io" , metav1.GetOptions {})
218
+ Expect (err ).NotTo (HaveOccurred ())
219
+ if crd .Spec .Conversion .Strategy == apiv1 .NoneConverter {
220
+ i ++
221
+ } else {
222
+ i = 0
223
+ }
224
+ time .Sleep (500 * time .Millisecond )
225
+ }
226
+ return attempts
227
+ }, 15 * time .Second ).Should (BeNumerically ("<" , 30 ))
228
+
229
+ // Stop the first reconciler (simulate the OSM upgrade completion)
230
+ close (stop )
120
231
})
121
232
})
122
233
})
0 commit comments