-
Notifications
You must be signed in to change notification settings - Fork 0
/
kube_client.go
187 lines (161 loc) · 5.35 KB
/
kube_client.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
package kubernetes_ctx
import (
"github.com/google/uuid"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
)
// Create creates a Kubernetes resource based on the given APIVersion/Kind,
// the name and the object definition itself. It allows us to easily manage
// all resources through Unstructured object with the "official" Kubernetes
// client.Client interface.
func (ctx *FeatureContext) Create(
groupVersionKind schema.GroupVersionKind,
namespacedName types.NamespacedName,
obj *unstructured.Unstructured,
opts ...client.CreateOption,
) error {
obj.SetGroupVersionKind(groupVersionKind)
obj.SetUID(types.UID(uuid.New().String()))
obj.SetName(namespacedName.Name)
obj.SetNamespace(namespacedName.Namespace)
kobj, err := ctx.scheme.New(groupVersionKind)
if err != nil {
return err
}
err = runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, kobj)
if err != nil {
return err
}
return ctx.client.Create(ctx.ctx, kobj, opts...)
}
// Get fetches the Kubernetes resource using the given APIVersion/Kind and
// the name. It wraps the Get method of the "official" Kubernetes client.Client
// interface, but returns an Unstructured object, more easier to use.
func (ctx *FeatureContext) Get(
groupVersionKind schema.GroupVersionKind,
namespacedName types.NamespacedName,
) (*unstructured.Unstructured, error) {
kobj, err := ctx.get(groupVersionKind, namespacedName)
if err != nil {
return nil, err
}
obj := unstructured.Unstructured{}
obj.Object, err = runtime.DefaultUnstructuredConverter.ToUnstructured(kobj)
return &obj, err
}
// Get fetches the Kubernetes resource using the given APIVersion/Kind and
// the name. It wraps the Get method of the "official" Kubernetes client.Client
// interface, and returns a runtime.Object.
func (ctx *FeatureContext) get(
groupVersionKind schema.GroupVersionKind,
namespacedName types.NamespacedName,
) (runtime.Object, error) {
kobj, err := ctx.scheme.New(groupVersionKind)
if err != nil {
return nil, err
}
err = ctx.client.Get(ctx.ctx, namespacedName, kobj)
if err != nil {
return nil, err
}
return kobj, nil
}
// List returns all Kubernetes resources based on the given APIVersion/Kind. It
// returns a List of Unstructured object, more easier to use.
func (ctx *FeatureContext) List(
groupVersionKind schema.GroupVersionKind,
opts ...client.ListOption,
) ([]*unstructured.Unstructured, error) {
// NOTE: can be dangerous but seems working...
groupVersionKind.Kind += "List"
kobj, err := ctx.scheme.New(groupVersionKind)
if err != nil {
return nil, err
}
err = ctx.client.List(ctx.ctx, kobj, opts...)
if err != nil {
return nil, err
}
list := unstructured.Unstructured{}
list.Object, err = runtime.DefaultUnstructuredConverter.ToUnstructured(kobj)
if err != nil {
return nil, err
}
if !list.IsList() {
return nil, nil
}
var objs []*unstructured.Unstructured
return objs, list.EachListItem(func(object runtime.Object) error {
objs = append(objs, object.(*unstructured.Unstructured))
return nil
})
}
// Update updates a Kubernetes resource based on the given APIVersion/Kind
// and the name with the given Unstructured object.
func (ctx *FeatureContext) Update(
groupVersionKind schema.GroupVersionKind,
namespacedName types.NamespacedName,
obj *unstructured.Unstructured,
opts ...client.UpdateOption,
) error {
obj.SetGroupVersionKind(groupVersionKind)
obj.SetName(namespacedName.Name)
obj.SetNamespace(namespacedName.Namespace)
kobj, err := ctx.scheme.New(obj.GroupVersionKind())
if err != nil {
return err
}
err = runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, kobj)
if err != nil {
return err
}
return ctx.client.Update(ctx.ctx, obj, opts...)
}
// Patch patches a Kubernetes resource based on the given APIVersion/Kind
// and the name with the given Patch value.
func (ctx *FeatureContext) Patch(
groupVersionKind schema.GroupVersionKind,
namespacedName types.NamespacedName,
pt types.PatchType,
data []byte,
) error {
obj, err := ctx.get(groupVersionKind, namespacedName)
if err != nil {
return err
}
return ctx.client.Patch(ctx.ctx, obj, client.RawPatch(pt, data))
}
// Delete deletes a Kubernetes resource based on the given APIVersion/Kind
// and the name, and returns the removed object. If a garbage collector is
// set to the context, it will call it on the removed resource.
func (ctx *FeatureContext) Delete(
groupVersionKind schema.GroupVersionKind,
namespacedName types.NamespacedName,
) (*unstructured.Unstructured, error) {
obj, err := ctx.DeleteWithoutGC(groupVersionKind, namespacedName)
if err != nil {
return nil, err
}
return obj, ctx.callGC(obj)
}
// DeleteWithoutGC deletes a Kubernetes resource based on the given
// APIVersion/Kind and the name, and returns the removed object.
// Therefore, it never calls the garbage collector.
func (ctx *FeatureContext) DeleteWithoutGC(
groupVersionKind schema.GroupVersionKind,
namespacedName types.NamespacedName,
) (*unstructured.Unstructured, error) {
kobj, err := ctx.get(groupVersionKind, namespacedName)
if err != nil {
return nil, err
}
obj := unstructured.Unstructured{}
obj.Object, err = runtime.DefaultUnstructuredConverter.ToUnstructured(kobj)
if err != nil {
return nil, err
}
return &obj, ctx.client.Delete(ctx.ctx, kobj)
}