Skip to content

Commit 4016e37

Browse files
committed
start wiring module to binding
1 parent 9369891 commit 4016e37

7 files changed

Lines changed: 333 additions & 189 deletions

File tree

backend/config.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import (
3939

4040
kuberesources "github.com/kube-bind/kube-bind/backend/kubernetes/resources"
4141
"github.com/kube-bind/kube-bind/backend/options"
42+
catalogv1alpha1 "github.com/kube-bind/kube-bind/sdk/apis/catalog/v1alpha1"
4243
kubebindv1alpha1 "github.com/kube-bind/kube-bind/sdk/apis/kubebind/v1alpha1"
4344
kubebindv1alpha2 "github.com/kube-bind/kube-bind/sdk/apis/kubebind/v1alpha2"
4445
)
@@ -88,6 +89,9 @@ func NewConfig(options *options.CompletedOptions) (*Config, error) {
8889
if err := kubebindv1alpha2.AddToScheme(scheme); err != nil {
8990
return nil, fmt.Errorf("error adding kubebind scheme: %w", err)
9091
}
92+
if err := catalogv1alpha1.AddToScheme(scheme); err != nil {
93+
return nil, fmt.Errorf("error adding catalog scheme: %w", err)
94+
}
9195

9296
config.Scheme = scheme
9397

backend/http/handler.go

Lines changed: 45 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -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

5148
var (
@@ -346,12 +343,13 @@ func createSessionState(authCode *AuthCode, token *oauth2.Token) (*session.State
346343
}
347344

348345
type 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

437416
func (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
}

backend/kubernetes/manager.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
mcmanager "sigs.k8s.io/multicluster-runtime/pkg/manager"
3434

3535
kuberesources "github.com/kube-bind/kube-bind/backend/kubernetes/resources"
36+
catalogv1alpha1 "github.com/kube-bind/kube-bind/sdk/apis/catalog/v1alpha1"
3637
kubebindv1alpha2 "github.com/kube-bind/kube-bind/sdk/apis/kubebind/v1alpha2"
3738
)
3839

@@ -165,6 +166,38 @@ func (m *Manager) ListCustomResourceDefinitions(ctx context.Context, cluster str
165166
return &crds, nil
166167
}
167168

169+
func (m *Manager) ListCollections(ctx context.Context, cluster string) (*catalogv1alpha1.CollectionList, error) {
170+
cl, err := m.manager.GetCluster(ctx, cluster)
171+
if err != nil {
172+
return nil, err
173+
}
174+
c := cl.GetClient()
175+
176+
var collections catalogv1alpha1.CollectionList
177+
err = c.List(ctx, &collections)
178+
if err != nil {
179+
return nil, err
180+
}
181+
182+
return &collections, nil
183+
}
184+
185+
func (m *Manager) GetModule(ctx context.Context, cluster, name string) (*catalogv1alpha1.Module, error) {
186+
cl, err := m.manager.GetCluster(ctx, cluster)
187+
if err != nil {
188+
return nil, err
189+
}
190+
c := cl.GetClient()
191+
192+
var module catalogv1alpha1.Module
193+
err = c.Get(ctx, types.NamespacedName{Name: name}, &module)
194+
if err != nil {
195+
return nil, err
196+
}
197+
198+
return &module, nil
199+
}
200+
168201
func (m *Manager) ListDynamicResources(ctx context.Context, cluster string, gvk schema.GroupVersionKind, selector labels.Selector) (*unstructured.UnstructuredList, error) {
169202
cl, err := m.manager.GetCluster(ctx, cluster)
170203
if err != nil {

backend/kubernetes/resources/resources.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,6 @@ const (
2525
KubeconfigSecretName = "kubeconfig"
2626
ClusterBindingName = "cluster"
2727

28-
// TODO(MQ): maybe think of a better label name.
28+
// TODO(mjudeikis): maybe think of a better label name.
2929
ExportedCRDsLabel = "kube-bind.io/exported"
3030
)

backend/template/login.html

Lines changed: 0 additions & 49 deletions
This file was deleted.

0 commit comments

Comments
 (0)