Skip to content

Commit

Permalink
feat(plugins/plugin-kubectl): improve odo usage experience
Browse files Browse the repository at this point in the history
Fixes #4345
  • Loading branch information
starpit committed Apr 21, 2020
1 parent ebba36e commit 639ca32
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 16 deletions.
2 changes: 2 additions & 0 deletions plugins/plugin-kubectl/i18n/resources_en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@
"currentContext": "This is your current context",
"notCurrentContext": "This is not your current context",
"More Information": "More Information",
"Basic": "Basic",
"Introduction": "Introduction",
"Miscellaneous": "Miscellaneous",
"Options": "Options",
"Commands": "Commands",
"Examples": "Examples"
Expand Down
5 changes: 3 additions & 2 deletions plugins/plugin-kubectl/oc/src/controller/exec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
*/

import { Arguments } from '@kui-shell/core'
import { doExecWithStdout, KubeOptions } from '@kui-shell/plugin-kubectl'
import { doExecWithStdout, KubeOptions, commandPrefix } from '@kui-shell/plugin-kubectl'

export default function doExec<O extends KubeOptions>(args: Arguments<O>) {
return doExecWithStdout(args, undefined, 'oc')
const cmd = args.argv[0] === commandPrefix ? args.argv[1] : args.argv[0]
return doExecWithStdout(args, undefined, cmd)
}
44 changes: 34 additions & 10 deletions plugins/plugin-kubectl/oc/src/controller/kubectl/catchall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,20 @@
* limitations under the License.
*/

import { inBrowser, hasProxy, Arguments, Registrar } from '@kui-shell/core'
import { doExecWithPty, commandPrefix, isUsage, doHelp, KubeOptions } from '@kui-shell/plugin-kubectl'
import { inBrowser, hasProxy, Arguments, Registrar, i18n } from '@kui-shell/core'
import {
doExecWithPty,
doExecWithMarkdown,
commandPrefix,
isUsage,
doHelp,
KubeOptions
} from '@kui-shell/plugin-kubectl'

/** is the given string `str` the `oc` command? */
const isOc = (str: string) => /^oc$/.test(str)
const strings = i18n('plugin-kubectl')

/** is the given string `str` the `oc` or `odo` command? */
const isOc = (str: string) => /^(oc|odo)$/.test(str)

export default (registrar: Registrar) => {
if (inBrowser() && !hasProxy()) {
Expand All @@ -34,12 +43,27 @@ export default (registrar: Registrar) => {
(argv: string[]) => {
return isOc(argv[0]) || (argv[0] === commandPrefix && isOc(argv[1]))
},
(args: Arguments<KubeOptions>) =>
isUsage(args) ||
// (args.argv.length === 1 && args.argv[0] === 'oc') ||
(args.argv.length === 2 && args.argv[1] === 'oc' && args.argv[0] === commandPrefix)
? doHelp('oc', args)
: doExecWithPty(args),
async (args: Arguments<KubeOptions>) => {
const cmd = args.argv[0] === commandPrefix ? args.argv[1] : args.argv[0]

if (args.argv.length === 1 || (args.argv.length === 2 && args.argv[1] === cmd)) {
// `oc` or `odo` on their own
const response = await doExecWithMarkdown(args, cmd)
response.links.push({
label: strings('More Information'),
command: `${cmd} -h`
})
return response
}

return isUsage(args)
? doHelp(cmd, args).catch(err => {
// failsafe: something went wrong with doHelp
console.error(err)
return doExecWithPty(args)
})
: doExecWithPty(args)
},
1 // priority
)
}
1 change: 1 addition & 0 deletions plugins/plugin-kubectl/oc/src/controller/raw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ import { doNativeExec, defaultFlags, commandPrefix } from '@kui-shell/plugin-kub

export default async (registrar: Registrar) => {
registrar.listen(`/${commandPrefix}/_oc`, doNativeExec, Object.assign({}, defaultFlags, { requiresLocal: true }))
registrar.listen(`/${commandPrefix}/_odo`, doNativeExec, Object.assign({}, defaultFlags, { requiresLocal: true }))
}
49 changes: 49 additions & 0 deletions plugins/plugin-kubectl/src/controller/kubectl/exec-to-markdown.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright 2020 IBM Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { Arguments, NavResponse, i18n } from '@kui-shell/core'

import { KubeOptions } from './options'
import { doExecWithStdout } from './exec'
import commandPrefix from '../command-prefix'

const strings = i18n('plugin-kubectl')

export default async function(args: Arguments<KubeOptions>, exec?: string): Promise<NavResponse> {
const cmd = args.argv[0] === commandPrefix ? args.argv[1] : args.argv[0]
const raw = await doExecWithStdout(args, undefined, exec)

const content = raw.replace(/^ (.*)/gm, ' $1') // code blocks: indentation >= 8

return {
apiVersion: 'kui-shell/v1',
kind: 'NavResponse',
breadcrumbs: [{ label: cmd }],
links: [],
menus: [
{
label: strings('Usage'),
items: [
{
mode: strings('Introduction'),
content,
contentType: 'text/markdown'
}
]
}
]
}
}
2 changes: 2 additions & 0 deletions plugins/plugin-kubectl/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ export { default as TrafficLight } from './lib/model/traffic-light'

export { default as apiVersion } from './controller/kubectl/apiVersion'

export { default as doExecWithMarkdown } from './controller/kubectl/exec-to-markdown'

export {
doExecWithStdoutViaPty,
doExecWithPty,
Expand Down
22 changes: 18 additions & 4 deletions plugins/plugin-kubectl/src/lib/util/help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@ const renderHelpUnsafe = (

const processSections = (section: Section) => ({
title: section.title,
nRowsInViewport: section.title.match(/Available Commands/i) ? 8 : undefined,
rows: section.content
.split(/[\n\r]/)
.filter(x => x)
Expand Down Expand Up @@ -279,7 +278,7 @@ ${usageSection[0].content.slice(0, usageSection[0].content.indexOf('\n')).trim()
]

const optionsMenuItems = (): MultiModalMode[] => {
if (verb === '') {
if (verb === '' && command === 'kubectl') {
// kubectl
return [
{
Expand Down Expand Up @@ -316,14 +315,29 @@ ${usageSection[0].content.slice(0, usageSection[0].content.indexOf('\n')).trim()
.filter(section => /command/i.test(section.title))
.map(section => {
return {
mode: section.title.replace(/Command(s)/, '').replace(':', ''),
mode: section.title.replace(/Command(s)/, '').replace(/:$/, '') || strings('Basic'),
content: commandDocTable(section.rows, command, verb, 'COMMAND')
}
})
}
}
}

const miscMenu = (): Menu => {
const randomSections = sections.filter(
section => !(/command/i.test(section.title) || /Flags|Options/i.test(section.title))
)
if (randomSections.length > 0) {
return {
label: strings('Miscellaneous'),
items: randomSections.map(section => ({
mode: section.title.replace(/:$/, ''),
content: commandDocTable(section.rows, command, verb, 'COMMAND')
}))
}
}
}

/** header nav contains sections: Examples */
const exampleMenu = () => {
if (detailedExample && detailedExample.length > 0) {
Expand All @@ -341,7 +355,7 @@ ${usageSection[0].content.slice(0, usageSection[0].content.indexOf('\n')).trim()
}
}

const menus = [headerMenu(strings('Usage')), commandMenu(), exampleMenu()].filter(x => x)
const menus = [headerMenu(strings('Usage')), commandMenu(), miscMenu(), exampleMenu()].filter(x => x)

debug('menus', menus)

Expand Down
16 changes: 16 additions & 0 deletions plugins/plugin-kubectl/src/test/k8s2/usage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,20 @@ describe('kubectl dash h', function(this: Common.ISuite) {
// help on get
it('should refresh', () => Common.refresh(this))
help('kubectl get -h', ['kubectl', 'get'], kubectlGetModes)

// help on oc
it('should refresh', () => Common.refresh(this))
help('oc', ['oc'], commonModes)

// oc -h
it('should refresh', () => Common.refresh(this))
help('oc -h', ['oc'], commonModes.concat(['Basic']))

// help on odo
it('should refresh', () => Common.refresh(this))
help('odo', ['odo'], commonModes)

// odo -h
it('should refresh', () => Common.refresh(this))
help('odo -h', ['odo'], commonModes.concat(['Flags', 'Basic']))
})
5 changes: 5 additions & 0 deletions tools/travis/microk8s.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ pushd /tmp
sudo cp oc /usr/local/bin
sudo chmod +x /usr/local/bin/oc
oc version

echo "Downloading this odo: https://mirror.openshift.com/pub/openshift-v4/clients/odo/latest/odo-${PLATFORM}-amd64"
sudo sh -c "curl -L https://mirror.openshift.com/pub/openshift-v4/clients/odo/latest/odo-${PLATFORM}-amd64 -o /usr/local/bin/odo"
sudo chmod +x /usr/local/bin/odo
odo version
fi

# wait for the kubectl download and socat installation
Expand Down

0 comments on commit 639ca32

Please sign in to comment.