generated from vshn/go-bootstrap
/
configmap_controller.go
122 lines (104 loc) · 3.5 KB
/
configmap_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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/*
Copyright 2022.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package controllers
import (
"context"
"reflect"
"strconv"
"github.com/projectsyn/k8s-service-ca-controller/certs"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
)
const (
// InjectLabelKey is the label which indicates that the Service CA
// certificate should be injected into the ConfigMap
InjectLabelKey = "service.syn.tools/inject-ca-bundle"
)
// ConfigMapReconciler injects the service CA certificate into field `ca.crt`
// of ConfigMap objects which have the label
// `service.syn.tools/inject-ca-bundle` set to `true`.
type ConfigMapReconciler struct {
client.Client
Scheme *runtime.Scheme
CANamespace string
}
//+kubebuilder:rbac:groups=core,resources=configmaps,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=core,resources=configmaps/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=core,resources=configmaps/finalizers,verbs=update
// Reconcile injects the service CA certificate into ConfigMaps which have the
// `service.syn.tools/inject-ca-bundle` label set to `true`.
// Please note that the reconciler will requeue requests until the Service CA
// is created an ready.
func (r *ConfigMapReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
l := log.FromContext(ctx).WithValues("namespace", req.Namespace, "name", req.Name)
cm := corev1.ConfigMap{}
err := r.Get(ctx, client.ObjectKey{
Name: req.Name,
Namespace: req.Namespace,
}, &cm)
if err != nil {
if errors.IsNotFound(err) {
// nothing to do
return ctrl.Result{}, nil
}
l.Error(err, "while fetching configmap")
return ctrl.Result{}, err
}
cmLabels := cm.Labels
if cmLabels == nil {
// nothing to do, exit
return ctrl.Result{}, nil
}
inject, ok := cmLabels[InjectLabelKey]
if !ok {
// label not present, nothing to do
return ctrl.Result{}, nil
}
ok, err = strconv.ParseBool(inject)
if err != nil {
l.V(1).Info("Failed to parse label value as boolean", "value", inject)
// don't requeue
return ctrl.Result{}, nil
}
if !ok {
l.V(1).Info("Label value is `false`, not injecting CA")
// don't requeue
return ctrl.Result{}, nil
}
serviceCA, err := certs.GetServiceCA(ctx, r.Client, l, r.CANamespace)
if err != nil {
l.Info("Service CA not ready yet, requeuing request")
return ctrl.Result{}, err
}
origCM := cm.DeepCopy()
if cm.Data == nil {
cm.Data = map[string]string{}
}
cm.Data["ca.crt"] = serviceCA
if !reflect.DeepEqual(cm.Data, origCM.Data) {
// Only update CM if we're actually making changes
l.Info("Updating Service CA in key `ca.crt`")
r.Update(ctx, &cm)
}
return ctrl.Result{}, nil
}
// SetupWithManager sets up the controller with the Manager.
func (r *ConfigMapReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&corev1.ConfigMap{}).
Complete(r)
}