github.com/redhat-appstudio/e2e-tests@v0.0.0-20230619105049-9a422b2094d7/pkg/apis/kubernetes/client.go (about) 1 package client 2 3 import ( 4 "fmt" 5 "os" 6 "time" 7 8 toolchainv1alpha1 "github.com/codeready-toolchain/api/api/v1alpha1" 9 ecp "github.com/enterprise-contract/enterprise-contract-controller/api/v1alpha1" 10 ocpOauth "github.com/openshift/api/config/v1" 11 routev1 "github.com/openshift/api/route/v1" 12 userv1 "github.com/openshift/api/user/v1" 13 routeclientset "github.com/openshift/client-go/route/clientset/versioned" 14 appstudioApi "github.com/redhat-appstudio/application-api/api/v1alpha1" 15 buildservice "github.com/redhat-appstudio/build-service/api/v1alpha1" 16 "github.com/redhat-appstudio/e2e-tests/pkg/sandbox" 17 integrationservice "github.com/redhat-appstudio/integration-service/api/v1alpha1" 18 integrationservicev1beta1 "github.com/redhat-appstudio/integration-service/api/v1beta1" 19 jvmbuildservice "github.com/redhat-appstudio/jvm-build-service/pkg/apis/jvmbuildservice/v1alpha1" 20 jvmbuildserviceclientset "github.com/redhat-appstudio/jvm-build-service/pkg/client/clientset/versioned" 21 gitopsv1alpha1 "github.com/redhat-appstudio/managed-gitops/backend-shared/apis/managed-gitops/v1alpha1" 22 managedgitopsv1alpha1 "github.com/redhat-appstudio/managed-gitops/backend/apis/managed-gitops/v1alpha1" 23 release "github.com/redhat-appstudio/release-service/api/v1alpha1" 24 spi "github.com/redhat-appstudio/service-provider-integration-operator/api/v1beta1" 25 tekton "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" 26 pipelineclientset "github.com/tektoncd/pipeline/pkg/client/clientset/versioned" 27 "k8s.io/apimachinery/pkg/runtime" 28 utilruntime "k8s.io/apimachinery/pkg/util/runtime" 29 "k8s.io/apimachinery/pkg/util/wait" 30 "k8s.io/client-go/dynamic" 31 "k8s.io/client-go/kubernetes" 32 clientgoscheme "k8s.io/client-go/kubernetes/scheme" 33 "k8s.io/client-go/rest" 34 "k8s.io/client-go/tools/clientcmd" 35 crclient "sigs.k8s.io/controller-runtime/pkg/client" 36 "sigs.k8s.io/controller-runtime/pkg/client/config" 37 ) 38 39 const ( 40 DefaultRetryInterval = time.Millisecond * 100 // make it short because a "retry interval" is waited before the first test 41 DefaultTimeout = time.Second * 240 42 ) 43 44 type CustomClient struct { 45 kubeClient *kubernetes.Clientset 46 crClient crclient.Client 47 pipelineClient pipelineclientset.Interface 48 dynamicClient dynamic.Interface 49 jvmbuildserviceClient jvmbuildserviceclientset.Interface 50 routeClient routeclientset.Interface 51 } 52 53 type K8SClient struct { 54 AsKubeAdmin *CustomClient 55 AsKubeDeveloper *CustomClient 56 ProxyUrl string 57 SandboxController *sandbox.SandboxController 58 UserName string 59 UserNamespace string 60 UserToken string 61 } 62 63 var ( 64 scheme = runtime.NewScheme() 65 ) 66 67 func init() { 68 utilruntime.Must(clientgoscheme.AddToScheme(scheme)) 69 utilruntime.Must(appstudioApi.AddToScheme(scheme)) 70 utilruntime.Must(ocpOauth.AddToScheme(scheme)) 71 utilruntime.Must(tekton.AddToScheme(scheme)) 72 utilruntime.Must(routev1.AddToScheme(scheme)) 73 utilruntime.Must(managedgitopsv1alpha1.AddToScheme(scheme)) 74 utilruntime.Must(spi.AddToScheme(scheme)) 75 utilruntime.Must(toolchainv1alpha1.AddToScheme(scheme)) 76 utilruntime.Must(release.AddToScheme(scheme)) 77 utilruntime.Must(gitopsv1alpha1.AddToScheme(scheme)) 78 utilruntime.Must(integrationservice.AddToScheme(scheme)) 79 utilruntime.Must(integrationservicev1beta1.AddToScheme(scheme)) 80 utilruntime.Must(jvmbuildservice.AddToScheme(scheme)) 81 utilruntime.Must(ecp.AddToScheme(scheme)) 82 utilruntime.Must(buildservice.AddToScheme(scheme)) 83 utilruntime.Must(userv1.AddToScheme(scheme)) 84 } 85 86 // Kube returns the clientset for Kubernetes upstream. 87 func (c *CustomClient) KubeInterface() kubernetes.Interface { 88 return c.kubeClient 89 } 90 91 // Return a rest client to perform CRUD operations on Kubernetes objects 92 func (c *CustomClient) KubeRest() crclient.Client { 93 return c.crClient 94 } 95 96 func (c *CustomClient) PipelineClient() pipelineclientset.Interface { 97 return c.pipelineClient 98 } 99 100 func (c *CustomClient) JvmbuildserviceClient() jvmbuildserviceclientset.Interface { 101 return c.jvmbuildserviceClient 102 } 103 104 func (c *CustomClient) RouteClient() routeclientset.Interface { 105 return c.routeClient 106 } 107 108 // Returns a DynamicClient interface. 109 // Note: other client interfaces are likely preferred, except in rare cases. 110 func (c *CustomClient) DynamicClient() dynamic.Interface { 111 return c.dynamicClient 112 } 113 114 // Creates Kubernetes clients: 115 // 1. Will create a kubernetes client from default kubeconfig as kubeadmin 116 // 2. Will create a sandbox user and will generate a client using user token a new client to create resources in RHTAP like a normal user 117 func NewDevSandboxProxyClient(userName string) (*K8SClient, error) { 118 asAdminClient, err := NewAdminKubernetesClient() 119 if err != nil { 120 return nil, err 121 } 122 123 sandboxController, err := sandbox.NewDevSandboxController(asAdminClient.KubeInterface(), asAdminClient.KubeRest()) 124 if err != nil { 125 return nil, err 126 } 127 128 proxyAuthInfo, err := sandboxController.ReconcileUserCreation(userName) 129 if err != nil { 130 return nil, err 131 } 132 133 sandboxProxyClient, err := CreateAPIProxyClient(proxyAuthInfo.UserToken, proxyAuthInfo.ProxyUrl) 134 if err != nil { 135 return nil, err 136 } 137 138 return &K8SClient{ 139 AsKubeAdmin: asAdminClient, 140 AsKubeDeveloper: sandboxProxyClient, 141 ProxyUrl: proxyAuthInfo.ProxyUrl, 142 SandboxController: sandboxController, 143 UserName: proxyAuthInfo.UserName, 144 UserNamespace: proxyAuthInfo.UserNamespace, 145 UserToken: proxyAuthInfo.UserToken, 146 }, nil 147 } 148 149 // Creates a kubernetes client from default kubeconfig. Will take it from KUBECONFIG env if it is defined and if in case is not defined 150 // will create the client from $HOME/.kube/config 151 func NewAdminKubernetesClient() (*CustomClient, error) { 152 adminKubeconfig, err := config.GetConfig() 153 if err != nil { 154 return nil, err 155 } 156 clientSets, err := createClientSetsFromConfig(adminKubeconfig) 157 if err != nil { 158 return nil, err 159 } 160 161 crClient, err := crclient.New(adminKubeconfig, crclient.Options{ 162 Scheme: scheme, 163 }) 164 165 if err != nil { 166 return nil, err 167 } 168 169 return &CustomClient{ 170 kubeClient: clientSets.kubeClient, 171 pipelineClient: clientSets.pipelineClient, 172 dynamicClient: clientSets.dynamicClient, 173 jvmbuildserviceClient: clientSets.jvmbuildserviceClient, 174 routeClient: clientSets.routeClient, 175 crClient: crClient, 176 }, nil 177 } 178 179 // CreateAPIProxyClient creates a client to the RHTAP api proxy using the given user token 180 func CreateAPIProxyClient(usertoken, proxyURL string) (*CustomClient, error) { 181 var proxyCl crclient.Client 182 var initProxyClError error 183 184 apiConfig, err := clientcmd.NewDefaultClientConfigLoadingRules().Load() 185 if err != nil { 186 return nil, fmt.Errorf("error initializing api proxy client config rules %s", err) 187 } 188 189 defaultConfig, err := clientcmd.NewDefaultClientConfig(*apiConfig, &clientcmd.ConfigOverrides{}).ClientConfig() 190 if err != nil { 191 return nil, fmt.Errorf("error initializing default client configs %s", err) 192 } 193 proxyKubeConfig := &rest.Config{ 194 Host: proxyURL, 195 TLSClientConfig: defaultConfig.TLSClientConfig, 196 BearerToken: usertoken, 197 } 198 199 // Getting the proxy client can fail from time to time if the proxy's informer cache has not been 200 // updated yet and we try to create the client to quickly so retry to reduce flakiness. 201 waitErr := wait.Poll(DefaultRetryInterval, DefaultTimeout, func() (done bool, err error) { 202 proxyCl, initProxyClError = crclient.New(proxyKubeConfig, crclient.Options{Scheme: scheme}) 203 return initProxyClError == nil, nil 204 }) 205 if waitErr != nil { 206 return nil, initProxyClError 207 } 208 209 clientSets, err := createClientSetsFromConfig(proxyKubeConfig) 210 if err != nil { 211 return nil, err 212 } 213 214 return &CustomClient{ 215 kubeClient: clientSets.kubeClient, 216 pipelineClient: clientSets.pipelineClient, 217 dynamicClient: clientSets.dynamicClient, 218 jvmbuildserviceClient: clientSets.jvmbuildserviceClient, 219 routeClient: clientSets.routeClient, 220 crClient: proxyCl, 221 }, nil 222 } 223 224 func NewKubeFromKubeConfigFile(kubeconfig string) (*kubernetes.Clientset, error) { 225 kubeConfData, err := os.ReadFile(kubeconfig) 226 if err != nil { 227 return nil, err 228 } 229 230 config, err := clientcmd.RESTConfigFromKubeConfig(kubeConfData) 231 if err != nil { 232 return nil, err 233 } 234 235 return kubernetes.NewForConfig(config) 236 } 237 238 func createClientSetsFromConfig(cfg *rest.Config) (*CustomClient, error) { 239 client, err := kubernetes.NewForConfig(cfg) 240 if err != nil { 241 return nil, err 242 } 243 244 dynamicClient, err := dynamic.NewForConfig(cfg) 245 if err != nil { 246 return nil, err 247 } 248 249 pipelineClient, err := pipelineclientset.NewForConfig(cfg) 250 if err != nil { 251 return nil, err 252 } 253 254 jvmbuildserviceClient, err := jvmbuildserviceclientset.NewForConfig(cfg) 255 if err != nil { 256 return nil, err 257 } 258 259 routeClient, err := routeclientset.NewForConfig(cfg) 260 if err != nil { 261 return nil, err 262 } 263 264 return &CustomClient{ 265 kubeClient: client, 266 pipelineClient: pipelineClient, 267 dynamicClient: dynamicClient, 268 jvmbuildserviceClient: jvmbuildserviceClient, 269 routeClient: routeClient, 270 }, nil 271 }