github.com/oam-dev/kubevela@v1.9.11/pkg/cmd/factory.go (about)

     1  /*
     2  Copyright 2022 The KubeVela 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 cmd
    18  
    19  import (
    20  	"sync"
    21  
    22  	"k8s.io/client-go/rest"
    23  	"k8s.io/client-go/util/flowcontrol"
    24  	"sigs.k8s.io/controller-runtime/pkg/client"
    25  
    26  	"github.com/kubevela/pkg/multicluster"
    27  
    28  	cmdutil "github.com/oam-dev/kubevela/pkg/cmd/util"
    29  	"github.com/oam-dev/kubevela/pkg/utils/common"
    30  )
    31  
    32  // Factory client factory for running command
    33  type Factory interface {
    34  	Client() client.Client
    35  	Config() *rest.Config
    36  }
    37  
    38  // ClientGetter function for getting client
    39  type ClientGetter func() (client.Client, error)
    40  
    41  // ConfigGetter function for getting config
    42  type ConfigGetter func() (*rest.Config, error)
    43  
    44  type delegateFactory struct {
    45  	ClientGetter
    46  	ConfigGetter
    47  }
    48  
    49  // Client return the client for command line use, interrupt if error encountered
    50  func (f *delegateFactory) Client() client.Client {
    51  	cli, err := f.ClientGetter()
    52  	cmdutil.CheckErr(err)
    53  	return cli
    54  }
    55  
    56  // Config return the kubeConfig for command line use
    57  func (f *delegateFactory) Config() *rest.Config {
    58  	cfg, err := f.ConfigGetter()
    59  	cmdutil.CheckErr(err)
    60  	return cfg
    61  }
    62  
    63  // NewDelegateFactory create a factory based on getter function
    64  func NewDelegateFactory(clientGetter ClientGetter, configGetter ConfigGetter) Factory {
    65  	return &delegateFactory{ClientGetter: clientGetter, ConfigGetter: configGetter}
    66  }
    67  
    68  var (
    69  	// DefaultRateLimiter default rate limiter for cmd client
    70  	DefaultRateLimiter = flowcontrol.NewTokenBucketRateLimiter(100, 200)
    71  )
    72  
    73  type defaultFactory struct {
    74  	sync.Mutex
    75  	cfg *rest.Config
    76  	cli client.Client
    77  }
    78  
    79  // Client return the client for command line use, interrupt if error encountered
    80  func (f *defaultFactory) Client() client.Client {
    81  	f.Lock()
    82  	defer f.Unlock()
    83  	if f.cli == nil {
    84  		var err error
    85  		f.cli, err = client.New(f.cfg, client.Options{Scheme: common.Scheme})
    86  		cmdutil.CheckErr(err)
    87  	}
    88  	return f.cli
    89  }
    90  
    91  // Config return the kubeConfig for command line use
    92  func (f *defaultFactory) Config() *rest.Config {
    93  	return f.cfg
    94  }
    95  
    96  // NewDefaultFactory create a factory based on client getter function
    97  func NewDefaultFactory(cfg *rest.Config) Factory {
    98  	copiedCfg := *cfg
    99  	copiedCfg.RateLimiter = DefaultRateLimiter
   100  	copiedCfg.Wrap(multicluster.NewTransportWrapper())
   101  	return &defaultFactory{cfg: &copiedCfg}
   102  }
   103  
   104  type deferredFactory struct {
   105  	sync.Mutex
   106  	Factory
   107  	ConfigGetter
   108  }
   109  
   110  // NewDeferredFactory create a factory that will only get KubeConfig until it is needed for the first time
   111  func NewDeferredFactory(getter ConfigGetter) Factory {
   112  	return &deferredFactory{ConfigGetter: getter}
   113  }
   114  
   115  func (f *deferredFactory) init() {
   116  	cfg, err := f.ConfigGetter()
   117  	cmdutil.CheckErr(err)
   118  	f.Factory = NewDefaultFactory(cfg)
   119  }
   120  
   121  // Config return the kubeConfig
   122  func (f *deferredFactory) Config() *rest.Config {
   123  	f.Lock()
   124  	defer f.Unlock()
   125  	if f.Factory == nil {
   126  		f.init()
   127  	}
   128  	return f.Factory.Config()
   129  }
   130  
   131  // Client return the kubeClient
   132  func (f *deferredFactory) Client() client.Client {
   133  	f.Lock()
   134  	defer f.Unlock()
   135  	if f.Factory == nil {
   136  		f.init()
   137  	}
   138  	return f.Factory.Client()
   139  }
   140  
   141  type testFactory struct {
   142  	cfg *rest.Config
   143  	cli client.Client
   144  }
   145  
   146  // NewTestFactory new a factory for the testing
   147  func NewTestFactory(cfg *rest.Config,
   148  	cli client.Client) Factory {
   149  	return &testFactory{cli: cli, cfg: cfg}
   150  }
   151  
   152  func (t *testFactory) Client() client.Client {
   153  	return t.cli
   154  }
   155  func (t *testFactory) Config() *rest.Config {
   156  	return t.cfg
   157  }