Skip to content
This repository has been archived by the owner on Jan 19, 2023. It is now read-only.

Commit

Permalink
Handle mutliple CRD versions
Browse files Browse the repository at this point in the history
CRD api has moved from v1beta1 to v1. Handle both methods

Signed-off-by: bryanl <bryanliles@gmail.com>
  • Loading branch information
bryanl committed Dec 17, 2019
1 parent cfabb08 commit b1110c5
Show file tree
Hide file tree
Showing 23 changed files with 936 additions and 581 deletions.
1 change: 1 addition & 0 deletions changelogs/unreleased/405-bryanl
@@ -0,0 +1 @@
Support v1 and v1beta1 CRD API
2 changes: 2 additions & 0 deletions internal/api/content_manager.go
Expand Up @@ -7,6 +7,7 @@ package api

import (
"context"
"fmt"
"strings"
"time"

Expand Down Expand Up @@ -132,6 +133,7 @@ func (cm *ContentManager) generateContent(ctx context.Context, state octant.Stat
state.SetContentPath(notFoundRedirectPath(contentPath))
return component.EmptyContentResponse, true, nil
} else {
fmt.Println("generate content", err)
return component.EmptyContentResponse, false, errors.Wrap(err, "generate content")
}
}
Expand Down
31 changes: 21 additions & 10 deletions internal/describer/crd.go
Expand Up @@ -7,16 +7,17 @@ package describer

import (
"context"
"fmt"

"github.com/pkg/errors"
apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"

"github.com/vmware-tanzu/octant/internal/config"
"github.com/vmware-tanzu/octant/internal/gvk"
"github.com/vmware-tanzu/octant/internal/link"
"github.com/vmware-tanzu/octant/internal/modules/overview/yamlviewer"
"github.com/vmware-tanzu/octant/internal/octant"
"github.com/vmware-tanzu/octant/internal/printer"
"github.com/vmware-tanzu/octant/internal/queryer"
"github.com/vmware-tanzu/octant/internal/resourceviewer"
Expand All @@ -25,7 +26,7 @@ import (
"github.com/vmware-tanzu/octant/pkg/view/component"
)

type crdPrinter func(ctx context.Context, crd *apiextv1beta1.CustomResourceDefinition, object *unstructured.Unstructured, options printer.Options) (component.Component, error)
type crdPrinter func(ctx context.Context, crd, object *unstructured.Unstructured, options printer.Options) (component.Component, error)
type resourceViewerPrinter func(ctx context.Context, object *unstructured.Unstructured, dashConfig config.Dash, q queryer.Queryer) (component.Component, error)
type yamlPrinter func(runtime.Object) (*component.YAML, error)

Expand Down Expand Up @@ -66,14 +67,24 @@ func (c *crd) Describe(ctx context.Context, namespace string, options Options) (
return component.EmptyContentResponse, err
}

// TODO: crd.Spec.Version is incorrect. Use crd.Spec.Version instead.
gvk := schema.GroupVersionKind{
Group: crd.Spec.Group,
Version: crd.Spec.Version,
Kind: crd.Spec.Names.Kind,
octantCRD, err := octant.NewCustomResourceDefinition(crd)
if err != nil {
return component.EmptyContentResponse, err
}

crdVersions, err := octantCRD.Versions()
if err != nil {
return component.EmptyContentResponse, fmt.Errorf("get versions for crd %s: %w", crd.GetName(), err)
} else if len(crdVersions) == 0 {
return component.EmptyContentResponse, fmt.Errorf("crd %s has no no versions", crd.GetName())
}

crGVK, err := gvk.CustomResource(crd, crdVersions[0])
if err != nil {
return component.EmptyContentResponse, fmt.Errorf("get gvk for custom resource")
}

apiVersion, kind := gvk.ToAPIVersionAndKind()
apiVersion, kind := crGVK.ToAPIVersionAndKind()

key := store.Key{
Namespace: namespace,
Expand All @@ -93,7 +104,7 @@ func (c *crd) Describe(ctx context.Context, namespace string, options Options) (

title := component.Title(
component.NewText("Custom Resources"),
component.NewText(crd.Name),
component.NewText(crd.GetName()),
component.NewText(object.GetName()))

iconName, iconSource := loadIcon(icon.CustomResourceDefinition)
Expand Down
73 changes: 19 additions & 54 deletions internal/describer/crd_list.go
Expand Up @@ -7,27 +7,16 @@ package describer

import (
"context"
"fmt"

"github.com/pkg/errors"
apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime/schema"

"github.com/vmware-tanzu/octant/internal/link"
"github.com/vmware-tanzu/octant/internal/modules/overview/yamlviewer"
"github.com/vmware-tanzu/octant/internal/printer"
"github.com/vmware-tanzu/octant/pkg/icon"
"github.com/vmware-tanzu/octant/pkg/store"
"github.com/vmware-tanzu/octant/pkg/view/component"
)

type crdListPrinter func(
crdName string,
crd *apiextv1beta1.CustomResourceDefinition,
objects *unstructured.UnstructuredList,
linkGenerator link.Interface,
isLoading bool) (component.Component, error)
type crdListPrinter func(crdObject *unstructured.Unstructured, resources *unstructured.UnstructuredList, version string, linkGenerator link.Interface) (component.Component, error)

type crdListDescriptionOption func(*crdList)

Expand Down Expand Up @@ -57,63 +46,39 @@ func newCRDList(name, path string, options ...crdListDescriptionOption) *crdList

func (cld *crdList) Describe(ctx context.Context, namespace string, options Options) (component.ContentResponse, error) {
objectStore := options.ObjectStore()

crd, err := CustomResourceDefinition(ctx, cld.name, objectStore)
if err != nil {
return component.EmptyContentResponse, err
}

objects, isLoading, err := ListCustomResources(ctx, crd, namespace, objectStore, options.LabelSet)
if err != nil {
return component.EmptyContentResponse, err
printOptions := printer.Options{
DashConfig: options.Dash,
Link: options.Link,
}

table, err := cld.printer(cld.name, crd, objects, options.Link, isLoading)
view, err := printer.CustomResourceDefinitionHandler(ctx, crd, namespace, printOptions)
if err != nil {
return component.EmptyContentResponse, err
}
view.SetAccessor("summary")

list := component.NewList(fmt.Sprintf("Custom Resources / %s", cld.name), []component.Component{
table,
})
title := component.Title(
component.NewText("Custom Resources"),
component.NewText(crd.GetName()))

iconName, iconSource := loadIcon(icon.CustomResourceDefinition)
list.SetIcon(iconName, iconSource)
contentResponse := component.NewContentResponse(title)
contentResponse.Add(view)

return component.ContentResponse{
Components: []component.Component{list},
}, nil
}

func ListCustomResources(
ctx context.Context,
crd *apiextv1beta1.CustomResourceDefinition,
namespace string,
o store.Store,
selector *labels.Set) (*unstructured.UnstructuredList, bool, error) {
if crd == nil {
return nil, false, errors.New("crd is nil")
}
gvk := schema.GroupVersionKind{
Group: crd.Spec.Group,
Version: crd.Spec.Version,
Kind: crd.Spec.Names.Kind,
}

apiVersion, kind := gvk.ToAPIVersionAndKind()

key := store.Key{
Namespace: namespace,
APIVersion: apiVersion,
Kind: kind,
Selector: selector,
}

objects, isLoading, err := o.List(ctx, key)
yamlView, err := yamlviewer.ToComponent(crd)
if err != nil {
return nil, false, errors.Wrapf(err, "listing custom resources for %q", crd.Name)
return component.EmptyContentResponse, err
}
yamlView.SetAccessor("yaml")

contentResponse.Add(yamlView)

return objects, isLoading, nil
return *contentResponse, nil
}

func (cld *crdList) PathFilters() []PathFilter {
Expand Down
82 changes: 0 additions & 82 deletions internal/describer/crd_list_test.go

This file was deleted.

73 changes: 60 additions & 13 deletions internal/describer/crd_section.go
Expand Up @@ -7,10 +7,14 @@ package describer

import (
"context"
"path"
"sort"
"sync"

"github.com/vmware-tanzu/octant/internal/gvk"
"github.com/vmware-tanzu/octant/internal/log"
"github.com/vmware-tanzu/octant/internal/octant"
"github.com/vmware-tanzu/octant/pkg/store"
"github.com/vmware-tanzu/octant/pkg/view/component"
)

Expand Down Expand Up @@ -57,28 +61,71 @@ func (csd *CRDSection) Describe(ctx context.Context, namespace string, options O

sort.Strings(names)

list := component.NewList("Custom Resources", nil)
// list := component.NewList("Custom Resources", nil)

tableCols := component.NewTableCols("Name", "Labels", "Age")
table := component.NewTable("Custom Resources", "", tableCols)

for _, name := range names {
resp, err := csd.describers[name].Describe(ctx, namespace, options)
if err != nil {
return component.EmptyContentResponse, err
}
// resp, err := csd.describers[name].Describe(ctx, namespace, options)
// if err != nil {
// return component.EmptyContentResponse, err
// }

switch d := csd.describers[name].(type) {
case *crdList:
key := store.KeyFromGroupVersionKind(gvk.CustomResourceDefinition)
key.Name = d.name
crd, _, err := options.ObjectStore().Get(ctx, key)
if err != nil {
return component.EmptyContentResponse, err
}

crdObject, err := octant.NewCustomResourceDefinition(crd)
if err != nil {
return component.EmptyContentResponse, err
}

versions, err := crdObject.Versions()
if err != nil {
return component.EmptyContentResponse, err
}

for i := range resp.Components {
if nestedList, ok := resp.Components[i].(*component.List); ok {
for i := range nestedList.Config.Items {
item := nestedList.Config.Items[i]
if !item.IsEmpty() {
list.Add(item)
}
count := 0
for _, version := range versions {
crGVK, err := gvk.CustomResource(crd, version)
if err != nil {
return component.EmptyContentResponse, err
}
key2 := store.KeyFromGroupVersionKind(crGVK)
key2.Namespace = namespace
list, _, err := options.ObjectStore().List(ctx, key2)
if err != nil {
return component.EmptyContentResponse, err
}
count += len(list.Items)
}

if count > 0 {
row := component.TableRow{}

ref := path.Join("/overview/namespace", namespace, "custom-resources", crd.GetName())
if namespace == "" {
ref = path.Join("/cluster-overview/custom-resources", crd.GetName())
}

row["Name"] = component.NewLink("", crd.GetName(), ref)
row["Labels"] = component.NewLabels(crd.GetLabels())
row["Age"] = component.NewTimestamp(crd.GetCreationTimestamp().Time)

table.Add(row)
}

}
}

cr := component.ContentResponse{
Components: []component.Component{list},
Components: []component.Component{table},
Title: component.TitleFromString(csd.title),
}

Expand Down

0 comments on commit b1110c5

Please sign in to comment.