-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathutil.go
107 lines (87 loc) · 2.83 KB
/
util.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
package kubeutil
import (
"context"
"reflect"
"github.com/go-logr/logr"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
apierrs "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)
// IgnoreNotFound returns nil when the err is kubernetes NotFound, otherwise
// returns the original err
func IgnoreNotFound(err error) error {
if apierrs.IsNotFound(err) {
return nil
}
return err
}
// mutateFn is used to reconsicle differences when the object is getting
// updated. src is the existing object while dest is what the object will be
// updated to.
type mutateFn func(src, dest runtime.Object)
// CreateOrUpdate
func CreateOrUpdate(ctx context.Context, log logr.Logger, c client.Client, obj runtime.Object) error {
nn, err := client.ObjectKeyFromObject(obj)
if err != nil {
return err
}
fns := []mutateFn{}
switch obj.(type) {
case *corev1.Service:
fns = append(fns, func(src, dest runtime.Object) {
// clusterIp cannot be updated on a service, so copy the field
dest.(*corev1.Service).Spec.ClusterIP = src.(*corev1.Service).Spec.ClusterIP
})
}
res, err := createOrUpdate(ctx, c, obj, fns...)
log.V(1).Info(string(res), "name", nn.String(), "object", reflect.TypeOf(obj))
return err
}
// for reference https://github.com/kubernetes-sigs/controller-runtime/blob/master/pkg/controller/controllerutil/controllerutil.go#L136
func createOrUpdate(ctx context.Context, c client.Client, obj runtime.Object, mutateFn ...mutateFn) (controllerutil.OperationResult, error) {
key, err := client.ObjectKeyFromObject(obj)
if err != nil {
return controllerutil.OperationResultNone, err
}
existing := obj.DeepCopyObject()
if err := c.Get(ctx, key, existing); err != nil {
if !errors.IsNotFound(err) {
return controllerutil.OperationResultNone, err
}
if err := c.Create(ctx, obj); err != nil {
return controllerutil.OperationResultNone, err
}
return controllerutil.OperationResultCreated, nil
}
if err := setMatchingResourceVersion(existing, obj); err != nil {
return controllerutil.OperationResultNone, err
}
for _, fn := range mutateFn {
fn(existing, obj)
}
if reflect.DeepEqual(existing, obj) {
return controllerutil.OperationResultNone, err
}
if err := c.Update(ctx, obj); err != nil {
return controllerutil.OperationResultNone, err
}
return controllerutil.OperationResultUpdated, nil
}
// setMatchingResourceVersion sets the ResourceVersion to be the same as the
// first argument
func setMatchingResourceVersion(from, to runtime.Object) error {
src, err := meta.Accessor(from)
if err != nil {
return err
}
dest, err := meta.Accessor(to)
if err != nil {
return err
}
dest.SetResourceVersion(src.GetResourceVersion())
return nil
}