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 }