/
apply.go
65 lines (56 loc) · 1.93 KB
/
apply.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
package apply
import (
"context"
"fmt"
"log"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/api/equality"
apierrors "k8s.io/apimachinery/pkg/api/errors"
uns "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/types"
k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
)
// ApplyObject applies the desired object against the apiserver,
// merging it with any existing objects if already present.
func ApplyObject(ctx context.Context, client k8sclient.Client, obj *uns.Unstructured) error {
name := obj.GetName()
namespace := obj.GetNamespace()
if name == "" {
return errors.Errorf("Object %s has no name", obj.GroupVersionKind().String())
}
gvk := obj.GroupVersionKind()
// used for logging and errors
objDesc := fmt.Sprintf("(%s) %s/%s", gvk.String(), namespace, name)
log.Printf("reconciling %s", objDesc)
if err := IsObjectSupported(obj); err != nil {
return errors.Wrapf(err, "object %s unsupported", objDesc)
}
// Get existing
existing := &uns.Unstructured{}
existing.SetGroupVersionKind(gvk)
err := client.Get(ctx, types.NamespacedName{Name: obj.GetName(), Namespace: obj.GetNamespace()}, existing)
if err != nil && apierrors.IsNotFound(err) {
log.Printf("does not exist, creating %s", objDesc)
err := client.Create(ctx, obj)
if err != nil {
return errors.Wrapf(err, "could not create %s", objDesc)
}
log.Printf("successfully created %s", objDesc)
return nil
}
if err != nil {
return errors.Wrapf(err, "could not retrieve existing %s", objDesc)
}
// Merge the desired object with what actually exists
if err := MergeObjectForUpdate(existing, obj); err != nil {
return errors.Wrapf(err, "could not merge object %s with existing", objDesc)
}
if !equality.Semantic.DeepEqual(existing, obj) {
if err := client.Update(ctx, obj); err != nil {
return errors.Wrapf(err, "could not update object %s", objDesc)
} else {
log.Printf("update was successful")
}
}
return nil
}