@@ -33,19 +33,16 @@ import (
3333 "github.com/gorilla/securecookie"
3434 "golang.org/x/oauth2"
3535 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
36- "k8s.io/apimachinery/pkg/labels"
3736 "k8s.io/apimachinery/pkg/runtime"
38- "k8s.io/apimachinery/pkg/runtime/schema"
3937 componentbaseversion "k8s.io/component-base/version"
4038 "k8s.io/klog/v2"
4139
4240 "github.com/kube-bind/kube-bind/backend/kubernetes"
43- "github.com/kube-bind/kube-bind/backend/kubernetes/resources"
4441 "github.com/kube-bind/kube-bind/backend/session"
4542 "github.com/kube-bind/kube-bind/backend/template"
4643 bindversion "github.com/kube-bind/kube-bind/pkg/version"
44+ catalogv1alpha1 "github.com/kube-bind/kube-bind/sdk/apis/catalog/v1alpha1"
4745 kubebindv1alpha2 "github.com/kube-bind/kube-bind/sdk/apis/kubebind/v1alpha2"
48- "github.com/kube-bind/kube-bind/sdk/apis/kubebind/v1alpha2/helpers"
4946)
5047
5148var (
@@ -346,12 +343,13 @@ func createSessionState(authCode *AuthCode, token *oauth2.Token) (*session.State
346343}
347344
348345type UISchema struct {
349- Name string
350- Version string
351- Group string
352- Kind string
353- Scope string // "Namespaced" or "Cluster"
354- Resource string
346+ Scope string // "Namespaced" or "Cluster"
347+
348+ Name string
349+ Description string
350+
351+ Resources []kubebindv1alpha2.APIServiceExportResource
352+ PermissionClaims []kubebindv1alpha2.PermissionClaim
355353
356354 // SessionID
357355 SessionID string
@@ -376,44 +374,25 @@ func (h *handler) handleResources(w http.ResponseWriter, r *http.Request) {
376374 return
377375 }
378376
379- exportedSchemas , err := h .getBackendDynamicResource (r .Context (), providerCluster )
377+ modules , err := h .listCollectionModules (r .Context (), providerCluster )
380378 if err != nil {
381379 logger .Error (err , "failed to get dynamic resources" )
382380 http .Error (w , "internal error" , http .StatusInternalServerError )
383381 return
384382 }
385383
386- result := make ([]UISchema , 0 , len (exportedSchemas ))
387- for _ , item := range exportedSchemas {
384+ result := make ([]UISchema , 0 , len (modules . Items ))
385+ for _ , item := range modules . Items {
388386 if ! strings .EqualFold (h .scope .String (), string (item .Spec .Scope )) && h .scope != kubebindv1alpha2 .ClusterScope {
389387 continue
390388 }
391389
392- if len (item .Spec .Versions ) == 0 {
393- logger .Error (fmt .Errorf ("no versions found" ), "skipping schema" , "name" , item .Name )
394- continue
395- }
396- // pick first served version
397- ver := ""
398- for _ , v := range item .Spec .Versions {
399- if v .Served {
400- ver = v .Name
401- break
402- }
403- }
404- if ver == "" {
405- logger .Error (fmt .Errorf ("no served versions found" ), "skipping schema" , "name" , item .Name )
406- continue
407- }
408390 result = append (result , UISchema {
409- Name : item .GetName (),
410- Kind : item .Spec .Names .Kind ,
411- Scope : string (item .Spec .Scope ),
412- Version : ver ,
413- Group : item .Spec .Group ,
414- // Important: This MUST be used as UI button class in the url, so tests can 'click it' based on it.
415- Resource : item .Spec .Names .Plural ,
416- SessionID : sessionID ,
391+ Name : item .GetName (),
392+ Scope : string (item .Spec .Scope ),
393+ PermissionClaims : item .Spec .PermissionClaims ,
394+ Resources : item .Spec .Resources ,
395+ SessionID : sessionID ,
417396 })
418397 }
419398
@@ -436,9 +415,7 @@ func (h *handler) handleResources(w http.ResponseWriter, r *http.Request) {
436415
437416func (h * handler ) handleBind (w http.ResponseWriter , r * http.Request ) {
438417 logger := getLogger (r )
439- group := r .URL .Query ().Get ("group" )
440- resource := r .URL .Query ().Get ("resource" )
441- version := r .URL .Query ().Get ("version" )
418+ moduleName := r .URL .Query ().Get ("module" )
442419 providerCluster := mux .Vars (r )["cluster" ]
443420
444421 prepareNoCache (w )
@@ -466,24 +443,25 @@ func (h *handler) handleBind(w http.ResponseWriter, r *http.Request) {
466443 return
467444 }
468445
446+ // Module consist of many resources and permissionClaims. Read it and translate to
447+ module , err := h .kubeManager .GetModule (r .Context (), providerCluster , moduleName )
448+ if err != nil {
449+ logger .Error (err , "failed to get module" )
450+ http .Error (w , "internal error" , http .StatusInternalServerError )
451+ return
452+ }
453+
469454 request := kubebindv1alpha2.APIServiceExportRequestResponse {
470455 TypeMeta : metav1.TypeMeta {
471456 APIVersion : kubebindv1alpha2 .SchemeGroupVersion .String (),
472457 Kind : "APIServiceExportRequest" ,
473458 },
474459 ObjectMeta : kubebindv1alpha2.NameObjectMeta {
475- // this is good for one resource. If there are more (in the future),
476- // we need a better name heuristic. Note: it does not have to be unique.
477- // But pretty is better.
478- Name : resource + "." + group ,
460+ Name : moduleName ,
479461 },
480462 Spec : kubebindv1alpha2.APIServiceExportRequestSpec {
481- Resources : []kubebindv1alpha2.APIServiceExportRequestResource {
482- {
483- GroupResource : kubebindv1alpha2.GroupResource {Group : group , Resource : resource },
484- Versions : []string {version },
485- },
486- },
463+ Resources : module .Spec .Resources ,
464+ PermissionClaims : module .Spec .PermissionClaims ,
487465 },
488466 }
489467
@@ -543,34 +521,27 @@ func mustRead(f func(name string) ([]byte, error), name string) string {
543521 return string (bs )
544522}
545523
546- func (h * handler ) getBackendDynamicResource (ctx context.Context , cluster string ) (kubebindv1alpha2.ExportedSchemas , error ) {
547- labelSelector := labels.Set {
548- resources .ExportedCRDsLabel : "true" ,
549- }
550-
551- parts := strings .SplitN (h .schemaSource , "." , 3 )
552- if len (parts ) != 3 { // We check this in validation, but just in case.
553- return nil , fmt .Errorf ("invalid schema source: %q" , h .schemaSource )
554- }
555-
556- gvk := schema.GroupVersionKind {
557- Kind : parts [0 ],
558- Version : parts [1 ],
559- Group : parts [2 ],
560- }
561- list , err := h .kubeManager .ListDynamicResources (ctx , cluster , gvk , labelSelector .AsSelector ())
524+ // listCollectionModules fetches the list of Collections from the backend cluster.
525+ // Flow is:
526+ // 1. List Collection and check what modules we are targeting
527+ // 2. Get modules from the backend cluster and consutruct shallow-bound schemas (no crd content)
528+ func (h * handler ) listCollectionModules (ctx context.Context , cluster string ) (* catalogv1alpha1.ModuleList , error ) {
529+ collections , err := h .kubeManager .ListCollections (ctx , cluster )
562530 if err != nil {
563- return nil , fmt .Errorf ("failed to list resources: %w" , err )
531+
532+ return nil , fmt .Errorf ("failed to list collections: %w" , err )
564533 }
565534
566- boundSchemas := make (kubebindv1alpha2.ExportedSchemas , len (list .Items ))
567- for _ , item := range list .Items {
568- boundSchema , err := helpers .UnstructuredToBoundSchema (item )
569- if err != nil {
570- return nil , err
535+ modules := & catalogv1alpha1.ModuleList {}
536+ for _ , collection := range collections .Items {
537+ for _ , m := range collection .Spec .Modules {
538+ module , err := h .kubeManager .GetModule (ctx , cluster , m .Name )
539+ if err != nil {
540+ return nil , fmt .Errorf ("failed to get module %q: %w" , m .Name , err )
541+ }
542+ modules .Items = append (modules .Items , * module )
571543 }
572- boundSchemas [boundSchema .ResourceGroupName ()] = boundSchema
573544 }
574545
575- return boundSchemas , nil
546+ return modules , nil
576547}
0 commit comments