@agilecustoms/envctl 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/client/ProcessRunner.js +7 -1
- package/dist/client/TerraformAdapter.js +11 -3
- package/dist/commands/configure.js +23 -0
- package/dist/commands/delete.js +13 -2
- package/dist/commands/deploy.js +37 -6
- package/dist/commands/index.js +2 -0
- package/dist/commands/plan.js +22 -0
- package/dist/commands/utils.js +21 -11
- package/dist/container.js +3 -2
- package/dist/index.js +3 -1
- package/dist/model/EnvSize.js +11 -0
- package/dist/model/EnvStatus.js +7 -0
- package/dist/model/EnvType.js +5 -0
- package/dist/model/index.js +4 -1
- package/dist/service/ConfigService.js +28 -0
- package/dist/service/EnvCtl.js +33 -23
- package/dist/service/index.js +1 -0
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ npm view @agilecustoms/envctl version # show latest version available (without i
|
|
|
33
33
|
`env-api` is a microservice hosted in 'maintenance' account and working as garbage collector: every environment first
|
|
34
34
|
created in `env-api` and then 'managed' by `env-api`: it deletes env when it is not in use anymore OR can extend lifetime.
|
|
35
35
|
Creation API yields unique ID, so you can safely manage env (delete, extend lifetime) via this ID. But creation API
|
|
36
|
-
|
|
36
|
+
needs to be secured. There are two main use cases:
|
|
37
37
|
1. create environment from CI (mainly ephemeral envs)
|
|
38
38
|
2. create env from dev machine
|
|
39
39
|
|
|
@@ -9,7 +9,9 @@ export class ProcessRunner {
|
|
|
9
9
|
return this.run(scriptPath, args, cwd, scanner);
|
|
10
10
|
}
|
|
11
11
|
async run(command, args, cwd, scanner) {
|
|
12
|
-
const spawnOptions = {
|
|
12
|
+
const spawnOptions = {
|
|
13
|
+
stdio: ['inherit', 'pipe', 'pipe'],
|
|
14
|
+
};
|
|
13
15
|
if (cwd) {
|
|
14
16
|
spawnOptions.cwd = cwd;
|
|
15
17
|
}
|
|
@@ -26,6 +28,10 @@ export class ProcessRunner {
|
|
|
26
28
|
scanner(line);
|
|
27
29
|
console.log(`> ${line}`);
|
|
28
30
|
}
|
|
31
|
+
if (buffer.includes('Enter a value:')) {
|
|
32
|
+
console.log(buffer);
|
|
33
|
+
buffer = '';
|
|
34
|
+
}
|
|
29
35
|
});
|
|
30
36
|
let errorBuffer = '';
|
|
31
37
|
child.stderr.on('data', (data) => {
|
|
@@ -40,15 +40,23 @@ export class TerraformAdapter {
|
|
|
40
40
|
throw new KnownException('Can not find terraform files. Command needs to be run in a directory with terraform files');
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
tfArgs(envAttrs, tfArgs) {
|
|
44
|
+
return [
|
|
45
45
|
`-var=env=${envAttrs.env}`,
|
|
46
46
|
`-var=owner=${envAttrs.owner}`,
|
|
47
47
|
`-var=env_size=${envAttrs.size}`,
|
|
48
48
|
`-var=env_type=${envAttrs.type}`,
|
|
49
49
|
...tfArgs
|
|
50
50
|
];
|
|
51
|
-
|
|
51
|
+
}
|
|
52
|
+
async plan(envAttrs, tfArgs, cwd) {
|
|
53
|
+
const args = this.tfArgs(envAttrs, tfArgs);
|
|
54
|
+
console.log('Running: terraform plan -auto-approve', ...args);
|
|
55
|
+
await this.processRunner.run('terraform', ['plan', ...args], cwd);
|
|
56
|
+
}
|
|
57
|
+
async deploy(envAttrs, tfArgs, cwd, attemptNo = 1) {
|
|
58
|
+
const args = this.tfArgs(envAttrs, tfArgs);
|
|
59
|
+
console.log('Running: terraform apply -auto-approve', ...args);
|
|
52
60
|
this.printTime();
|
|
53
61
|
try {
|
|
54
62
|
await this.processRunner.run('terraform', ['apply', '-auto-approve', ...args], cwd);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { configService } from '../container.js';
|
|
4
|
+
import { wrap } from './utils.js';
|
|
5
|
+
export function configure(program) {
|
|
6
|
+
program
|
|
7
|
+
.command('configure')
|
|
8
|
+
.description('Configure user settings on your local machine')
|
|
9
|
+
.action(wrap(handler));
|
|
10
|
+
}
|
|
11
|
+
async function handler() {
|
|
12
|
+
const answers = await inquirer.prompt([
|
|
13
|
+
{
|
|
14
|
+
type: 'input',
|
|
15
|
+
name: 'owner',
|
|
16
|
+
message: 'owner is required to deploy any env\n'
|
|
17
|
+
+ 'this value will be used as default - if not provided via --owner key in "deploy" command\n'
|
|
18
|
+
+ '(prefer GitHub username)\n'
|
|
19
|
+
+ 'owner:',
|
|
20
|
+
},
|
|
21
|
+
]);
|
|
22
|
+
configService.saveConfig({ owner: answers.owner });
|
|
23
|
+
}
|
package/dist/commands/delete.js
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
-
import { envCtl } from '../container.js';
|
|
2
|
+
import { configService, envCtl } from '../container.js';
|
|
3
|
+
import { KnownException } from '../exceptions.js';
|
|
3
4
|
import { wrap } from './utils.js';
|
|
4
5
|
export function deleteIt(program) {
|
|
5
6
|
program
|
|
6
7
|
.command('delete')
|
|
7
8
|
.description('Delete a development environment')
|
|
8
|
-
.
|
|
9
|
+
.option('--env <env>', 'Environment name (can be git hash). {project}-{env} give env key used to store env state (s3 key in case of AWS)')
|
|
9
10
|
.option('--project <project>', 'Project code (like tt). Used when multiple projects deployed in same AWS account')
|
|
10
11
|
.action(wrap(handler));
|
|
11
12
|
}
|
|
12
13
|
async function handler(options) {
|
|
13
14
|
let { env, project } = options;
|
|
15
|
+
if (!env) {
|
|
16
|
+
const owner = configService.getOwner();
|
|
17
|
+
if (!owner) {
|
|
18
|
+
throw new KnownException('--env argument is not provided\n'
|
|
19
|
+
+ 'default to owner from local configuration, but it is not configured\n'
|
|
20
|
+
+ 'please call with --env argument or run \'envctl configure\' to configure owner');
|
|
21
|
+
}
|
|
22
|
+
console.log(`Env name not provided, default to owner name ${owner}`);
|
|
23
|
+
env = owner;
|
|
24
|
+
}
|
|
14
25
|
await envCtl.delete(env, project);
|
|
15
26
|
}
|
package/dist/commands/deploy.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { configService, envCtl } from '../container.js';
|
|
4
|
+
import { KnownException } from '../exceptions.js';
|
|
5
|
+
import { EnvType } from '../model/index.js';
|
|
6
|
+
import { EnvSize } from '../model/index.js';
|
|
7
|
+
import { ensureEnumValue, ensureKind, wrap } from './utils.js';
|
|
4
8
|
export function deploy(program) {
|
|
5
9
|
program
|
|
6
10
|
.command('deploy')
|
|
7
11
|
.description('Create new or update existing dev environment')
|
|
8
12
|
.option('--project <project>', 'Project code (like tt). Used when multiple projects deployed in same AWS account')
|
|
9
13
|
.option('--env <env>', 'Environment name (can be git hash). {project}-{env} give env key used to store env state (s3 key in case of AWS)')
|
|
10
|
-
.
|
|
11
|
-
.
|
|
14
|
+
.option('--owner <owner>', 'Environment owner (GH username)')
|
|
15
|
+
.option('--size <size>', 'Environment size: min, small, full')
|
|
12
16
|
.option('--type <type>', 'Environment type: dev, prod', 'dev')
|
|
13
17
|
.option('--kind <kind>', 'Environment kind: complete project (default) or some slice such as tt-core + tt-web')
|
|
14
18
|
.option('--cwd <cwd>', 'Working directory (default: current directory)')
|
|
@@ -17,12 +21,39 @@ export function deploy(program) {
|
|
|
17
21
|
.action(wrap(handler));
|
|
18
22
|
}
|
|
19
23
|
async function handler(tfArgs, options) {
|
|
24
|
+
const envDto = await parseEnvDto(options);
|
|
25
|
+
await envCtl.deploy(envDto, tfArgs, options.cwd);
|
|
26
|
+
}
|
|
27
|
+
export async function parseEnvDto(options) {
|
|
20
28
|
let { project, env, owner, size, type, kind, cwd } = options;
|
|
29
|
+
if (!owner) {
|
|
30
|
+
owner = configService.getOwner();
|
|
31
|
+
if (!owner) {
|
|
32
|
+
throw new KnownException('when called without --owner option, first call \'envctl configure\'');
|
|
33
|
+
}
|
|
34
|
+
console.log(`Owner not provided, default to configured owner ${owner}`);
|
|
35
|
+
}
|
|
21
36
|
if (!env) {
|
|
22
37
|
console.log(`Env name not provided, default to owner name ${owner}`);
|
|
23
38
|
env = owner;
|
|
24
39
|
}
|
|
25
40
|
kind = ensureKind(kind, cwd);
|
|
26
|
-
|
|
27
|
-
|
|
41
|
+
let envSize;
|
|
42
|
+
if (size) {
|
|
43
|
+
envSize = ensureEnumValue(EnvSize, size, 'size');
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
const answer = await inquirer.prompt([
|
|
47
|
+
{
|
|
48
|
+
type: 'list',
|
|
49
|
+
name: 'size',
|
|
50
|
+
message: 'Environment size:',
|
|
51
|
+
choices: Object.values(EnvSize),
|
|
52
|
+
default: EnvSize.Small,
|
|
53
|
+
}
|
|
54
|
+
]);
|
|
55
|
+
envSize = answer.size;
|
|
56
|
+
}
|
|
57
|
+
const envType = ensureEnumValue(EnvType, type, 'type');
|
|
58
|
+
return { project, env, owner, size: envSize, type: envType, kind };
|
|
28
59
|
}
|
package/dist/commands/index.js
CHANGED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { envCtl } from '../container.js';
|
|
3
|
+
import { parseEnvDto } from './deploy.js';
|
|
4
|
+
import { wrap } from './utils.js';
|
|
5
|
+
export function plan(program) {
|
|
6
|
+
program
|
|
7
|
+
.command('plan')
|
|
8
|
+
.description('High level wrapper for terraform plan. Compliments deploy command: if you plan to deploy env with envctl deploy,'
|
|
9
|
+
+ ' then it is recommended to do plan with envctl plan to guarantee consistent behavior')
|
|
10
|
+
.option('--env <env>', 'Environment name (can be git hash). {project}-{env} give env key used to store env state (s3 key in case of AWS)')
|
|
11
|
+
.option('--owner <owner>', 'Environment owner (GH username)')
|
|
12
|
+
.option('--size <size>', 'Environment size: min, small, full')
|
|
13
|
+
.option('--type <type>', 'Environment type: dev, prod', 'dev')
|
|
14
|
+
.option('--cwd <cwd>', 'Working directory (default: current directory)')
|
|
15
|
+
.allowUnknownOption(true)
|
|
16
|
+
.argument('[args...]')
|
|
17
|
+
.action(wrap(handler));
|
|
18
|
+
}
|
|
19
|
+
async function handler(tfArgs, options) {
|
|
20
|
+
const envDto = await parseEnvDto(options);
|
|
21
|
+
await envCtl.plan(envDto, tfArgs, options.cwd);
|
|
22
|
+
}
|
package/dist/commands/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
2
|
+
import { ExitPromptError } from '@inquirer/core';
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
4
|
import { BusinessException, ExitException, KnownException } from '../exceptions.js';
|
|
5
5
|
export function wrap(callable) {
|
|
6
6
|
return async (...args) => {
|
|
@@ -12,7 +12,9 @@ export function wrap(callable) {
|
|
|
12
12
|
if (error instanceof KnownException || error instanceof BusinessException) {
|
|
13
13
|
console.error(error.message);
|
|
14
14
|
}
|
|
15
|
-
else if (
|
|
15
|
+
else if (error instanceof ExitException || error instanceof ExitPromptError) {
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
16
18
|
console.error('Unknown error:', error);
|
|
17
19
|
}
|
|
18
20
|
process.exit(1);
|
|
@@ -22,16 +24,17 @@ export function wrap(callable) {
|
|
|
22
24
|
}
|
|
23
25
|
};
|
|
24
26
|
}
|
|
25
|
-
export async function
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
export async function promptYesNo(message, defaultValue = false) {
|
|
28
|
+
const { answer } = await inquirer.prompt([
|
|
29
|
+
{
|
|
30
|
+
type: 'confirm',
|
|
31
|
+
name: 'answer',
|
|
32
|
+
message,
|
|
33
|
+
default: defaultValue,
|
|
34
|
+
},
|
|
35
|
+
]);
|
|
29
36
|
return answer;
|
|
30
37
|
}
|
|
31
|
-
export async function promptYesNo(question) {
|
|
32
|
-
const answer = await prompt(question);
|
|
33
|
-
return answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes';
|
|
34
|
-
}
|
|
35
38
|
export function ensureKind(kind, cwd) {
|
|
36
39
|
if (kind) {
|
|
37
40
|
return kind;
|
|
@@ -53,3 +56,10 @@ function resolveCwd(cwd) {
|
|
|
53
56
|
}
|
|
54
57
|
return path.resolve(process.cwd(), cwd);
|
|
55
58
|
}
|
|
59
|
+
export function ensureEnumValue(enumObj, value, name) {
|
|
60
|
+
const values = Object.values(enumObj);
|
|
61
|
+
if (!values.includes(value)) {
|
|
62
|
+
throw new KnownException(`Invalid ${name}: "${value}". Must be one of: ${values.join(', ')}`);
|
|
63
|
+
}
|
|
64
|
+
return value;
|
|
65
|
+
}
|
package/dist/container.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { EnvApiClient, HttpClient, TerraformAdapter } from './client/index.js';
|
|
2
2
|
import { ProcessRunner } from './client/ProcessRunner.js';
|
|
3
|
-
import { EnvCtl } from './service/index.js';
|
|
3
|
+
import { ConfigService, EnvCtl } from './service/index.js';
|
|
4
|
+
const configService = new ConfigService();
|
|
4
5
|
const httpClient = new HttpClient();
|
|
5
6
|
const envApiClient = new EnvApiClient(httpClient);
|
|
6
7
|
const processRunner = new ProcessRunner();
|
|
7
8
|
const terraformAdapter = new TerraformAdapter(processRunner);
|
|
8
9
|
const envCtl = new EnvCtl(envApiClient, terraformAdapter);
|
|
9
|
-
export { envCtl };
|
|
10
|
+
export { configService, envCtl };
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { createRequire } from 'module';
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import updateNotifier from 'update-notifier';
|
|
5
|
-
import { deleteIt, deploy } from './commands/index.js';
|
|
5
|
+
import { configure, deleteIt, deploy, plan } from './commands/index.js';
|
|
6
6
|
const require = createRequire(import.meta.url);
|
|
7
7
|
const pkg = require('../package.json');
|
|
8
8
|
updateNotifier({ pkg, updateCheckInterval: 0 }).notify();
|
|
@@ -11,6 +11,8 @@ program
|
|
|
11
11
|
.name('envctl')
|
|
12
12
|
.description('CLI to manage environments')
|
|
13
13
|
.version(pkg.version);
|
|
14
|
+
configure(program);
|
|
14
15
|
deploy(program);
|
|
15
16
|
deleteIt(program);
|
|
17
|
+
plan(program);
|
|
16
18
|
program.parse(process.argv);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export var EnvSize;
|
|
2
|
+
(function (EnvSize) {
|
|
3
|
+
EnvSize["Min"] = "min";
|
|
4
|
+
EnvSize["Small"] = "small";
|
|
5
|
+
EnvSize["Full"] = "full";
|
|
6
|
+
})(EnvSize || (EnvSize = {}));
|
|
7
|
+
export const EnvSizeAvgTime = {
|
|
8
|
+
[EnvSize.Min]: 2,
|
|
9
|
+
[EnvSize.Small]: 5,
|
|
10
|
+
[EnvSize.Full]: 10,
|
|
11
|
+
};
|
package/dist/model/index.js
CHANGED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as os from 'node:os';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
const CONFIG_PATH = path.join(os.homedir(), '.envctl', 'config.json');
|
|
5
|
+
export class ConfigService {
|
|
6
|
+
config;
|
|
7
|
+
constructor() {
|
|
8
|
+
}
|
|
9
|
+
saveConfig(config) {
|
|
10
|
+
const mergedConfig = { ...this.loadConfig(), ...config };
|
|
11
|
+
const data = JSON.stringify(mergedConfig, null, 2);
|
|
12
|
+
fs.mkdirSync(path.dirname(CONFIG_PATH), { recursive: true });
|
|
13
|
+
fs.writeFileSync(CONFIG_PATH, data);
|
|
14
|
+
}
|
|
15
|
+
loadConfig() {
|
|
16
|
+
if (this.config)
|
|
17
|
+
return this.config;
|
|
18
|
+
this.config = {};
|
|
19
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
20
|
+
const data = fs.readFileSync(CONFIG_PATH, 'utf-8');
|
|
21
|
+
this.config = JSON.parse(data);
|
|
22
|
+
}
|
|
23
|
+
return this.config;
|
|
24
|
+
}
|
|
25
|
+
getOwner() {
|
|
26
|
+
return this.loadConfig()?.owner;
|
|
27
|
+
}
|
|
28
|
+
}
|
package/dist/service/EnvCtl.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { promptYesNo } from '../commands/utils.js';
|
|
2
2
|
import { KnownException } from '../exceptions.js';
|
|
3
|
+
import { EnvSizeAvgTime, EnvStatus } from '../model/index.js';
|
|
3
4
|
export class EnvCtl {
|
|
4
5
|
envApi;
|
|
5
6
|
terraformAdapter;
|
|
@@ -7,8 +8,15 @@ export class EnvCtl {
|
|
|
7
8
|
this.envApi = envApi;
|
|
8
9
|
this.terraformAdapter = terraformAdapter;
|
|
9
10
|
}
|
|
11
|
+
key(project, env) {
|
|
12
|
+
return project ? `${project}-${env}` : env;
|
|
13
|
+
}
|
|
14
|
+
async plan(envDto, tfArgs, cwd) {
|
|
15
|
+
console.log('Deploying resources');
|
|
16
|
+
await this.terraformAdapter.plan(envDto, tfArgs, cwd);
|
|
17
|
+
}
|
|
10
18
|
async deploy(envDto, tfArgs, cwd) {
|
|
11
|
-
const key =
|
|
19
|
+
const key = this.key(envDto.project, envDto.env);
|
|
12
20
|
console.log(`Check if env ${key} already exists`);
|
|
13
21
|
const env = await this.envApi.get(key);
|
|
14
22
|
if (env === null) {
|
|
@@ -36,31 +44,33 @@ export class EnvCtl {
|
|
|
36
44
|
if (env.kind !== envDto.kind) {
|
|
37
45
|
throw new KnownException(`Can not change env kind ${env.kind} -> ${envDto.kind}`);
|
|
38
46
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
await
|
|
47
|
+
switch (env.status) {
|
|
48
|
+
case EnvStatus.Creating:
|
|
49
|
+
case EnvStatus.Updating: {
|
|
50
|
+
const answerYes = await promptYesNo(`Env status is ${env.status}, likely to be an error from a previous run\n`
|
|
51
|
+
+ 'Do you want to proceed with deployment?');
|
|
52
|
+
if (answerYes) {
|
|
53
|
+
await this.runDeploy(key, envDto, tfArgs, cwd);
|
|
54
|
+
}
|
|
55
|
+
break;
|
|
43
56
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (answerYes) {
|
|
57
|
+
case EnvStatus.Active: {
|
|
58
|
+
console.log('Env status is ACTIVE\nWill lock for update and run terraform apply (to update resources)');
|
|
59
|
+
await this.envApi.lockForUpdate(key);
|
|
48
60
|
await this.runDeploy(key, envDto, tfArgs, cwd);
|
|
61
|
+
break;
|
|
49
62
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
else if (env.status === 'DELETING') {
|
|
57
|
-
const time = env.size === 'min' ? 2 : 5;
|
|
58
|
-
throw new KnownException(`Env status is DELETING, please wait (~${time} min)`);
|
|
63
|
+
case EnvStatus.Deleting: {
|
|
64
|
+
const time = EnvSizeAvgTime[env.size];
|
|
65
|
+
throw new KnownException(`Env status is DELETING, please wait (~${time} min)`);
|
|
66
|
+
}
|
|
67
|
+
default:
|
|
68
|
+
throw new KnownException(`Unsupported environment status: ${env.status}`);
|
|
59
69
|
}
|
|
60
70
|
}
|
|
61
|
-
async runDeploy(key,
|
|
71
|
+
async runDeploy(key, envDto, tfArgs, cwd) {
|
|
62
72
|
console.log('Deploying resources');
|
|
63
|
-
await this.terraformAdapter.deploy(
|
|
73
|
+
await this.terraformAdapter.deploy(envDto, tfArgs, cwd);
|
|
64
74
|
console.log('Activating env (to finish creation)');
|
|
65
75
|
await this.envApi.activate(key);
|
|
66
76
|
console.log('Lock env to run db evolution');
|
|
@@ -69,14 +79,14 @@ export class EnvCtl {
|
|
|
69
79
|
await this.envApi.activate(key);
|
|
70
80
|
}
|
|
71
81
|
async delete(envName, project) {
|
|
72
|
-
const key = project
|
|
82
|
+
const key = this.key(project, envName);
|
|
73
83
|
console.log(`Retrieve env`);
|
|
74
84
|
const env = await this.envApi.get(key);
|
|
75
85
|
if (env === null) {
|
|
76
86
|
throw new KnownException(`Environment ${key} does not exist`);
|
|
77
87
|
}
|
|
78
|
-
if (env.status ===
|
|
79
|
-
const answerYes = await promptYesNo('Environment is still being created.\nDo you want to delete it?
|
|
88
|
+
if (env.status === EnvStatus.Creating) {
|
|
89
|
+
const answerYes = await promptYesNo('Environment is still being created.\nDo you want to delete it?');
|
|
80
90
|
if (!answerYes) {
|
|
81
91
|
throw new KnownException('Aborting env deletion');
|
|
82
92
|
}
|
package/dist/service/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agilecustoms/envctl",
|
|
3
3
|
"description": "node.js CLI client for manage environments",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.11.0",
|
|
5
5
|
"author": "Alex Chekulaev",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -26,14 +26,17 @@
|
|
|
26
26
|
"build": "tsc",
|
|
27
27
|
"run": "node dist/index.js",
|
|
28
28
|
"run-version": "tsc --sourceMap true && npm run run -- --version",
|
|
29
|
-
"run-
|
|
30
|
-
"run-
|
|
29
|
+
"run-configure": "tsc --sourceMap true && npm run run -- configure",
|
|
30
|
+
"run-plan": "tsc --sourceMap true && npm run run -- plan --size min --cwd ../tt-core",
|
|
31
|
+
"run-deploy": "tsc --sourceMap true && npm run run -- deploy --size min --cwd ../tt-core",
|
|
32
|
+
"run-delete": "tsc --sourceMap true && npm run run -- delete"
|
|
31
33
|
},
|
|
32
34
|
"dependencies": {
|
|
33
35
|
"@aws-sdk/client-sts": "^3.716.0",
|
|
34
36
|
"@aws-sdk/credential-providers": "^3.716.0",
|
|
35
37
|
"aws4": "^1.13.2",
|
|
36
38
|
"commander": "^13.0.0",
|
|
39
|
+
"inquirer": "^12.6.0",
|
|
37
40
|
"update-notifier": "^7.3.1"
|
|
38
41
|
},
|
|
39
42
|
"devDependencies": {
|