forked from rancher/norman
/
object.go
119 lines (96 loc) · 2.65 KB
/
object.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
package lifecycle
import (
"github.com/rancher/norman/clientbase"
"github.com/rancher/norman/types/slice"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)
var (
created = "io.cattle.lifecycle.create"
)
type ObjectLifecycle interface {
Create(obj runtime.Object) error
Finalize(obj runtime.Object) error
Updated(obj runtime.Object) error
}
type objectLifecycleAdapter struct {
name string
lifecycle ObjectLifecycle
objectClient *clientbase.ObjectClient
}
func NewObjectLifecycleAdapter(name string, lifecycle ObjectLifecycle, objectClient *clientbase.ObjectClient) func(key string, obj runtime.Object) error {
o := objectLifecycleAdapter{
name: name,
lifecycle: lifecycle,
objectClient: objectClient,
}
return o.sync
}
func (o *objectLifecycleAdapter) sync(key string, obj runtime.Object) error {
if obj == nil {
return nil
}
metadata, err := meta.Accessor(obj)
if err != nil {
return err
}
if cont, err := o.finalize(metadata, obj); err != nil || !cont {
return err
}
if cont, err := o.create(metadata, obj); err != nil || !cont {
return err
}
return o.lifecycle.Updated(obj.DeepCopyObject())
}
func (o *objectLifecycleAdapter) finalize(metadata metav1.Object, obj runtime.Object) (bool, error) {
// Check finalize
if metadata.GetDeletionTimestamp() == nil {
return true, nil
}
if !slice.ContainsString(metadata.GetFinalizers(), o.name) {
return false, nil
}
obj = obj.DeepCopyObject()
metadata, err := meta.Accessor(obj)
if err != nil {
return false, err
}
var finalizers []string
for _, finalizer := range metadata.GetFinalizers() {
if finalizer == o.name {
continue
}
finalizers = append(finalizers, finalizer)
}
metadata.SetFinalizers(finalizers)
if err := o.lifecycle.Finalize(obj); err != nil {
return false, err
}
_, err = o.objectClient.Update(metadata.GetName(), obj)
return false, err
}
func (o *objectLifecycleAdapter) createKey() string {
return created + "." + o.name
}
func (o *objectLifecycleAdapter) create(metadata metav1.Object, obj runtime.Object) (bool, error) {
initialized := o.createKey()
if metadata.GetLabels()[initialized] == "true" {
return true, nil
}
obj = obj.DeepCopyObject()
metadata, err := meta.Accessor(obj)
if err != nil {
return false, err
}
if metadata.GetLabels() == nil {
metadata.SetLabels(map[string]string{})
}
metadata.SetFinalizers(append(metadata.GetFinalizers(), o.name))
metadata.GetLabels()[initialized] = "true"
if err := o.lifecycle.Create(obj); err != nil {
return false, err
}
_, err = o.objectClient.Update(metadata.GetName(), obj)
return false, err
}