Advertisement
Guest User

Untitled

a guest
Jul 23rd, 2019
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.07 KB | None | 0 0
  1. /*
  2. Copyright (c) 2019 VMware, Inc. All Rights Reserved.
  3. SPDX-License-Identifier: Apache-2.0
  4. */
  5.  
  6. package main
  7.  
  8. import (
  9. "context"
  10. "fmt"
  11. "log"
  12. "sync"
  13. "time"
  14.  
  15. "github.com/pkg/errors"
  16. "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
  17. "k8s.io/apimachinery/pkg/runtime"
  18. "k8s.io/apimachinery/pkg/runtime/schema"
  19.  
  20. "github.com/vmware/octant/pkg/action"
  21. "github.com/vmware/octant/pkg/plugin"
  22. "github.com/vmware/octant/pkg/plugin/api"
  23. "github.com/vmware/octant/pkg/store"
  24. "github.com/vmware/octant/pkg/view/component"
  25. "github.com/vmware/octant/pkg/view/flexlayout"
  26. )
  27.  
  28. func main() {
  29. podGVK := schema.GroupVersionKind{Version: "v1", Kind: "Pod"}
  30. capabilities := plugin.Capabilities{
  31. SupportsPrinterConfig: []schema.GroupVersionKind{podGVK},
  32. SupportsTab: []schema.GroupVersionKind{podGVK},
  33. }
  34.  
  35. tabHandler := HandlePrintTab(handleTab)
  36. printHandler := HandlePrint(handlePrint)
  37. objectStatusHandler := HandleObjectStatus(handleObjectStatus)
  38.  
  39. p, err := NewPlugin("plugin-name", "a description", capabilities, tabHandler, printHandler, objectStatusHandler)
  40. if err != nil {
  41. log.Fatal(err)
  42. }
  43.  
  44. p.Serve()
  45. }
  46.  
  47. func handleTab(dashboardClient Dashboard, object runtime.Object) (*component.Tab, error) {
  48. if object == nil {
  49. return nil, errors.New("object is nil")
  50. }
  51.  
  52. layout := flexlayout.New()
  53. section := layout.AddSection()
  54. err := section.Add(component.NewText("content from a plugin"), component.WidthHalf)
  55. if err != nil {
  56. return nil, err
  57. }
  58.  
  59. tab := component.Tab{
  60. Name: "PluginStub",
  61. Contents: *layout.ToComponent("Plugin"),
  62. }
  63.  
  64. return &tab, nil
  65. }
  66.  
  67. func handlePrint(dashboardClient Dashboard, object runtime.Object) (plugin.PrintResponse, error) {
  68. if object == nil {
  69. return plugin.PrintResponse{}, errors.Errorf("object is nil")
  70. }
  71.  
  72. ctx := context.Background()
  73. key, err := store.KeyFromObject(object)
  74. if err != nil {
  75. return plugin.PrintResponse{}, err
  76. }
  77. u, err := dashboardClient.Get(ctx, key)
  78. if err != nil {
  79. return plugin.PrintResponse{}, err
  80. }
  81.  
  82. log.Printf("loaded object from objectstore: %v", u)
  83.  
  84. msg := fmt.Sprintf("update from plugin at %s", time.Now().Format(time.RFC3339))
  85.  
  86. return plugin.PrintResponse{
  87. Config: []component.SummarySection{
  88. {Header: "from-plugin", Content: component.NewText(msg)},
  89. },
  90. Status: []component.SummarySection{
  91. {Header: "from-plugin", Content: component.NewText(msg)},
  92. },
  93. Items: []component.FlexLayoutItem{
  94. {
  95. Width: component.WidthHalf,
  96. View: component.NewText("item 1 from plugin"),
  97. },
  98. {
  99. Width: component.WidthFull,
  100. View: component.NewText("item 2 from plugin"),
  101. },
  102. },
  103. }, nil
  104.  
  105. }
  106.  
  107. func handleObjectStatus(dashboardClient Dashboard, object runtime.Object) (plugin.ObjectStatusResponse, error) {
  108. if object == nil {
  109. return plugin.ObjectStatusResponse{}, errors.New("object is nil")
  110. }
  111.  
  112. status := component.PodSummary{
  113. Status: component.NodeStatusError,
  114. Details: []component.Component{component.NewText(fmt.Sprintf("Timestamp: %s", time.Now().Format(time.RFC850)))},
  115. }
  116.  
  117. return plugin.ObjectStatusResponse{
  118. ObjectStatus: status,
  119. }, nil
  120. }
  121.  
  122. type PluginOption func(p *Plugin) error
  123.  
  124. type HandleActionFunc func(dashboardClient Dashboard, payload action.Payload) error
  125.  
  126. func HandleAction(fn HandleActionFunc) PluginOption {
  127. return func(p *Plugin) error {
  128. p.pluginHandler.handleAction = fn
  129. return nil
  130. }
  131. }
  132.  
  133. type HandlePrintFunc func(dashboardClient Dashboard, object runtime.Object) (plugin.PrintResponse, error)
  134.  
  135. func HandlePrint(fn HandlePrintFunc) PluginOption {
  136. return func(p *Plugin) error {
  137. p.pluginHandler.print = fn
  138. return nil
  139. }
  140. }
  141.  
  142. type HandleObjectStatusFunc func(dashboardClient Dashboard, object runtime.Object) (plugin.ObjectStatusResponse, error)
  143.  
  144. func HandleObjectStatus(fn HandleObjectStatusFunc) PluginOption {
  145. return func(p *Plugin) error {
  146. p.pluginHandler.objectStatus = fn
  147. return nil
  148. }
  149. }
  150.  
  151. type HandlePrintTabFunc func(dashboardClient Dashboard, object runtime.Object) (*component.Tab, error)
  152.  
  153. func HandlePrintTab(fn HandlePrintTabFunc) PluginOption {
  154. return func(p *Plugin) error {
  155. p.pluginHandler.printTab = fn
  156. return nil
  157. }
  158. }
  159.  
  160. type Plugin struct {
  161. pluginHandler *pluginHandler
  162. }
  163.  
  164. func NewPlugin(name, description string, capabilities plugin.Capabilities, options ...PluginOption) (*Plugin, error) {
  165. p := &Plugin{
  166. pluginHandler: &pluginHandler{
  167. name: name,
  168. description: description,
  169. capabilities: capabilities,
  170. },
  171. }
  172.  
  173. for _, option := range options {
  174. if err := option(p); err != nil {
  175. return nil, err
  176. }
  177. }
  178.  
  179. if err := p.Validate(); err != nil {
  180. return nil, err
  181. }
  182.  
  183. return p, nil
  184. }
  185.  
  186. func (p *Plugin) Validate() error {
  187. if p.pluginHandler.name == "" {
  188. return errors.New("plugin requires a name")
  189. }
  190. if p.pluginHandler.description == "" {
  191. return errors.New("plugin requires a description")
  192. }
  193. return nil
  194. }
  195.  
  196. func (p *Plugin) Serve() {
  197. ph := &pluginHandler{}
  198. plugin.Serve(ph)
  199. }
  200.  
  201. type pluginHandler struct {
  202. mu sync.Mutex
  203.  
  204. name string
  205. description string
  206. capabilities plugin.Capabilities
  207.  
  208. print func(dashboardClient Dashboard, object runtime.Object) (plugin.PrintResponse, error)
  209. printTab func(dashboardClient Dashboard, object runtime.Object) (*component.Tab, error)
  210. objectStatus func(dashboardClient Dashboard, object runtime.Object) (plugin.ObjectStatusResponse, error)
  211. handleAction func(dashboardClient Dashboard, payload action.Payload) error
  212.  
  213. dashboardClient Dashboard
  214. }
  215.  
  216. func (p *pluginHandler) Register(dashboardAPIAddress string) (plugin.Metadata, error) {
  217. p.mu.Lock()
  218. defer p.mu.Unlock()
  219.  
  220. client, err := NewDashboard(dashboardAPIAddress)
  221. if err != nil {
  222. return plugin.Metadata{}, errors.Wrap(err, "create api client")
  223. }
  224.  
  225. p.dashboardClient = client
  226.  
  227. return plugin.Metadata{
  228. Name: p.name,
  229. Description: p.description,
  230. Capabilities: p.capabilities,
  231. }, nil
  232. }
  233.  
  234. func (p *pluginHandler) Print(object runtime.Object) (plugin.PrintResponse, error) {
  235. if p.print == nil {
  236. return plugin.PrintResponse{}, nil
  237. }
  238.  
  239. return p.print(p.dashboardClient, object)
  240. }
  241.  
  242. func (p *pluginHandler) PrintTab(object runtime.Object) (*component.Tab, error) {
  243. if p.printTab == nil {
  244. return &component.Tab{}, nil
  245. }
  246.  
  247. return p.printTab(p.dashboardClient, object)
  248. }
  249.  
  250. func (p *pluginHandler) ObjectStatus(object runtime.Object) (plugin.ObjectStatusResponse, error) {
  251. if p.objectStatus == nil {
  252. return plugin.ObjectStatusResponse{}, nil
  253. }
  254.  
  255. return p.objectStatus(p.dashboardClient, object)
  256. }
  257.  
  258. func (p *pluginHandler) HandleAction(payload action.Payload) error {
  259. if p.handleAction == nil {
  260. return nil
  261. }
  262.  
  263. return p.handleAction(p.dashboardClient, payload)
  264. }
  265.  
  266. var _ plugin.Service = (*pluginHandler)(nil)
  267.  
  268. type Dashboard interface {
  269. Close() error
  270. List(ctx context.Context, key store.Key) ([]*unstructured.Unstructured, error)
  271. Get(ctx context.Context, key store.Key) (*unstructured.Unstructured, error)
  272. Update(ctx context.Context, object *unstructured.Unstructured) error
  273. PortForward(ctx context.Context, req api.PortForwardRequest) (api.PortForwardResponse, error)
  274. CancelPortForward(ctx context.Context, id string)
  275. ForceFrontendUpdate(ctx context.Context) error
  276. }
  277.  
  278. func NewDashboard(dashboardAPIAddress string) (Dashboard, error) {
  279. return api.NewClient(dashboardAPIAddress)
  280. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement