-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcrd_controller.go
98 lines (86 loc) · 2.77 KB
/
crd_controller.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package controller
import (
"bytes"
"context"
"fmt"
"github.com/openmfp/kubernetes-graphql-gateway/listener/apischema"
"github.com/openmfp/kubernetes-graphql-gateway/listener/workspacefile"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
)
// CRDReconciler reconciles a CustomResourceDefinition object
type CRDReconciler struct {
ClusterName string
client.Client
*apischema.CRDResolver
io *workspacefile.IOHandler
}
func NewCRDReconciler(name string,
clt client.Client,
cr *apischema.CRDResolver,
io *workspacefile.IOHandler,
) *CRDReconciler {
return &CRDReconciler{
ClusterName: name,
Client: clt,
CRDResolver: cr,
io: io,
}
}
func (r *CRDReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
logger := log.FromContext(ctx).WithValues("cluster", r.ClusterName).WithName(req.Name)
logger.Info("starting reconciliation...")
crd := &apiextensionsv1.CustomResourceDefinition{}
err := r.Client.Get(ctx, req.NamespacedName, crd)
if apierrors.IsNotFound(err) {
logger.Info("resource not found, updating schema...")
return ctrl.Result{}, r.updateAPISchema()
}
if client.IgnoreNotFound(err) != nil {
logger.Error(err, "failed to get reconciled object")
return ctrl.Result{}, err
}
return ctrl.Result{}, r.updateAPISchemaWith(crd)
}
// SetupWithManager sets up the controller with the Manager.
func (r *CRDReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&apiextensionsv1.CustomResourceDefinition{}).
Named("CRD").
Complete(r)
}
func (r *CRDReconciler) updateAPISchema() error {
savedJSON, err := r.io.Read(r.ClusterName)
if err != nil {
return fmt.Errorf("failed to read JSON from filesystem: %w", err)
}
actualJSON, err := r.Resolve()
if err != nil {
return fmt.Errorf("failed to resolve server JSON schema: %w", err)
}
if !bytes.Equal(actualJSON, savedJSON) {
if err := r.io.Write(actualJSON, r.ClusterName); err != nil {
return fmt.Errorf("failed to write JSON to filesystem: %w", err)
}
}
return nil
}
func (r *CRDReconciler) updateAPISchemaWith(crd *apiextensionsv1.CustomResourceDefinition) error {
savedJSON, err := r.io.Read(r.ClusterName)
if err != nil {
return fmt.Errorf("failed to read JSON from filesystem: %w", err)
}
actualJSON, err := r.ResolveApiSchema(crd)
if err != nil {
return fmt.Errorf("failed to resolve server JSON schema: %w", err)
}
if !bytes.Equal(actualJSON, savedJSON) {
if err := r.io.Write(actualJSON, r.ClusterName); err != nil {
return fmt.Errorf("failed to write JSON to filesystem: %w", err)
}
}
return nil
}