...

Source file src/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/clientbacked_dryrun.go

Documentation: k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient

     1  /*
     2  Copyright 2017 The Kubernetes Authors.
     3  
     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
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    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.
    15  */
    16  
    17  package apiclient
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"fmt"
    23  
    24  	"github.com/pkg/errors"
    25  
    26  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    27  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    28  	"k8s.io/apimachinery/pkg/runtime"
    29  	"k8s.io/client-go/dynamic"
    30  	clientset "k8s.io/client-go/kubernetes"
    31  	clientsetscheme "k8s.io/client-go/kubernetes/scheme"
    32  	"k8s.io/client-go/rest"
    33  	core "k8s.io/client-go/testing"
    34  	"k8s.io/client-go/tools/clientcmd"
    35  )
    36  
    37  // ClientBackedDryRunGetter implements the DryRunGetter interface for use in NewDryRunClient() and proxies all GET and LIST requests to the backing API server reachable via rest.Config
    38  type ClientBackedDryRunGetter struct {
    39  	client        clientset.Interface
    40  	dynamicClient dynamic.Interface
    41  }
    42  
    43  // InitDryRunGetter should implement the DryRunGetter interface
    44  var _ DryRunGetter = &ClientBackedDryRunGetter{}
    45  
    46  // NewClientBackedDryRunGetter creates a new ClientBackedDryRunGetter instance based on the rest.Config object
    47  func NewClientBackedDryRunGetter(config *rest.Config) (*ClientBackedDryRunGetter, error) {
    48  	client, err := clientset.NewForConfig(config)
    49  	if err != nil {
    50  		return nil, err
    51  	}
    52  	dynamicClient, err := dynamic.NewForConfig(config)
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  
    57  	return &ClientBackedDryRunGetter{
    58  		client:        client,
    59  		dynamicClient: dynamicClient,
    60  	}, nil
    61  }
    62  
    63  // NewClientBackedDryRunGetterFromKubeconfig creates a new ClientBackedDryRunGetter instance from the given KubeConfig file
    64  func NewClientBackedDryRunGetterFromKubeconfig(file string) (*ClientBackedDryRunGetter, error) {
    65  	config, err := clientcmd.LoadFromFile(file)
    66  	if err != nil {
    67  		return nil, errors.Wrap(err, "failed to load kubeconfig")
    68  	}
    69  	clientConfig, err := clientcmd.NewDefaultClientConfig(*config, &clientcmd.ConfigOverrides{}).ClientConfig()
    70  	if err != nil {
    71  		return nil, errors.Wrap(err, "failed to create API client configuration from kubeconfig")
    72  	}
    73  	return NewClientBackedDryRunGetter(clientConfig)
    74  }
    75  
    76  // HandleGetAction handles GET actions to the dryrun clientset this interface supports
    77  func (clg *ClientBackedDryRunGetter) HandleGetAction(action core.GetAction) (bool, runtime.Object, error) {
    78  	unstructuredObj, err := clg.dynamicClient.Resource(action.GetResource()).Namespace(action.GetNamespace()).Get(context.TODO(), action.GetName(), metav1.GetOptions{})
    79  	if err != nil {
    80  		// Inform the user that the requested object wasn't found.
    81  		printIfNotExists(err)
    82  		return true, nil, err
    83  	}
    84  	newObj, err := decodeUnstructuredIntoAPIObject(action, unstructuredObj)
    85  	if err != nil {
    86  		fmt.Printf("error after decode: %v %v\n", unstructuredObj, err)
    87  		return true, nil, err
    88  	}
    89  	return true, newObj, err
    90  }
    91  
    92  // HandleListAction handles LIST actions to the dryrun clientset this interface supports
    93  func (clg *ClientBackedDryRunGetter) HandleListAction(action core.ListAction) (bool, runtime.Object, error) {
    94  	listOpts := metav1.ListOptions{
    95  		LabelSelector: action.GetListRestrictions().Labels.String(),
    96  		FieldSelector: action.GetListRestrictions().Fields.String(),
    97  	}
    98  
    99  	unstructuredList, err := clg.dynamicClient.Resource(action.GetResource()).Namespace(action.GetNamespace()).List(context.TODO(), listOpts)
   100  	if err != nil {
   101  		return true, nil, err
   102  	}
   103  	newObj, err := decodeUnstructuredIntoAPIObject(action, unstructuredList)
   104  	if err != nil {
   105  		fmt.Printf("error after decode: %v %v\n", unstructuredList, err)
   106  		return true, nil, err
   107  	}
   108  	return true, newObj, err
   109  }
   110  
   111  // Client gets the backing clientset.Interface
   112  func (clg *ClientBackedDryRunGetter) Client() clientset.Interface {
   113  	return clg.client
   114  }
   115  
   116  // decodeUnstructuredIntoAPIObject converts the *unversioned.Unversioned object returned from the dynamic client
   117  // to bytes; and then decodes it back _to an external api version (k8s.io/api)_ using the normal API machinery
   118  func decodeUnstructuredIntoAPIObject(action core.Action, unstructuredObj runtime.Unstructured) (runtime.Object, error) {
   119  	objBytes, err := json.Marshal(unstructuredObj)
   120  	if err != nil {
   121  		return nil, err
   122  	}
   123  	newObj, err := runtime.Decode(clientsetscheme.Codecs.UniversalDecoder(action.GetResource().GroupVersion()), objBytes)
   124  	if err != nil {
   125  		return nil, err
   126  	}
   127  	return newObj, nil
   128  }
   129  
   130  func printIfNotExists(err error) {
   131  	if apierrors.IsNotFound(err) {
   132  		fmt.Println("[dryrun] The GET request didn't yield any result, the API Server returned a NotFound error.")
   133  	}
   134  }
   135  

View as plain text