From 3706db2436371cd797501eaf26132003b4902ad0 Mon Sep 17 00:00:00 2001 From: Scott Lowe Date: Wed, 16 Sep 2020 15:23:36 +0200 Subject: [PATCH] Add new command `app rename` Change-type: minor Resolves: #1567 Signed-off-by: Scott Lowe --- lib/actions-oclif/app/rename.ts | 135 ++++++++++++++++++++++++++++++++ lib/preparser.ts | 1 + 2 files changed, 136 insertions(+) create mode 100644 lib/actions-oclif/app/rename.ts diff --git a/lib/actions-oclif/app/rename.ts b/lib/actions-oclif/app/rename.ts new file mode 100644 index 00000000..c13114b7 --- /dev/null +++ b/lib/actions-oclif/app/rename.ts @@ -0,0 +1,135 @@ +/** + * @license + * Copyright 2016-2020 Balena Ltd. + * + * 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 { flags } from '@oclif/command'; +import type { IArg } from '@oclif/parser/lib/args'; +import Command from '../../command'; +import * as cf from '../../utils/common-flags'; +import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy'; +import type { Application, ApplicationType, BalenaSDK } from 'balena-sdk'; + +interface FlagsDef { + help: void; +} + +interface ArgsDef { + name: string; + newName?: string; +} + +export default class AppRenameCmd extends Command { + public static description = stripIndent` + Rename an application. + + Rename an application. + + Note, if the \`newName\` parameter is omitted, it will be + prompted for interactively. + `; + public static examples = [ + '$ balena app rename OldName', + '$ balena app rename OldName NewName', + ]; + + public static args: Array> = [ + { + name: 'name', + description: 'application name or numeric ID', + required: true, + }, + { + name: 'newName', + description: 'the new name for the application', + }, + ]; + + public static usage = 'app rename [newName]'; + + public static flags: flags.Input = { + help: cf.help, + }; + + public static authenticated = true; + + public async run() { + const { args: params } = this.parse(AppRenameCmd); + + const { ExpectedError, instanceOf } = await import('../../errors'); + const balena = getBalenaSdk(); + + // Get app + let app; + try { + app = await balena.models.application.get(params.name, { + $expand: { + application_type: { + $select: ['is_legacy'], + }, + }, + }); + } catch (e) { + const { BalenaApplicationNotFound } = await import('balena-errors'); + if (instanceOf(e, BalenaApplicationNotFound)) { + throw new ExpectedError(`Application ${params.name} not found.`); + } else { + throw e; + } + } + + // Check app supports renaming + const appType = (app.application_type as ApplicationType[])?.[0]; + if (appType.is_legacy) { + throw new ExpectedError( + `Application ${params.name} is of 'legacy' type, and cannot be renamed.`, + ); + } + + const { validateApplicationName } = await import('../../utils/validation'); + const newName = + params.newName || + (await getCliForm().ask({ + message: 'Please enter the new name for this application:', + type: 'input', + validate: validateApplicationName, + })) || + ''; + + try { + await this.renameApplication(balena, app.id, newName); + } catch (e) { + // BalenaRequestError: Request error: Unique key constraint violated + if ((e.message || '').toLowerCase().includes('unique')) { + throw new ExpectedError( + `Error: application ${params.name} already exists.`, + ); + } + throw e; + } + + console.log(`Application ${params.name} renamed to ${newName}`); + } + + async renameApplication(balena: BalenaSDK, id: number, newName: string) { + return balena.pine.patch({ + resource: 'application', + id, + body: { + app_name: newName, + }, + }); + } +} diff --git a/lib/preparser.ts b/lib/preparser.ts index c7abd6bc..a710c4eb 100644 --- a/lib/preparser.ts +++ b/lib/preparser.ts @@ -145,6 +145,7 @@ export const oclifCommandIds = [ 'api-key:generate', 'app', 'app:create', + 'app:rename', 'app:restart', 'app:rm', 'apps',