@agilecustoms/envctl 0.18.2 → 0.19.1
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.
|
@@ -18,16 +18,17 @@ export class ProcessRunner {
|
|
|
18
18
|
const child = spawn(command, args, spawnOptions);
|
|
19
19
|
child.stdout.setEncoding('utf8');
|
|
20
20
|
child.stderr.setEncoding('utf8');
|
|
21
|
+
function processLine(line) {
|
|
22
|
+
if (scanner)
|
|
23
|
+
scanner(line);
|
|
24
|
+
console.log(line);
|
|
25
|
+
}
|
|
21
26
|
let buffer = '';
|
|
22
27
|
child.stdout.on('data', (data) => {
|
|
23
28
|
buffer += data;
|
|
24
29
|
const lines = buffer.split('\n');
|
|
25
30
|
buffer = lines.pop() || '';
|
|
26
|
-
|
|
27
|
-
if (scanner)
|
|
28
|
-
scanner(line);
|
|
29
|
-
console.log(line);
|
|
30
|
-
}
|
|
31
|
+
lines.forEach(processLine);
|
|
31
32
|
if (buffer.includes('Enter a value:')) {
|
|
32
33
|
console.log(buffer);
|
|
33
34
|
buffer = '';
|
|
@@ -39,9 +40,7 @@ export class ProcessRunner {
|
|
|
39
40
|
});
|
|
40
41
|
return new Promise((resolve, reject) => {
|
|
41
42
|
child.on('close', (code) => {
|
|
42
|
-
|
|
43
|
-
scanner(buffer);
|
|
44
|
-
console.log(buffer);
|
|
43
|
+
processLine(buffer);
|
|
45
44
|
if (code === 0) {
|
|
46
45
|
if (errorBuffer) {
|
|
47
46
|
console.warn('Process completed successfully, but there were errors:\n' + errorBuffer);
|
|
@@ -103,7 +103,7 @@ export class TerraformAdapter {
|
|
|
103
103
|
throw new KnownException(`terraform apply failed with code ${error.code}:\n${error.message}`, { cause: error });
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
|
-
async destroy(env, tfArgs, cwd, attemptNo = 1) {
|
|
106
|
+
async destroy(env, tfArgs, force, cwd, attemptNo = 1) {
|
|
107
107
|
let wrongDir = false;
|
|
108
108
|
const scanner = (line) => {
|
|
109
109
|
if (line.includes('Either you have not created any objects yet or the existing objects were')) {
|
|
@@ -121,9 +121,14 @@ export class TerraformAdapter {
|
|
|
121
121
|
}
|
|
122
122
|
const lockId = this.lockId(error, attemptNo);
|
|
123
123
|
if (lockId) {
|
|
124
|
-
|
|
124
|
+
if (force) {
|
|
125
|
+
await this.forceUnlock(lockId, cwd);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
await this.promptUnlock(lockId, cwd);
|
|
129
|
+
}
|
|
125
130
|
console.info('State unlocked, retrying terraform destroy');
|
|
126
|
-
return this.destroy(env, tfArgs, cwd, attemptNo + 1);
|
|
131
|
+
return this.destroy(env, tfArgs, force, cwd, attemptNo + 1);
|
|
127
132
|
}
|
|
128
133
|
throw new KnownException(`terraform destroy failed with code ${error.code}:\n${error.message}`, { cause: error });
|
|
129
134
|
}
|
|
@@ -147,6 +152,9 @@ export class TerraformAdapter {
|
|
|
147
152
|
if (!answerYes) {
|
|
148
153
|
throw new AbortedException();
|
|
149
154
|
}
|
|
155
|
+
await this.forceUnlock(id, cwd);
|
|
156
|
+
}
|
|
157
|
+
async forceUnlock(id, cwd) {
|
|
150
158
|
console.log('Force unlocking state');
|
|
151
159
|
await this.processRunner.run('terraform', ['force-unlock', '-force', id], cwd);
|
|
152
160
|
}
|
package/dist/commands/_keys.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export const _keys = {
|
|
2
2
|
CWD: 'Working directory (default: current directory)',
|
|
3
3
|
ENV: 'Environment name (can be git hash). {project}-{env} give env key used to store env state (s3 key in case of AWS)',
|
|
4
|
+
FORCE: 'Force deletion without confirmation',
|
|
4
5
|
KIND: 'Environment kind: complete project (default) or some slice such as tt-core + tt-web',
|
|
5
6
|
OWNER: 'Environment owner (GH username)',
|
|
6
7
|
PROJECT: 'Project code (like tt). Used when multiple projects deployed in same AWS account',
|
package/dist/commands/delete.js
CHANGED
|
@@ -8,7 +8,7 @@ export function deleteIt(program) {
|
|
|
8
8
|
.description('Delete a development environment')
|
|
9
9
|
.option('--project <project>', _keys.PROJECT)
|
|
10
10
|
.option('--env <env>', _keys.ENV)
|
|
11
|
-
.option('--force',
|
|
11
|
+
.option('--force', _keys.FORCE)
|
|
12
12
|
.option('--cwd <cwd>', _keys.CWD)
|
|
13
13
|
.action(wrap(handler));
|
|
14
14
|
}
|
package/dist/commands/destroy.js
CHANGED
|
@@ -10,13 +10,14 @@ export function destroy(program) {
|
|
|
10
10
|
+ ' Main use case - test deletion process, basically that you have enough permissions to delete resources')
|
|
11
11
|
.option('--project <project>', _keys.PROJECT)
|
|
12
12
|
.option('--env <env>', _keys.ENV)
|
|
13
|
+
.option('--force', _keys.FORCE)
|
|
13
14
|
.option('--cwd <cwd>', _keys.CWD)
|
|
14
15
|
.allowUnknownOption(true)
|
|
15
16
|
.argument('[args...]')
|
|
16
17
|
.action(wrap(handler));
|
|
17
18
|
}
|
|
18
19
|
async function handler(tfArgs, options) {
|
|
19
|
-
const { project, env, cwd } = options;
|
|
20
|
+
const { project, env, force, cwd } = options;
|
|
20
21
|
const envName = cliHelper.ensureEnv(env);
|
|
21
|
-
await envCtl.destroy(project, envName, tfArgs, cwd);
|
|
22
|
+
await envCtl.destroy(project, envName, tfArgs, Boolean(force), cwd);
|
|
22
23
|
}
|
package/dist/service/EnvCtl.js
CHANGED
|
@@ -183,14 +183,16 @@ export class EnvCtl {
|
|
|
183
183
|
const statusMessage = await this.envApi.delete(env);
|
|
184
184
|
console.log(statusMessage);
|
|
185
185
|
}
|
|
186
|
-
async destroy(project, envName, tfArgs, cwd) {
|
|
186
|
+
async destroy(project, envName, tfArgs, force, cwd) {
|
|
187
187
|
const env = await this.get(project, envName);
|
|
188
|
-
const kind = this.cliHelper.ensureKind(undefined, cwd);
|
|
189
|
-
if (env.kind && env.kind !== kind) {
|
|
190
|
-
throw new KnownException(`Env ${env.key} kind (dir-name): ${env.kind} - make sure you run destroy from the same directory`);
|
|
191
|
-
}
|
|
192
188
|
this.checkStatus(env);
|
|
193
|
-
|
|
189
|
+
if (!force) {
|
|
190
|
+
const kind = this.cliHelper.ensureKind(undefined, cwd);
|
|
191
|
+
if (env.kind && env.kind !== kind) {
|
|
192
|
+
throw new KnownException(`Env ${env.key} kind (dir-name): ${env.kind} - make sure you run destroy from the same directory`);
|
|
193
|
+
}
|
|
194
|
+
await this.promptUnlock(env, [EnvStatus.Creating]);
|
|
195
|
+
}
|
|
194
196
|
if (env.status === EnvStatus.Active) {
|
|
195
197
|
console.log('Lock env to run destroy');
|
|
196
198
|
await this.envApi.lockForUpdate(env);
|
|
@@ -198,13 +200,13 @@ export class EnvCtl {
|
|
|
198
200
|
const { owner, size, type, ephemeral } = env;
|
|
199
201
|
const tfEnv = { owner, size, type, ephemeral, env: envName };
|
|
200
202
|
console.log('Destroying env resources');
|
|
201
|
-
await this.terraformAdapter.destroy(tfEnv, tfArgs, cwd);
|
|
203
|
+
await this.terraformAdapter.destroy(tfEnv, tfArgs, force, cwd);
|
|
202
204
|
console.log('Unlock env');
|
|
203
205
|
await this.envApi.activate(env);
|
|
204
206
|
console.log('Schedule env metadata deletion');
|
|
205
207
|
const statusMessage = await this.envApi.delete(env);
|
|
206
208
|
console.log(statusMessage);
|
|
207
|
-
console.log('Please wait for ~
|
|
209
|
+
console.log('Please wait for ~15 sec before you can create env with same name');
|
|
208
210
|
}
|
|
209
211
|
async get(project, envName) {
|
|
210
212
|
const key = this.key(project, envName);
|
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.19.1",
|
|
5
5
|
"author": "Alex Chekulaev",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -25,18 +25,20 @@
|
|
|
25
25
|
"test": "vitest run --coverage",
|
|
26
26
|
"build": "tsc",
|
|
27
27
|
"run": "node dist/index.js",
|
|
28
|
-
"run-version": "tsc --sourceMap true && npm run run -- --version",
|
|
29
|
-
"run-configure": "tsc --sourceMap true && npm run run -- configure",
|
|
30
|
-
"run-status": "tsc --sourceMap true && npm run run -- status
|
|
31
|
-
"run-plan": "tsc --sourceMap true && npm run run -- plan
|
|
32
|
-
"run-deploy": "tsc --sourceMap true && npm run run -- deploy
|
|
33
|
-
"run-delete": "tsc --sourceMap true && npm run run -- delete
|
|
34
|
-
"run-destroy": "tsc --sourceMap true && npm run run -- destroy --cwd ../tt-core",
|
|
35
|
-
"
|
|
36
|
-
"run-api-create-ephemeral": "tsc --sourceMap true && npm run run -- api-create-ephemeral --env
|
|
37
|
-
"run-api-
|
|
38
|
-
"run-api-
|
|
39
|
-
"run-api-
|
|
28
|
+
"run-version": " tsc --sourceMap true && npm run run -- --version",
|
|
29
|
+
"run-configure": " tsc --sourceMap true && npm run run -- configure",
|
|
30
|
+
"run-status": " tsc --sourceMap true && npm run run -- status --cwd ../tt-core",
|
|
31
|
+
"run-plan": " tsc --sourceMap true && npm run run -- plan --cwd ../tt-core --size min",
|
|
32
|
+
"run-deploy": " tsc --sourceMap true && npm run run -- deploy --cwd ../tt-core --size min",
|
|
33
|
+
"run-delete": " tsc --sourceMap true && npm run run -- delete --cwd ../tt-core",
|
|
34
|
+
"run-destroy": " tsc --sourceMap true && npm run run -- destroy --cwd ../tt-core",
|
|
35
|
+
"-": "",
|
|
36
|
+
"run-api-create-ephemeral": "tsc --sourceMap true && npm run run -- api-create-ephemeral --env test --owner laxa1986 --size min --type dev",
|
|
37
|
+
"run-api-status": " tsc --sourceMap true && npm run run -- status --env test",
|
|
38
|
+
"run-api-init": " tsc --sourceMap true && npm run run -- init --env test --cwd ../tt-gitops",
|
|
39
|
+
"run-api-deploy": " tsc --sourceMap true && npm run run -- deploy --env test --cwd ../tt-gitops -var-file=versions.tfvars",
|
|
40
|
+
"run-api-delete": " tsc --sourceMap true && npm run run -- delete --env test --cwd ../tt-gitops --force",
|
|
41
|
+
"run-api-destroy": "tsc --sourceMap true && npm run run -- destroy --env test --cwd ../tt-gitops --force -var-file=versions.tfvars"
|
|
40
42
|
},
|
|
41
43
|
"dependencies": {
|
|
42
44
|
"@aws-sdk/client-sts": "^3.716.0",
|