-
Notifications
You must be signed in to change notification settings - Fork 286
/
unauth.go
165 lines (136 loc) Β· 5.29 KB
/
unauth.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
package kubernetes
import (
"context"
"fmt"
"strings"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/utils/pointer"
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
)
// UnAuthClient is a generic kubernetes API client that takes a kubeconfig
// file on every call in order to authenticate.
type UnAuthClient struct {
kubectl Kubectl
scheme *runtime.Scheme
}
// NewUnAuthClient builds a new UnAuthClient.
func NewUnAuthClient(kubectl Kubectl) *UnAuthClient {
return &UnAuthClient{
kubectl: kubectl,
scheme: runtime.NewScheme(),
}
}
// Init initializes the client internal API scheme
// It has always be invoked at least once before making any API call
// It is not thread safe.
func (c *UnAuthClient) Init() error {
return addToScheme(c.scheme, schemeAdders...)
}
// Get performs a GET call to the kube API server authenticating with a kubeconfig file
// and unmarshalls the response into the provdied Object.
func (c *UnAuthClient) Get(ctx context.Context, name, namespace, kubeconfig string, obj runtime.Object) error {
resourceType, err := c.resourceTypeForObj(obj)
if err != nil {
return fmt.Errorf("getting kubernetes resource: %v", err)
}
var opts KubectlGetOptions
if namespace == "" {
opts = KubectlGetOptions{Name: name, ClusterScoped: pointer.Bool(true)}
} else {
opts = KubectlGetOptions{Name: name, Namespace: namespace}
}
return c.kubectl.Get(ctx, resourceType, kubeconfig, obj, &opts)
}
// KubeconfigClient returns an equivalent authenticated client.
func (c *UnAuthClient) KubeconfigClient(kubeconfig string) Client {
return NewKubeconfigClient(c, kubeconfig)
}
// BuildClientFromKubeconfig returns an equivalent authenticated client. It will never return
// an error but this helps satisfy a generic factory interface where errors are possible. It's
// basically an alias to KubeconfigClient.
func (c *UnAuthClient) BuildClientFromKubeconfig(kubeconfig string) (Client, error) {
return c.KubeconfigClient(kubeconfig), nil
}
// Apply performs an upsert in the form of a client-side apply.
func (c *UnAuthClient) Apply(ctx context.Context, kubeconfig string, obj runtime.Object) error {
return c.kubectl.Apply(ctx, kubeconfig, obj)
}
// ApplyServerSide creates or patches and object using server side logic.
func (c *UnAuthClient) ApplyServerSide(ctx context.Context, kubeconfig, fieldManager string, obj Object, opts ...ApplyServerSideOption) error {
o := &ApplyServerSideOptions{}
for _, opt := range opts {
opt.ApplyToApplyServerSide(o)
}
ko := KubectlApplyOptions{
ServerSide: true,
FieldManager: fieldManager,
}
if o.ForceOwnership {
ko.ForceOwnership = o.ForceOwnership
}
return c.kubectl.Apply(ctx, kubeconfig, obj, ko)
}
// List retrieves list of objects. On a successful call, Items field
// in the list will be populated with the result returned from the server.
func (c *UnAuthClient) List(ctx context.Context, kubeconfig string, list ObjectList) error {
resourceType, err := c.resourceTypeForObj(list)
if err != nil {
return fmt.Errorf("getting kubernetes resource: %v", err)
}
return c.kubectl.Get(ctx, resourceType, kubeconfig, list)
}
// Create saves the object obj in the Kubernetes cluster.
func (c *UnAuthClient) Create(ctx context.Context, kubeconfig string, obj Object) error {
return c.kubectl.Create(ctx, kubeconfig, obj)
}
// Update updates the given obj in the Kubernetes cluster.
func (c *UnAuthClient) Update(ctx context.Context, kubeconfig string, obj Object) error {
return c.kubectl.Replace(ctx, kubeconfig, obj)
}
// Delete deletes the given obj from Kubernetes cluster.
func (c *UnAuthClient) Delete(ctx context.Context, kubeconfig string, obj Object) error {
resourceType, err := c.resourceTypeForObj(obj)
if err != nil {
return fmt.Errorf("deleting kubernetes resource: %v", err)
}
o := &KubectlDeleteOptions{
Name: obj.GetName(),
Namespace: obj.GetNamespace(),
}
return c.kubectl.Delete(ctx, resourceType, kubeconfig, o)
}
// DeleteAllOf deletes all objects of the given type matching the given options.
func (c *UnAuthClient) DeleteAllOf(ctx context.Context, kubeconfig string, obj Object, opts ...DeleteAllOfOption) error {
resourceType, err := c.resourceTypeForObj(obj)
if err != nil {
return fmt.Errorf("deleting kubernetes resource: %v", err)
}
deleteAllOpts := &DeleteAllOfOptions{}
for _, opt := range opts {
opt.ApplyToDeleteAllOf(deleteAllOpts)
}
o := &KubectlDeleteOptions{}
o.Namespace = deleteAllOpts.Namespace
o.HasLabels = deleteAllOpts.HasLabels
return c.kubectl.Delete(ctx, resourceType, kubeconfig, o)
}
func (c *UnAuthClient) resourceTypeForObj(obj runtime.Object) (string, error) {
groupVersionKind, err := apiutil.GVKForObject(obj, c.scheme)
if err != nil {
return "", err
}
if meta.IsListType(obj) && strings.HasSuffix(groupVersionKind.Kind, "List") {
// if obj is a list, treat it as a request for the "individual" item's resource
groupVersionKind.Kind = groupVersionKind.Kind[:len(groupVersionKind.Kind)-4]
}
return groupVersionToKubectlResourceType(groupVersionKind), nil
}
func groupVersionToKubectlResourceType(g schema.GroupVersionKind) string {
if g.Group == "" {
// if Group is not set, this probably an obj from "core", which api group is just v1
return g.Kind
}
return fmt.Sprintf("%s.%s.%s", g.Kind, g.Version, g.Group)
}