2 Copyright 2018 The Kubernetes Authors.
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
24 "k8s.io/apimachinery/pkg/api/meta"
25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
27 "k8s.io/apimachinery/pkg/runtime"
28 "k8s.io/apimachinery/pkg/runtime/schema"
29 "k8s.io/client-go/dynamic"
32 // client is a client.Client that reads and writes directly from/to an API server. It lazily initializes
33 // new clients at the time they are used, and caches the client.
34 type unstructuredClient struct {
35 client dynamic.Interface
36 restMapper meta.RESTMapper
39 // Create implements client.Client
40 func (uc *unstructuredClient) Create(_ context.Context, obj runtime.Object) error {
41 u, ok := obj.(*unstructured.Unstructured)
43 return fmt.Errorf("unstructured client did not understand object: %T", obj)
45 r, err := uc.getResourceInterface(u.GroupVersionKind(), u.GetNamespace())
49 i, err := r.Create(u, metav1.CreateOptions{})
57 // Update implements client.Client
58 func (uc *unstructuredClient) Update(_ context.Context, obj runtime.Object) error {
59 u, ok := obj.(*unstructured.Unstructured)
61 return fmt.Errorf("unstructured client did not understand object: %T", obj)
63 r, err := uc.getResourceInterface(u.GroupVersionKind(), u.GetNamespace())
67 i, err := r.Update(u, metav1.UpdateOptions{})
75 // Delete implements client.Client
76 func (uc *unstructuredClient) Delete(_ context.Context, obj runtime.Object, opts ...DeleteOptionFunc) error {
77 u, ok := obj.(*unstructured.Unstructured)
79 return fmt.Errorf("unstructured client did not understand object: %T", obj)
81 r, err := uc.getResourceInterface(u.GroupVersionKind(), u.GetNamespace())
85 deleteOpts := DeleteOptions{}
86 err = r.Delete(u.GetName(), deleteOpts.ApplyOptions(opts).AsDeleteOptions())
90 // Get implements client.Client
91 func (uc *unstructuredClient) Get(_ context.Context, key ObjectKey, obj runtime.Object) error {
92 u, ok := obj.(*unstructured.Unstructured)
94 return fmt.Errorf("unstructured client did not understand object: %T", obj)
96 r, err := uc.getResourceInterface(u.GroupVersionKind(), key.Namespace)
100 i, err := r.Get(key.Name, metav1.GetOptions{})
108 // List implements client.Client
109 func (uc *unstructuredClient) List(_ context.Context, opts *ListOptions, obj runtime.Object) error {
110 u, ok := obj.(*unstructured.UnstructuredList)
112 return fmt.Errorf("unstructured client did not understand object: %T", obj)
114 gvk := u.GroupVersionKind()
115 if strings.HasSuffix(gvk.Kind, "List") {
116 gvk.Kind = gvk.Kind[:len(gvk.Kind)-4]
120 namespace = opts.Namespace
122 r, err := uc.getResourceInterface(gvk, namespace)
127 i, err := r.List(*opts.AsListOptions())
136 func (uc *unstructuredClient) UpdateStatus(_ context.Context, obj runtime.Object) error {
137 u, ok := obj.(*unstructured.Unstructured)
139 return fmt.Errorf("unstructured client did not understand object: %T", obj)
141 r, err := uc.getResourceInterface(u.GroupVersionKind(), u.GetNamespace())
145 i, err := r.UpdateStatus(u, metav1.UpdateOptions{})
153 func (uc *unstructuredClient) getResourceInterface(gvk schema.GroupVersionKind, ns string) (dynamic.ResourceInterface, error) {
154 mapping, err := uc.restMapper.RESTMapping(gvk.GroupKind(), gvk.Version)
158 if mapping.Scope.Name() == meta.RESTScopeNameRoot {
159 return uc.client.Resource(mapping.Resource), nil
161 return uc.client.Resource(mapping.Resource).Namespace(ns), nil