@@ -28,15 +28,20 @@ import (
28
28
"os/exec"
29
29
"strconv"
30
30
"strings"
31
+ "time"
31
32
33
+ "github.com/go-logr/logr"
32
34
corev1 "k8s.io/api/core/v1"
35
+ apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
36
+ "k8s.io/apimachinery/pkg/api/errors"
33
37
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
34
38
"k8s.io/apimachinery/pkg/runtime"
35
39
"k8s.io/apimachinery/pkg/types"
36
40
"k8s.io/client-go/kubernetes"
37
41
"k8s.io/client-go/rest"
38
42
"k8s.io/client-go/tools/clientcmd"
39
43
"k8s.io/client-go/tools/remotecommand"
44
+ "sigs.k8s.io/controller-runtime/pkg/client"
40
45
)
41
46
42
47
const (
@@ -207,3 +212,138 @@ func NewConfig() (*rest.Config, error) {
207
212
return clientcmd .NewNonInteractiveDeferredLoadingClientConfig (
208
213
loader , & clientcmd.ConfigOverrides {}).ClientConfig ()
209
214
}
215
+
216
+ func UpdateforCRD (crdName string , cli client.Client , log * logr.Logger ) error {
217
+ // TODO: update CRD
218
+
219
+ // MYNS=extension-dmp
220
+ // CRD1=mysqlclusters.mysql.radondb.com
221
+ // CRD2=backups.mysql.radondb.com
222
+ // SEC=radondb-mysql-webhook-certs
223
+ // CERT=$(kubectl -n $MYNS get secrets $SEC -ojsonpath='{.data.tls\.crt}')
224
+ // kubectl patch CustomResourceDefinition $CRD1 --type=merge -p '{"spec":{"conversion":{"webhook":{"clientConfig":{"caBundle":"'$CERT'","service":{"namespace":"'$MYNS'"}}}}}}'
225
+ // kubectl patch CustomResourceDefinition $CRD2 --type=merge -p '{"spec":{"conversion":{"webhook":{"clientConfig":{"caBundle":"'$CERT'","service":{"namespace":"'$MYNS'"}}}}}}'
226
+ // echo $CERT
227
+ // fetch a secret in dmp-extension namespace which is named radondb-mysql-webhook-certs
228
+ // 1. first get os environment value MY_NAMESPACE, if not set, use default namespace ,"dmp-extension"
229
+ ctx , cancel := context .WithTimeout (context .Background (), 5 * time .Second )
230
+ defer cancel ()
231
+ ns := os .Getenv ("MY_NAMESPACE" )
232
+ if len (ns ) == 0 {
233
+ ns = "extension-dmp"
234
+ }
235
+ //2. get os environment value CERT_NAME, if not set, use default namespace "radondb-mysql-webhook-certs"
236
+ certName := os .Getenv ("CERT_NAME" )
237
+ if len (certName ) == 0 {
238
+ certName = "radondb-mysql-webhook-certs"
239
+ }
240
+ secret := & corev1.Secret {
241
+ TypeMeta : metav1.TypeMeta {
242
+ Kind : "Secret" ,
243
+ APIVersion : "v1" ,
244
+ },
245
+ ObjectMeta : metav1.ObjectMeta {
246
+ Name : certName ,
247
+ Namespace : ns ,
248
+ },
249
+ }
250
+ err := cli .Get (ctx , types.NamespacedName {Name : secret .Name , Namespace : secret .Namespace }, secret )
251
+ // if err is not found, return error
252
+ if errors .IsNotFound (err ) {
253
+ return fmt .Errorf ("secret %s not found" , certName )
254
+ }
255
+ cert := secret .Data ["tls.crt" ]
256
+
257
+ //fetch the CustomResourceDefinition ,which name is mysqlclusters.mysql.radondb.com
258
+ // 创建 CRD 实例
259
+ //apiextensionsv1.AddToScheme(scheme)
260
+ //CustomResourceDefinition
261
+ crd := & apiextensionsv1.CustomResourceDefinition {
262
+ TypeMeta : metav1.TypeMeta {
263
+ APIVersion : "v1" ,
264
+ Kind : "CustomResourceDefinition" ,
265
+ },
266
+ ObjectMeta : metav1.ObjectMeta {
267
+ Name : crdName ,
268
+ },
269
+ }
270
+ // 使用客户端获取 CRD 资源
271
+ errCRD := cli .Get (ctx , types.NamespacedName {Name : crdName }, crd )
272
+ if errCRD != nil {
273
+ return errCRD
274
+ }
275
+ hasBetaVersion := false
276
+ for _ , v := range crd .Spec .Versions {
277
+ if v .Name == "v1beta1" {
278
+ hasBetaVersion = true
279
+ }
280
+ }
281
+ if ! hasBetaVersion {
282
+ return fmt .Errorf ("has not v1beta1 version" )
283
+ }
284
+
285
+ oldCrd := crd .DeepCopy ()
286
+ // if CustomResourceConversion's CABundle of Webhook is not equal to cert, update it
287
+ // sometime the path and port are missing, I don't know why
288
+ if oldCrd .Spec .Conversion == nil || oldCrd .Spec .Conversion .Webhook == nil || oldCrd .Spec .Conversion .Webhook .ClientConfig == nil ||
289
+ oldCrd .Spec .Conversion .Webhook .ClientConfig .CABundle == nil ||
290
+ oldCrd .Spec .Conversion .Webhook .ClientConfig .Service .Path == nil ||
291
+ oldCrd .Spec .Conversion .Webhook .ClientConfig .Service .Port == nil ||
292
+ ! bytes .Equal (oldCrd .Spec .Conversion .Webhook .ClientConfig .CABundle , cert ) {
293
+ crd .Spec .Conversion = & apiextensionsv1.CustomResourceConversion {
294
+ Strategy : apiextensionsv1 .WebhookConverter ,
295
+ Webhook : & apiextensionsv1.WebhookConversion {
296
+ ClientConfig : & apiextensionsv1.WebhookClientConfig {
297
+ CABundle : []byte (cert ),
298
+ Service : & apiextensionsv1.ServiceReference {
299
+ Namespace : ns ,
300
+ Name : func () string {
301
+ if oldCrd .Spec .Conversion != nil && oldCrd .Spec .Conversion .Webhook != nil && oldCrd .Spec .Conversion .Webhook .ClientConfig != nil {
302
+ return oldCrd .Spec .Conversion .Webhook .ClientConfig .Service .Name
303
+ } else {
304
+ return "radondb-mysql-webhook"
305
+ }
306
+ }(),
307
+ Path : func () * string {
308
+ var p string = "/convert"
309
+ return & p
310
+ }(),
311
+ Port : func () * int32 {
312
+ var serverPort int32 = 443
313
+ return & serverPort
314
+ }(),
315
+ },
316
+ },
317
+ ConversionReviewVersions : []string {"v1" },
318
+ },
319
+ }
320
+ log .Info ("covert crd" , "value" , crd .Spec .Conversion )
321
+ } else {
322
+ return nil
323
+ }
324
+ errCRD = cli .Patch (ctx , crd , client .MergeFrom (oldCrd ))
325
+ if errCRD != nil {
326
+ return errCRD
327
+ }
328
+
329
+ return nil
330
+ }
331
+
332
+ func RunUpdeteCRD (cli client.Client , log * logr.Logger ) {
333
+ go func () {
334
+ // Just run in the first 500 seconds,almost eight minutes, because the crd webhook's CABundle is not correct just in the DMP reinstall period
335
+ // if this process failed, just need to restart the operetor pod
336
+ for i := 0 ; i < 100 ; i ++ {
337
+ time .Sleep (time .Second * 5 )
338
+ err := UpdateforCRD ("mysqlclusters.mysql.radondb.com" , cli , log )
339
+ if err != nil {
340
+ log .Info ("update CRD failed" , "error" , err )
341
+ }
342
+ err = UpdateforCRD ("backups.mysql.radondb.com" , cli , log )
343
+ if err != nil {
344
+ log .Info ("update CRD failed" , "error" , err )
345
+ }
346
+ }
347
+ log .Info ("check the crd about 8 minutes, now exit." )
348
+ }()
349
+ }
0 commit comments