2020-10-21 05:49:41 +00:00
|
|
|
/*
|
|
|
|
Copyright 2018 The Kubernetes Authors.
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package client
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
|
|
)
|
|
|
|
|
2021-06-25 05:02:01 +00:00
|
|
|
var _ Reader = &unstructuredClient{}
|
|
|
|
var _ Writer = &unstructuredClient{}
|
|
|
|
|
2020-10-21 05:49:41 +00:00
|
|
|
// client is a client.Client that reads and writes directly from/to an API server. It lazily initializes
|
|
|
|
// new clients at the time they are used, and caches the client.
|
|
|
|
type unstructuredClient struct {
|
|
|
|
cache *clientCache
|
|
|
|
paramCodec runtime.ParameterCodec
|
|
|
|
}
|
|
|
|
|
2021-06-25 05:02:01 +00:00
|
|
|
// Create implements client.Client.
|
|
|
|
func (uc *unstructuredClient) Create(ctx context.Context, obj Object, opts ...CreateOption) error {
|
2020-10-21 05:49:41 +00:00
|
|
|
u, ok := obj.(*unstructured.Unstructured)
|
|
|
|
if !ok {
|
|
|
|
return fmt.Errorf("unstructured client did not understand object: %T", obj)
|
|
|
|
}
|
|
|
|
|
|
|
|
gvk := u.GroupVersionKind()
|
|
|
|
|
|
|
|
o, err := uc.cache.getObjMeta(obj)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
createOpts := &CreateOptions{}
|
|
|
|
createOpts.ApplyOptions(opts)
|
2023-02-01 17:06:36 +00:00
|
|
|
|
2020-10-21 05:49:41 +00:00
|
|
|
result := o.Post().
|
|
|
|
NamespaceIfScoped(o.GetNamespace(), o.isNamespaced()).
|
|
|
|
Resource(o.resource()).
|
|
|
|
Body(obj).
|
|
|
|
VersionedParams(createOpts.AsCreateOptions(), uc.paramCodec).
|
|
|
|
Do(ctx).
|
|
|
|
Into(obj)
|
|
|
|
|
|
|
|
u.SetGroupVersionKind(gvk)
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2021-06-25 05:02:01 +00:00
|
|
|
// Update implements client.Client.
|
|
|
|
func (uc *unstructuredClient) Update(ctx context.Context, obj Object, opts ...UpdateOption) error {
|
2020-10-21 05:49:41 +00:00
|
|
|
u, ok := obj.(*unstructured.Unstructured)
|
|
|
|
if !ok {
|
|
|
|
return fmt.Errorf("unstructured client did not understand object: %T", obj)
|
|
|
|
}
|
|
|
|
|
|
|
|
gvk := u.GroupVersionKind()
|
|
|
|
|
|
|
|
o, err := uc.cache.getObjMeta(obj)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
updateOpts := UpdateOptions{}
|
|
|
|
updateOpts.ApplyOptions(opts)
|
2023-02-01 17:06:36 +00:00
|
|
|
|
2020-10-21 05:49:41 +00:00
|
|
|
result := o.Put().
|
|
|
|
NamespaceIfScoped(o.GetNamespace(), o.isNamespaced()).
|
|
|
|
Resource(o.resource()).
|
|
|
|
Name(o.GetName()).
|
|
|
|
Body(obj).
|
|
|
|
VersionedParams(updateOpts.AsUpdateOptions(), uc.paramCodec).
|
|
|
|
Do(ctx).
|
|
|
|
Into(obj)
|
|
|
|
|
|
|
|
u.SetGroupVersionKind(gvk)
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2021-06-25 05:02:01 +00:00
|
|
|
// Delete implements client.Client.
|
|
|
|
func (uc *unstructuredClient) Delete(ctx context.Context, obj Object, opts ...DeleteOption) error {
|
2023-02-01 17:06:36 +00:00
|
|
|
if _, ok := obj.(*unstructured.Unstructured); !ok {
|
2020-10-21 05:49:41 +00:00
|
|
|
return fmt.Errorf("unstructured client did not understand object: %T", obj)
|
|
|
|
}
|
|
|
|
|
|
|
|
o, err := uc.cache.getObjMeta(obj)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
deleteOpts := DeleteOptions{}
|
|
|
|
deleteOpts.ApplyOptions(opts)
|
2023-02-01 17:06:36 +00:00
|
|
|
|
2020-10-21 05:49:41 +00:00
|
|
|
return o.Delete().
|
|
|
|
NamespaceIfScoped(o.GetNamespace(), o.isNamespaced()).
|
|
|
|
Resource(o.resource()).
|
|
|
|
Name(o.GetName()).
|
|
|
|
Body(deleteOpts.AsDeleteOptions()).
|
|
|
|
Do(ctx).
|
|
|
|
Error()
|
|
|
|
}
|
|
|
|
|
2021-06-25 05:02:01 +00:00
|
|
|
// DeleteAllOf implements client.Client.
|
|
|
|
func (uc *unstructuredClient) DeleteAllOf(ctx context.Context, obj Object, opts ...DeleteAllOfOption) error {
|
2023-02-01 17:06:36 +00:00
|
|
|
if _, ok := obj.(*unstructured.Unstructured); !ok {
|
2020-10-21 05:49:41 +00:00
|
|
|
return fmt.Errorf("unstructured client did not understand object: %T", obj)
|
|
|
|
}
|
|
|
|
|
|
|
|
o, err := uc.cache.getObjMeta(obj)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
deleteAllOfOpts := DeleteAllOfOptions{}
|
|
|
|
deleteAllOfOpts.ApplyOptions(opts)
|
2023-02-01 17:06:36 +00:00
|
|
|
|
2020-10-21 05:49:41 +00:00
|
|
|
return o.Delete().
|
|
|
|
NamespaceIfScoped(deleteAllOfOpts.ListOptions.Namespace, o.isNamespaced()).
|
|
|
|
Resource(o.resource()).
|
|
|
|
VersionedParams(deleteAllOfOpts.AsListOptions(), uc.paramCodec).
|
|
|
|
Body(deleteAllOfOpts.AsDeleteOptions()).
|
|
|
|
Do(ctx).
|
|
|
|
Error()
|
|
|
|
}
|
|
|
|
|
2021-06-25 05:02:01 +00:00
|
|
|
// Patch implements client.Client.
|
|
|
|
func (uc *unstructuredClient) Patch(ctx context.Context, obj Object, patch Patch, opts ...PatchOption) error {
|
2023-02-01 17:06:36 +00:00
|
|
|
if _, ok := obj.(*unstructured.Unstructured); !ok {
|
2020-10-21 05:49:41 +00:00
|
|
|
return fmt.Errorf("unstructured client did not understand object: %T", obj)
|
|
|
|
}
|
|
|
|
|
|
|
|
o, err := uc.cache.getObjMeta(obj)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
data, err := patch.Data(obj)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
patchOpts := &PatchOptions{}
|
2023-02-01 17:06:36 +00:00
|
|
|
patchOpts.ApplyOptions(opts)
|
|
|
|
|
2020-10-21 05:49:41 +00:00
|
|
|
return o.Patch(patch.Type()).
|
|
|
|
NamespaceIfScoped(o.GetNamespace(), o.isNamespaced()).
|
|
|
|
Resource(o.resource()).
|
|
|
|
Name(o.GetName()).
|
2023-02-01 17:06:36 +00:00
|
|
|
VersionedParams(patchOpts.AsPatchOptions(), uc.paramCodec).
|
2020-10-21 05:49:41 +00:00
|
|
|
Body(data).
|
|
|
|
Do(ctx).
|
|
|
|
Into(obj)
|
|
|
|
}
|
|
|
|
|
2021-06-25 05:02:01 +00:00
|
|
|
// Get implements client.Client.
|
2023-02-01 17:06:36 +00:00
|
|
|
func (uc *unstructuredClient) Get(ctx context.Context, key ObjectKey, obj Object, opts ...GetOption) error {
|
2020-10-21 05:49:41 +00:00
|
|
|
u, ok := obj.(*unstructured.Unstructured)
|
|
|
|
if !ok {
|
|
|
|
return fmt.Errorf("unstructured client did not understand object: %T", obj)
|
|
|
|
}
|
|
|
|
|
|
|
|
gvk := u.GroupVersionKind()
|
|
|
|
|
2023-02-01 17:06:36 +00:00
|
|
|
getOpts := GetOptions{}
|
|
|
|
getOpts.ApplyOptions(opts)
|
|
|
|
|
2020-10-21 05:49:41 +00:00
|
|
|
r, err := uc.cache.getResource(obj)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
result := r.Get().
|
|
|
|
NamespaceIfScoped(key.Namespace, r.isNamespaced()).
|
|
|
|
Resource(r.resource()).
|
2023-02-01 17:06:36 +00:00
|
|
|
VersionedParams(getOpts.AsGetOptions(), uc.paramCodec).
|
2020-10-21 05:49:41 +00:00
|
|
|
Name(key.Name).
|
|
|
|
Do(ctx).
|
|
|
|
Into(obj)
|
|
|
|
|
|
|
|
u.SetGroupVersionKind(gvk)
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2021-06-25 05:02:01 +00:00
|
|
|
// List implements client.Client.
|
|
|
|
func (uc *unstructuredClient) List(ctx context.Context, obj ObjectList, opts ...ListOption) error {
|
2020-10-21 05:49:41 +00:00
|
|
|
u, ok := obj.(*unstructured.UnstructuredList)
|
|
|
|
if !ok {
|
|
|
|
return fmt.Errorf("unstructured client did not understand object: %T", obj)
|
|
|
|
}
|
|
|
|
|
|
|
|
gvk := u.GroupVersionKind()
|
2023-02-01 17:06:36 +00:00
|
|
|
gvk.Kind = strings.TrimSuffix(gvk.Kind, "List")
|
2020-10-21 05:49:41 +00:00
|
|
|
|
|
|
|
r, err := uc.cache.getResource(obj)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-02-01 17:06:36 +00:00
|
|
|
listOpts := ListOptions{}
|
|
|
|
listOpts.ApplyOptions(opts)
|
|
|
|
|
2020-10-21 05:49:41 +00:00
|
|
|
return r.Get().
|
|
|
|
NamespaceIfScoped(listOpts.Namespace, r.isNamespaced()).
|
|
|
|
Resource(r.resource()).
|
|
|
|
VersionedParams(listOpts.AsListOptions(), uc.paramCodec).
|
|
|
|
Do(ctx).
|
|
|
|
Into(obj)
|
|
|
|
}
|
|
|
|
|
2023-02-01 17:06:36 +00:00
|
|
|
func (uc *unstructuredClient) GetSubResource(ctx context.Context, obj, subResourceObj Object, subResource string, opts ...SubResourceGetOption) error {
|
|
|
|
if _, ok := obj.(*unstructured.Unstructured); !ok {
|
|
|
|
return fmt.Errorf("unstructured client did not understand object: %T", subResource)
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, ok := subResourceObj.(*unstructured.Unstructured); !ok {
|
2020-10-21 05:49:41 +00:00
|
|
|
return fmt.Errorf("unstructured client did not understand object: %T", obj)
|
|
|
|
}
|
|
|
|
|
2023-02-01 17:06:36 +00:00
|
|
|
if subResourceObj.GetName() == "" {
|
|
|
|
subResourceObj.SetName(obj.GetName())
|
|
|
|
}
|
|
|
|
|
2020-10-21 05:49:41 +00:00
|
|
|
o, err := uc.cache.getObjMeta(obj)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-02-01 17:06:36 +00:00
|
|
|
getOpts := &SubResourceGetOptions{}
|
|
|
|
getOpts.ApplyOptions(opts)
|
|
|
|
|
|
|
|
return o.Get().
|
|
|
|
NamespaceIfScoped(o.GetNamespace(), o.isNamespaced()).
|
|
|
|
Resource(o.resource()).
|
|
|
|
Name(o.GetName()).
|
|
|
|
SubResource(subResource).
|
|
|
|
VersionedParams(getOpts.AsGetOptions(), uc.paramCodec).
|
|
|
|
Do(ctx).
|
|
|
|
Into(subResourceObj)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (uc *unstructuredClient) CreateSubResource(ctx context.Context, obj, subResourceObj Object, subResource string, opts ...SubResourceCreateOption) error {
|
|
|
|
if _, ok := obj.(*unstructured.Unstructured); !ok {
|
|
|
|
return fmt.Errorf("unstructured client did not understand object: %T", subResourceObj)
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, ok := subResourceObj.(*unstructured.Unstructured); !ok {
|
|
|
|
return fmt.Errorf("unstructured client did not understand object: %T", obj)
|
|
|
|
}
|
|
|
|
|
|
|
|
if subResourceObj.GetName() == "" {
|
|
|
|
subResourceObj.SetName(obj.GetName())
|
|
|
|
}
|
|
|
|
|
|
|
|
o, err := uc.cache.getObjMeta(obj)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
createOpts := &SubResourceCreateOptions{}
|
|
|
|
createOpts.ApplyOptions(opts)
|
|
|
|
|
|
|
|
return o.Post().
|
|
|
|
NamespaceIfScoped(o.GetNamespace(), o.isNamespaced()).
|
|
|
|
Resource(o.resource()).
|
|
|
|
Name(o.GetName()).
|
|
|
|
SubResource(subResource).
|
|
|
|
Body(subResourceObj).
|
|
|
|
VersionedParams(createOpts.AsCreateOptions(), uc.paramCodec).
|
|
|
|
Do(ctx).
|
|
|
|
Into(subResourceObj)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (uc *unstructuredClient) UpdateSubResource(ctx context.Context, obj Object, subResource string, opts ...SubResourceUpdateOption) error {
|
|
|
|
if _, ok := obj.(*unstructured.Unstructured); !ok {
|
|
|
|
return fmt.Errorf("unstructured client did not understand object: %T", obj)
|
|
|
|
}
|
|
|
|
|
|
|
|
o, err := uc.cache.getObjMeta(obj)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
updateOpts := SubResourceUpdateOptions{}
|
|
|
|
updateOpts.ApplyOptions(opts)
|
|
|
|
|
|
|
|
body := obj
|
|
|
|
if updateOpts.SubResourceBody != nil {
|
|
|
|
body = updateOpts.SubResourceBody
|
|
|
|
}
|
|
|
|
if body.GetName() == "" {
|
|
|
|
body.SetName(obj.GetName())
|
|
|
|
}
|
|
|
|
if body.GetNamespace() == "" {
|
|
|
|
body.SetNamespace(obj.GetNamespace())
|
|
|
|
}
|
|
|
|
|
2020-10-21 05:49:41 +00:00
|
|
|
return o.Put().
|
|
|
|
NamespaceIfScoped(o.GetNamespace(), o.isNamespaced()).
|
|
|
|
Resource(o.resource()).
|
|
|
|
Name(o.GetName()).
|
2023-02-01 17:06:36 +00:00
|
|
|
SubResource(subResource).
|
|
|
|
Body(body).
|
|
|
|
VersionedParams(updateOpts.AsUpdateOptions(), uc.paramCodec).
|
2020-10-21 05:49:41 +00:00
|
|
|
Do(ctx).
|
2023-02-01 17:06:36 +00:00
|
|
|
Into(body)
|
2020-10-21 05:49:41 +00:00
|
|
|
}
|
|
|
|
|
2023-02-01 17:06:36 +00:00
|
|
|
func (uc *unstructuredClient) PatchSubResource(ctx context.Context, obj Object, subResource string, patch Patch, opts ...SubResourcePatchOption) error {
|
2020-10-21 05:49:41 +00:00
|
|
|
u, ok := obj.(*unstructured.Unstructured)
|
|
|
|
if !ok {
|
|
|
|
return fmt.Errorf("unstructured client did not understand object: %T", obj)
|
|
|
|
}
|
|
|
|
|
|
|
|
gvk := u.GroupVersionKind()
|
|
|
|
|
|
|
|
o, err := uc.cache.getObjMeta(obj)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-02-01 17:06:36 +00:00
|
|
|
patchOpts := &SubResourcePatchOptions{}
|
|
|
|
patchOpts.ApplyOptions(opts)
|
|
|
|
|
|
|
|
body := obj
|
|
|
|
if patchOpts.SubResourceBody != nil {
|
|
|
|
body = patchOpts.SubResourceBody
|
|
|
|
}
|
|
|
|
|
|
|
|
data, err := patch.Data(body)
|
2020-10-21 05:49:41 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
result := o.Patch(patch.Type()).
|
|
|
|
NamespaceIfScoped(o.GetNamespace(), o.isNamespaced()).
|
|
|
|
Resource(o.resource()).
|
|
|
|
Name(o.GetName()).
|
2023-02-01 17:06:36 +00:00
|
|
|
SubResource(subResource).
|
2020-10-21 05:49:41 +00:00
|
|
|
Body(data).
|
2023-02-01 17:06:36 +00:00
|
|
|
VersionedParams(patchOpts.AsPatchOptions(), uc.paramCodec).
|
2020-10-21 05:49:41 +00:00
|
|
|
Do(ctx).
|
2023-02-01 17:06:36 +00:00
|
|
|
Into(body)
|
2020-10-21 05:49:41 +00:00
|
|
|
|
|
|
|
u.SetGroupVersionKind(gvk)
|
|
|
|
return result
|
|
|
|
}
|