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  }