Reduce plugin to its minimal state (#4)

This commit is contained in:
Jordan Jensen 2019-09-20 16:51:52 -07:00 committed by Gary Smith
parent 85c3834a9e
commit 77e9f17d4c
2 changed files with 10 additions and 138 deletions

View File

@ -3,6 +3,7 @@ package main
import (
"fmt"
"log"
"opendev.org/airship/airshipui/internal/plugin"
)

View File

@ -6,36 +6,19 @@ SPDX-License-Identifier: Apache-2.0
package plugin
import (
"fmt"
"time"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/runtime/schema"
"github.com/vmware/octant/pkg/navigation"
"github.com/vmware/octant/pkg/plugin"
"github.com/vmware/octant/pkg/plugin/service"
"github.com/vmware/octant/pkg/store"
"github.com/vmware/octant/pkg/view/component"
"github.com/vmware/octant/pkg/view/flexlayout"
"github.com/vmware/octant/pkg/navigation"
"github.com/vmware/octant/pkg/plugin"
"github.com/vmware/octant/pkg/plugin/service"
"github.com/vmware/octant/pkg/view/component"
)
func Register(name string, description string) (*service.Plugin, error) {
// This plugin is interested in Pods
podGVK := schema.GroupVersionKind{Version: "v1", Kind: "Pod"}
// Tell Octant to call this plugin when printing configuration or tabs for Pods
capabilities := &plugin.Capabilities{
SupportsPrinterConfig: []schema.GroupVersionKind{podGVK},
SupportsTab: []schema.GroupVersionKind{podGVK},
IsModule: true,
IsModule: true,
}
// Set up what should happen when Octant calls this plugin.
options := []service.PluginOption{
service.WithPrinter(handlePrint),
service.WithTabPrinter(handleTab),
service.WithNavigation(handleNavigation, initRoutes),
}
@ -43,113 +26,14 @@ func Register(name string, description string) (*service.Plugin, error) {
return service.Register(name, description, capabilities, options...)
}
// handleTab is called when Octant wants to print a tab for an object.
func handleTab(request *service.PrintRequest) (plugin.TabResponse, error) {
if request.Object == nil {
return plugin.TabResponse{}, errors.New("object is nil")
}
// Octant uses flex layouts to display information. It's a flexible
// grid. A flex layout is composed of multiple section. Each section
// can contain multiple components. Components are displayed given
// a width. In the case below, the width is half of the visible space.
// Create sections to separate your components as each section will
// start a new row.
layout := flexlayout.New()
section := layout.AddSection()
// Octant contain's a library of components that can be used to display content.
// This example uses markdown text.
contents := component.NewMarkdownText("content from a *plugin*")
err := section.Add(contents, component.WidthHalf)
if err != nil {
return plugin.TabResponse{}, err
}
// In this example, this plugin will tell Octant to create a new
// tab when showing pods. This tab's name will be "Extra Pod Details".
tab := component.NewTabWithContents(*layout.ToComponent("Extra Pod Details"))
return plugin.TabResponse{Tab: tab}, nil
}
// handlePrint is called when Octant wants to print an object.
func handlePrint(request *service.PrintRequest) (plugin.PrintResponse, error) {
if request.Object == nil {
return plugin.PrintResponse{}, errors.Errorf("object is nil")
}
// load an object from the cluster and use that object to create a response.
// Octant has a helper function to generate a key from an object. The key
// is used to find the object in the cluster.
key, err := store.KeyFromObject(request.Object)
if err != nil {
return plugin.PrintResponse{}, err
}
u, found, err := request.DashboardClient.Get(request.Context(), key)
if err != nil {
return plugin.PrintResponse{}, err
}
// The plugin can check if the object it requested exists.
if !found {
return plugin.PrintResponse{}, errors.New("object doesn't exist")
}
// Octant has a component library that can be used to build content for a plugin.
// In this case, the plugin is creating a card.
podCard := component.NewCard(fmt.Sprintf("Extra Output for %s", u.GetName()))
podCard.SetBody(component.NewMarkdownText("This output was generated from _octant-sample-plugin_"))
msg := fmt.Sprintf("update from plugin at %s", time.Now().Format(time.RFC3339))
// When printing an object, you can create multiple types of content. In this
// example, the plugin is:
//
// * adding a field to the configuration section for this object.
// * adding a field to the status section for this object.
// * create a new piece of content that will be embedded in the
// summary section for the component.
return plugin.PrintResponse{
Config: []component.SummarySection{
{Header: "from-plugin", Content: component.NewText(msg)},
},
Status: []component.SummarySection{
{Header: "from-plugin", Content: component.NewText(msg)},
},
Items: []component.FlexLayoutItem{
{
Width: component.WidthHalf,
View: podCard,
},
},
}, nil
}
// handlePrint creates a navigation tree for this plugin. Navigation is dynamic and will
// be called frequently from Octant. Navigation is a tree of `Navigation` structs.
// The plugin can use whatever paths it likes since these paths can be namespaced to the
// the plugin.
func handleNavigation(request *service.NavigationRequest) (navigation.Navigation, error) {
return navigation.Navigation{
Title: "Sample Plugin",
Title: "Airship UI",
Path: request.GeneratePath(),
Children: []navigation.Navigation{
{
Title: "Nested Once",
Path: request.GeneratePath("nested-once"),
IconName: "folder",
Children: []navigation.Navigation{
{
Title: "Nested Twice",
Path: request.GeneratePath("nested-once", "nested-twice"),
IconName: "folder",
},
},
},
},
IconName: "cloud",
}, nil
}
@ -157,24 +41,11 @@ func handleNavigation(request *service.NavigationRequest) (navigation.Navigation
// initRoutes routes for this plugin. In this example, there is a global catch all route
// that will return the content for every single path.
func initRoutes(router *service.Router) {
gen := func(name, accessor, requestPath string) component.Component {
cardBody := component.NewText(fmt.Sprintf("hello from plugin: path %s", requestPath))
card := component.NewCard(fmt.Sprintf("My Card - %s", name))
card.SetBody(cardBody)
cardList := component.NewCardList(name)
cardList.AddCard(*card)
cardList.SetAccessor(accessor)
return cardList
}
router.HandleFunc("*", func(request *service.Request) (component.ContentResponse, error) {
// For each page, generate two tabs with a some content.
component1 := gen("Tab 1", "tab1", request.Path)
component2 := gen("Tab 2", "tab2", request.Path)
contentResponse := component.NewContentResponse(component.TitleFromString("Airship UI"))
contentResponse := component.NewContentResponse(component.TitleFromString("Example"))
contentResponse.Add(component1, component2)
text := component.NewText("This is the Airship UI plugin.")
contentResponse.Add(text)
return *contentResponse, nil
})