Skip to content

Commit

Permalink
feat: up command
Browse files Browse the repository at this point in the history
part of #7669
  • Loading branch information
starpit committed Jun 20, 2021
1 parent 8193d21 commit 5bac994
Show file tree
Hide file tree
Showing 22 changed files with 887 additions and 1 deletion.
2 changes: 1 addition & 1 deletion plugins/plugin-core-support/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@
"@kui-shell/plugin-core-support/*": ["src/*"]
}
},
"references": [{ "path": "./about" }]
"references": [{ "path": "./about" }, { "path": "./up" }]
}
32 changes: 32 additions & 0 deletions plugins/plugin-core-support/up/src/Checker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright 2021 The Kubernetes Authors
*
* 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 } from '@kui-shell/core'

export type CheckerArgs = Pick<Arguments, 'REPL'>

export type CheckResultSuccess = true | string
export type CheckResult = CheckResultSuccess | false

type Checker<T extends CheckResult = CheckResult> = {
check: (args: CheckerArgs) => T | Promise<T>
label: string | ((checkResult: T) => string)
fix?: string | ((args: Arguments) => T | Promise<T>)
needsCloudLogin?: boolean
optional?: boolean
}

export default Checker
19 changes: 19 additions & 0 deletions plugins/plugin-core-support/up/src/aws/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright 2021 The Kubernetes Authors
*
* 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 S3Creds from './s3'

export default [S3Creds]
32 changes: 32 additions & 0 deletions plugins/plugin-core-support/up/src/aws/s3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright 2021 The Kubernetes Authors
*
* 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 } from '@kui-shell/core'

async function check({ REPL }: Pick<Arguments, 'REPL'>) {
try {
await REPL.qexec('vfs fstat /s3/aws')
return true
} catch (err) {
return false
}
}

export default {
label: 'S3: mounted AWS',
check,
optional: true
}
52 changes: 52 additions & 0 deletions plugins/plugin-core-support/up/src/ibm/base/login.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2021 The Kubernetes Authors
*
* 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, encodeComponent } from '@kui-shell/core'
import { doExecWithStdoutViaPty } from '@kui-shell/plugin-bash-like'

import Options from '../../options'

async function check(args: Arguments) {
try {
await doExecWithStdoutViaPty(Object.assign({}, args, { command: 'ibmcloud account show' }))
return true
} catch (err) {
return false
}
}

export default {
label: 'CLI: ibmcloud login',
needsCloudLogin: true,
onFail: 'ibmcloud login',
fix: async ({ REPL, parsedOptions }: Arguments<Options>) => {
const sso = parsedOptions.sso ? `--sso` : ''
const apikey = parsedOptions.apikey ? `--apikey=${parsedOptions.apikey}` : ''

if (process.env.TRAVIS_JOB_ID || !process.stdout.isTTY) {
// when testing on traivs, force login without prompting for a region since we will test region targeting in target --fix
await REPL.qexec(`ibmcloud login ${sso || apikey} --no-region`)
} else {
await REPL.qexec(
`ibmcloud login ${sso || apikey}` +
(parsedOptions.region ? ` -r ${encodeComponent(parsedOptions.region)}` : '') +
(parsedOptions['resource-group'] ? ` -g ${encodeComponent(parsedOptions['resource-group'])}` : '')
)
}
return true
},
check
}
61 changes: 61 additions & 0 deletions plugins/plugin-core-support/up/src/ibm/base/target.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright 2021 The Kubernetes Authors
*
* 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.
*/

/* eslint-disable @typescript-eslint/camelcase */

import colors from 'colors/safe'
import { Arguments, encodeComponent } from '@kui-shell/core'
import { doExecWithStdoutViaPty } from '@kui-shell/plugin-bash-like'

import Options from '../../options'

async function check(args: Arguments) {
try {
const res = await doExecWithStdoutViaPty(Object.assign({}, args, { command: 'ibmcloud target --output=json' }))
if (res.includes('No resource group targeted')) {
return false
} else {
const { resource_group, region } = JSON.parse(res)
if (!resource_group) {
return false
} else {
const resourceGroupMsg = resource_group
? `${colors.gray('resource-group=')}${colors.yellow(resource_group.name)}`
: ''
const regionMsg = region ? `${colors.gray('region=')}${colors.yellow(region.name)}` : ''
return `${resourceGroupMsg} ${regionMsg}`
}
}
} catch (err) {
return false
}
}

export default {
label: (checkResult: false | string) =>
'Cloud: ibmcloud target ' + (!checkResult ? colors.red('not selected') : checkResult),
needsCloudLogin: true,
onFail: 'ibmcloud target -r <region=us-south,eu-de>',
fix: async ({ REPL, parsedOptions }: Arguments<Options>) => {
await REPL.qexec(
'ibmcloud target --fix' +
(parsedOptions.region ? ` --region ${encodeComponent(parsedOptions.region)}` : '') +
(parsedOptions['resource-group'] ? ` --resource-group ${encodeComponent(parsedOptions['resource-group'])}` : '')
)
return true
},
check
}
116 changes: 116 additions & 0 deletions plugins/plugin-core-support/up/src/ibm/ce/project.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* Copyright 2021 The Kubernetes Authors
*
* 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 colors from 'colors/safe'
import { Arguments } from '@kui-shell/core'
import { doExecWithStdoutViaPty } from '@kui-shell/plugin-bash-like'

import Options from '../../options'

async function check(args: Arguments): Promise<string | boolean> {
try {
return await args.REPL.qexec<string>('ibmcloud ce project current-name')
} catch (err) {
return false
}
}

async function fix(args: Arguments<Options>) {
let passThroughErrorToUser = false
const useThisProject = process.env['CE_PROJECT'] || args.parsedOptions['code-engine-project']
const createProject = async () =>
await args.REPL.qexec(`ibmcloud ce project create -n ${useThisProject || 'superproject'}`)

try {
const projects = JSON.parse(
await doExecWithStdoutViaPty(Object.assign({}, args, { command: 'ibmcloud ce project list -o json' }))
)

if (Array.isArray(projects) && projects.length !== 0) {
// then the user has at least one project
if (useThisProject) {
// then the user asked us to use a specific project; let us
// see if it exists:
const foundProject = projects.find(_ => _.name === useThisProject)

if (foundProject && foundProject.state === 'active' && foundProject.selected) {
// found it! and it is active and selected! nothing to do
// await args.REPL.qexec(`ibmcloud ce project select -n ${useThisProject}`)
console.log('Desired IBM CodeEngine project already selected ' + useThisProject)
} else if (foundProject && foundProject.state === 'active') {
// found it and it is active, but not selected
console.log('Switching to IBM CodeEngine project ' + foundProject.name)
await args.REPL.qexec(`ibmcloud ce project select -n ${foundProject.name}`)
} else if (!process.env.CE_PROJECT_CREATE_IF_NEEDED || process.env.CE_PROJECT_CREATE_IF_NEEDED === 'false') {
// did not find the user-specified project, do not create one
passThroughErrorToUser = true
throw new Error('Desired IBM Cloud CodeEngine project not found: ' + useThisProject)
} else {
// did not find the user-specified project, create one!
console.log('Creating specified IBM CodeEngine project: ' + useThisProject)
await createProject()
}
} else {
// if we get here, then the user has existing projects, but
// has not specified that we should use any particular one;
// favor "superproject" if active, otherwise the first active one
const firstActiveProject =
projects.find(_ => _.state === 'active' && _.name === 'superproject') ||
projects.find(_ => _.state === 'active')

if (firstActiveProject && firstActiveProject.name) {
// if we get here, then the user has an active project that we can use
if (firstActiveProject.active) {
console.log('Using IBM CodeEngine project ' + useThisProject)
} else {
console.log('Switching to IBM CodeEngine project ' + firstActiveProject.name)
await args.REPL.qexec(`ibmcloud ce project select -n ${firstActiveProject.name}`)
}
} else {
// if we get here, then the *user has no active projects*, so create one
console.error('No active IBM CodeEngine projects, creating one')
await createProject()
}
}
} else {
// if we get here, then the *user has no projects at all*, so create one
console.log('No IBM CodeEngine projects, creating one')
await createProject()
}
} catch (err) {
if (!passThroughErrorToUser) {
// conservatively create a new project
await createProject()
} else {
// then we threw an error somewhere above; rethrow it here for
// the user to see
throw err
}
}

return check(args)
}

export default {
label: (checkResult: false | string) =>
'Cloud: CodeEngine ' +
colors.gray('project=') +
(!checkResult ? colors.red('not selected') : colors.yellow(checkResult)),
needsCloudLogin: true,
onFail: 'ibmcloud ce project create --name <projectname=superproject>',
fix,
check
}
36 changes: 36 additions & 0 deletions plugins/plugin-core-support/up/src/ibm/cli/ce.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2021 The Kubernetes Authors
*
* 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 } from '@kui-shell/core'
import { doExecWithStdoutViaPty } from '@kui-shell/plugin-bash-like'

async function check(args: Arguments) {
try {
await doExecWithStdoutViaPty(Object.assign({}, args, { command: 'ibmcloud ce version' }))
return true
} catch (err) {
return false
}
}

const install = 'ibmcloud plugin install code-engine'

export default {
label: 'CLI plugin: ibmcloud code-engine',
fix: install,
onFail: install,
check
}
36 changes: 36 additions & 0 deletions plugins/plugin-core-support/up/src/ibm/cli/cos.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2021 The Kubernetes Authors
*
* 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 } from '@kui-shell/core'
import { doExecWithStdoutViaPty } from '@kui-shell/plugin-bash-like'

async function check(args: Arguments) {
try {
await doExecWithStdoutViaPty(Object.assign({}, args, { command: 'ibmcloud cos help' }))
return true
} catch (err) {
return false
}
}

const install = 'ibmcloud plugin install cloud-object-storage'

export default {
label: 'CLI plugin: ibmcloud cloud-object-storage',
fix: install,
onFail: install,
check
}

0 comments on commit 5bac994

Please sign in to comment.