Skip to content

2d. Decorating Existing TopNavSidecars

Mengting Yan edited this page Apr 20, 2020 · 3 revisions

Kui allows you to divide your code into commands that produce resources versus view-decorating logic. This can lead to better code quality, and also allows the two aspects of logic to be hosted by different plugins. This section covers how to separate the two.

In Kui, a plugin can register a mapping from subsets of resource types to view decorations. This mapping is established as Kui initializes itself (i.e. in the Kui "preloader"). If Kui finds a find preload.js or dist/preload.js, it will invoke the default export of that file, and automatically associate the given view modes with command responses.

Mode Registration

A plugin can register modes. A Mode Registration is a filter when, which identifies the subset of resources that this mode should decorate, and a Mode definition.

Example

We would like to enhance an existing plugin with an additional mode. The kubectl plugin enhances Kui with commands that fetch Kubernetes resources. It also exports a programmatic API that we can leverage.

In this example, we will add a view mode that 1) extracts the last applied configuration, an annotation which is stored as JSON, and 2) presents this information as a YAML-formatted view.

// here we use the core Kui API:
import { Registrar } from '@kui-shell/core'

// and here we use the API exported by the kubeui plugin:
import { KubeResource, isKubeResource } from '@kui-shell/plugin-kubectl'

/** the last applied annotation key */
const key = 'kubectl.kubernetes.io/last-applied-configuration'

/** the when filter definition */
function hasLastApplied(r: KubeResource) {
  return isKubeResource(r) && r.metadata.annotations[key] !== undefined
}

/** the mode definition */
const lastApplied = {
  mode: 'last applied',
  content: async (_, { metadata }: KubeResource) => {
    // the annotation is stored as a JSON string
    // but let's present the JSON as yaml
    const { safeDump } = await import('js-yaml')
    return {
      content: safeDump(JSON.parse(metadata.annotations[key]))
      contentType: 'yaml'
    }
  }
}

/** the default export that registers our mode */
export default (registrar: Registrar) => {
  registrar.registerMode({
    when: hasLastApplied, // <-- the filter part
    mode: lastApplied     // <-- the view part
  })
}

Next Steps