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.
22 "k8s.io/apimachinery/pkg/api/meta"
23 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
25 "k8s.io/apimachinery/pkg/runtime"
26 "k8s.io/apimachinery/pkg/runtime/schema"
27 "k8s.io/apimachinery/pkg/runtime/serializer/streaming"
28 "k8s.io/apimachinery/pkg/types"
29 "k8s.io/apimachinery/pkg/watch"
30 "k8s.io/client-go/rest"
33 type dynamicClient struct {
34 client *rest.RESTClient
37 var _ Interface = &dynamicClient{}
39 // NewForConfigOrDie creates a new Interface for the given config and
40 // panics if there is an error in the config.
41 func NewForConfigOrDie(c *rest.Config) Interface {
42 ret, err := NewForConfig(c)
49 func NewForConfig(inConfig *rest.Config) (Interface, error) {
50 config := rest.CopyConfig(inConfig)
51 // for serializing the options
52 config.GroupVersion = &schema.GroupVersion{}
53 config.APIPath = "/if-you-see-this-search-for-the-break"
54 config.AcceptContentTypes = "application/json"
55 config.ContentType = "application/json"
56 config.NegotiatedSerializer = basicNegotiatedSerializer{} // this gets used for discovery and error handling types
57 if config.UserAgent == "" {
58 config.UserAgent = rest.DefaultKubernetesUserAgent()
61 restClient, err := rest.RESTClientFor(config)
66 return &dynamicClient{client: restClient}, nil
69 type dynamicResourceClient struct {
72 resource schema.GroupVersionResource
75 func (c *dynamicClient) Resource(resource schema.GroupVersionResource) NamespaceableResourceInterface {
76 return &dynamicResourceClient{client: c, resource: resource}
79 func (c *dynamicResourceClient) Namespace(ns string) ResourceInterface {
85 func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured, opts metav1.CreateOptions, subresources ...string) (*unstructured.Unstructured, error) {
86 outBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj)
91 if len(subresources) > 0 {
92 accessor, err := meta.Accessor(obj)
96 name = accessor.GetName()
99 result := c.client.client.
101 AbsPath(append(c.makeURLSegments(name), subresources...)...).
103 SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
105 if err := result.Error(); err != nil {
109 retBytes, err := result.Raw()
113 uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes)
117 return uncastObj.(*unstructured.Unstructured), nil
120 func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured, opts metav1.UpdateOptions, subresources ...string) (*unstructured.Unstructured, error) {
121 accessor, err := meta.Accessor(obj)
125 outBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj)
130 result := c.client.client.
132 AbsPath(append(c.makeURLSegments(accessor.GetName()), subresources...)...).
134 SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
136 if err := result.Error(); err != nil {
140 retBytes, err := result.Raw()
144 uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes)
148 return uncastObj.(*unstructured.Unstructured), nil
151 func (c *dynamicResourceClient) UpdateStatus(obj *unstructured.Unstructured, opts metav1.UpdateOptions) (*unstructured.Unstructured, error) {
152 accessor, err := meta.Accessor(obj)
157 outBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj)
162 result := c.client.client.
164 AbsPath(append(c.makeURLSegments(accessor.GetName()), "status")...).
166 SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
168 if err := result.Error(); err != nil {
172 retBytes, err := result.Raw()
176 uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes)
180 return uncastObj.(*unstructured.Unstructured), nil
183 func (c *dynamicResourceClient) Delete(name string, opts *metav1.DeleteOptions, subresources ...string) error {
185 opts = &metav1.DeleteOptions{}
187 deleteOptionsByte, err := runtime.Encode(deleteOptionsCodec.LegacyCodec(schema.GroupVersion{Version: "v1"}), opts)
192 result := c.client.client.
194 AbsPath(append(c.makeURLSegments(name), subresources...)...).
195 Body(deleteOptionsByte).
197 return result.Error()
200 func (c *dynamicResourceClient) DeleteCollection(opts *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
202 opts = &metav1.DeleteOptions{}
204 deleteOptionsByte, err := runtime.Encode(deleteOptionsCodec.LegacyCodec(schema.GroupVersion{Version: "v1"}), opts)
209 result := c.client.client.
211 AbsPath(c.makeURLSegments("")...).
212 Body(deleteOptionsByte).
213 SpecificallyVersionedParams(&listOptions, dynamicParameterCodec, versionV1).
215 return result.Error()
218 func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error) {
219 result := c.client.client.Get().AbsPath(append(c.makeURLSegments(name), subresources...)...).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do()
220 if err := result.Error(); err != nil {
223 retBytes, err := result.Raw()
227 uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes)
231 return uncastObj.(*unstructured.Unstructured), nil
234 func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error) {
235 result := c.client.client.Get().AbsPath(c.makeURLSegments("")...).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do()
236 if err := result.Error(); err != nil {
239 retBytes, err := result.Raw()
243 uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes)
247 if list, ok := uncastObj.(*unstructured.UnstructuredList); ok {
251 list, err := uncastObj.(*unstructured.Unstructured).ToList()
258 func (c *dynamicResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
259 internalGV := schema.GroupVersions{
260 {Group: c.resource.Group, Version: runtime.APIVersionInternal},
261 // always include the legacy group as a decoding target to handle non-error `Status` return types
262 {Group: "", Version: runtime.APIVersionInternal},
264 s := &rest.Serializers{
265 Encoder: watchNegotiatedSerializerInstance.EncoderForVersion(watchJsonSerializerInfo.Serializer, c.resource.GroupVersion()),
266 Decoder: watchNegotiatedSerializerInstance.DecoderToVersion(watchJsonSerializerInfo.Serializer, internalGV),
268 RenegotiatedDecoder: func(contentType string, params map[string]string) (runtime.Decoder, error) {
269 return watchNegotiatedSerializerInstance.DecoderToVersion(watchJsonSerializerInfo.Serializer, internalGV), nil
271 StreamingSerializer: watchJsonSerializerInfo.StreamSerializer.Serializer,
272 Framer: watchJsonSerializerInfo.StreamSerializer.Framer,
275 wrappedDecoderFn := func(body io.ReadCloser) streaming.Decoder {
276 framer := s.Framer.NewFrameReader(body)
277 return streaming.NewDecoder(framer, s.StreamingSerializer)
281 return c.client.client.Get().AbsPath(c.makeURLSegments("")...).
282 SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
283 WatchWithSpecificDecoders(wrappedDecoderFn, unstructured.UnstructuredJSONScheme)
286 func (c *dynamicResourceClient) Patch(name string, pt types.PatchType, data []byte, opts metav1.UpdateOptions, subresources ...string) (*unstructured.Unstructured, error) {
287 result := c.client.client.
289 AbsPath(append(c.makeURLSegments(name), subresources...)...).
291 SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
293 if err := result.Error(); err != nil {
296 retBytes, err := result.Raw()
300 uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes)
304 return uncastObj.(*unstructured.Unstructured), nil
307 func (c *dynamicResourceClient) makeURLSegments(name string) []string {
309 if len(c.resource.Group) == 0 {
310 url = append(url, "api")
312 url = append(url, "apis", c.resource.Group)
314 url = append(url, c.resource.Version)
316 if len(c.namespace) > 0 {
317 url = append(url, "namespaces", c.namespace)
319 url = append(url, c.resource.Resource)
322 url = append(url, name)