@agilecustoms/envctl 1.20.3 → 1.22.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.
@@ -64,24 +64,22 @@ export class HttpClient {
64
64
  throw new Error('Error (network?) making the request:', { cause: error });
65
65
  }
66
66
  const contentType = response.headers?.get('Content-Type') || '';
67
+ const body = contentType.includes('application/json') ? await response.json() : await response.text();
67
68
  if (response.ok) {
68
- if (contentType.includes('application/json')) {
69
- return await response.json();
70
- }
71
- else {
72
- return await response.text();
73
- }
69
+ return body;
74
70
  }
75
- const message = await response.text();
76
71
  if (response.status === 404) {
77
- throw new NotFoundException(message);
72
+ throw new NotFoundException(body);
78
73
  }
79
74
  if (response.status === 422) {
80
- throw new BusinessException(message);
75
+ throw new BusinessException(body);
76
+ }
77
+ if (response.status === 426) {
78
+ throw new KnownException(body.message);
81
79
  }
82
80
  if (response.status >= 500) {
83
81
  logger.info('API Gateway request ID: ' + response.headers.get('x-amzn-requestid'));
84
82
  }
85
- throw new HttpException(`status: ${response.status}, ` + message);
83
+ throw new HttpException(`status: ${response.status}, ` + JSON.stringify(body));
86
84
  }
87
85
  }
@@ -10,7 +10,6 @@ export function configure(program, configService) {
10
10
  const profile = await input({ message: 'Profile name', default: 'default', required: true });
11
11
  const apiKey = await password({ message: 'API key', mask: true });
12
12
  const varKey = await input({ message: 'Terraform variable to auto populate with remote state key (empty to skip)' });
13
- const varEphemeral = await input({ message: 'Terraform variable to auto populate with flag "ephemeral" (empty to skip)' });
14
- configService.saveConfig(profile, { apiKey, varKey, varEphemeral });
13
+ configService.saveConfig(profile, { apiKey, varKey });
15
14
  }));
16
15
  }
@@ -61,9 +61,6 @@ export class ConfigService {
61
61
  getVarKey() {
62
62
  return this.config?.varKey;
63
63
  }
64
- getVarEphemeral() {
65
- return this.config?.varEphemeral;
66
- }
67
64
  getHost() {
68
65
  return this.config?.host || DEFAULT_HOST;
69
66
  }
@@ -48,26 +48,10 @@ export class EnvService extends BaseService {
48
48
  }
49
49
  return env;
50
50
  }
51
- checkDir(env) {
52
- if (env.ephemeral)
53
- return;
54
- if (env.dir) {
55
- const dir = this.cli.getDir();
56
- if (dir !== env.dir) {
57
- throw new KnownException(`Env ${env.key} was deployed from ${env.dir} - make sure you run this command from the same directory`);
58
- }
59
- }
60
- }
61
51
  async plan(tfArgs) {
62
52
  const key = this.terraformAdapter.getTerraformBackend().getKey();
63
- const env = await this.tryGetEnv(key);
64
- if (env) {
65
- this.checkDir(env);
66
- this.handleDeleteStatuses(env);
67
- }
68
- const newEnv = env === null;
69
- await this.lockTerraform(env, newEnv);
70
- await this.terraformAdapter.plan(env ?? { key, ephemeral: false }, tfArgs);
53
+ await this.lockTerraform(null, true);
54
+ await this.terraformAdapter.plan(key, tfArgs);
71
55
  }
72
56
  async createEphemeral(key) {
73
57
  const createEnv = { key };
@@ -85,14 +69,14 @@ export class EnvService extends BaseService {
85
69
  }
86
70
  }
87
71
  }
88
- handleDeleteStatuses(env) {
89
- if (env.status === EnvStatus.Deleting) {
90
- throw new KnownException(`Env ${env.key} status is DELETING, please wait.\n
91
- If it is DELETING more than 10 minutes, you can try to run 'envctl delete ${env.key} --force' to remove it`);
92
- }
93
- if (env.status === EnvStatus.DeleteError) {
94
- throw new KnownException(`Env ${env.key} status is DELETE_ERROR, most likely lack of permissions.\n
95
- Check logs with 'envctl logs', address the issue and re-run 'envctl delete ${env.key}'`);
72
+ checkDir(env) {
73
+ if (env.ephemeral)
74
+ return;
75
+ if (env.dir) {
76
+ const dir = this.cli.getDir();
77
+ if (dir !== env.dir) {
78
+ throw new KnownException(`Env ${env.key} was deployed from ${env.dir} - make sure you run this command from the same directory`);
79
+ }
96
80
  }
97
81
  }
98
82
  async apply(tfArgs) {
@@ -108,7 +92,14 @@ export class EnvService extends BaseService {
108
92
  return;
109
93
  }
110
94
  this.checkDir(env);
111
- this.handleDeleteStatuses(env);
95
+ if (env.status === EnvStatus.Deleting) {
96
+ throw new KnownException(`Env ${env.key} status is DELETING, please wait.\n
97
+ If it is DELETING more than 10 minutes, you can try to run 'envctl delete ${env.key} --force' to remove it`);
98
+ }
99
+ if (env.status === EnvStatus.DeleteError) {
100
+ throw new KnownException(`Env ${env.key} status is DELETE_ERROR, most likely lack of permissions.\n
101
+ Check logs with 'envctl logs', address the issue and re-run 'envctl delete ${env.key}'`);
102
+ }
112
103
  const status = env.status;
113
104
  if (status === EnvStatus.Init || status === EnvStatus.Active) {
114
105
  const newEnv = status === EnvStatus.Init;
@@ -145,7 +136,7 @@ export class EnvService extends BaseService {
145
136
  logger.info('Lock env to run destroy');
146
137
  await this.envApi.lockForUpdate(env);
147
138
  }
148
- await this.terraformAdapter.destroy(env, tfArgs, force);
139
+ await this.terraformAdapter.destroy(key, tfArgs, force);
149
140
  await this.envApi.delete(key, force);
150
141
  logger.info('Please wait for ~30 sec before you can create env with same name');
151
142
  }
@@ -120,7 +120,7 @@ export class TerraformAdapter {
120
120
  });
121
121
  logger.info(`\nTime EDT: ${edt}, UTC: ${utc}\n`);
122
122
  }
123
- tfArgs(env, args) {
123
+ tfArgs(key, args) {
124
124
  const varDefs = this.getVarDefs();
125
125
  const argVars = this.getArgVars(args);
126
126
  const extraArgs = [];
@@ -130,11 +130,7 @@ export class TerraformAdapter {
130
130
  const specialFields = {};
131
131
  const varKey = this.configService.getVarKey();
132
132
  if (varKey) {
133
- specialFields[varKey] = env.key;
134
- }
135
- const varEphemeral = this.configService.getVarEphemeral();
136
- if (varEphemeral) {
137
- specialFields[varEphemeral] = String(env.ephemeral);
133
+ specialFields[varKey] = key;
138
134
  }
139
135
  for (const name of Object.keys(specialFields)) {
140
136
  if (varDefs[name] && !argVars[name]) {
@@ -183,8 +179,8 @@ export class TerraformAdapter {
183
179
  });
184
180
  return result;
185
181
  }
186
- async plan(env, args) {
187
- args = this.tfArgs(env, args);
182
+ async plan(key, args) {
183
+ args = this.tfArgs(key, args);
188
184
  await this._plan(args, 1);
189
185
  }
190
186
  async _plan(args, attemptNo) {
@@ -212,7 +208,7 @@ export class TerraformAdapter {
212
208
  async apply(env, args) {
213
209
  const noPlan = args.every(arg => arg.startsWith('-'));
214
210
  if (noPlan) {
215
- args = this.tfArgs(env, args);
211
+ args = this.tfArgs(env.key, args);
216
212
  }
217
213
  logger.info('Running: terraform apply ' + args.join(' ') + '\n');
218
214
  try {
@@ -258,8 +254,8 @@ export class TerraformAdapter {
258
254
  throw new KnownException(`terraform apply failed with code ${error.code}:\n${error.message}`, { cause: error });
259
255
  }
260
256
  }
261
- async destroy(env, args, force) {
262
- args = this.tfArgs(env, args);
257
+ async destroy(key, args, force) {
258
+ args = this.tfArgs(key, args);
263
259
  await this._destroy(args, force);
264
260
  }
265
261
  async _destroy(args, force, attemptNo = 1) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agilecustoms/envctl",
3
- "version": "1.20.3",
3
+ "version": "1.22.0",
4
4
  "description": "node.js CLI client for manage environments",
5
5
  "keywords": [
6
6
  "terraform wrapper",
@@ -41,28 +41,35 @@
41
41
  "run-version": " npm run it -- --version",
42
42
  "run-configure": "npm run it -- configure",
43
43
  "run-logs": " npm run it -- logs",
44
- "-t1-": "",
45
- "t1-desc": "dev env (fully fledged ~/.envctl/default.json)",
46
- "t1": "CWD=../tt-core npm run it --",
47
- "t1-init": "cd ../tt-core && terraform init -upgrade -backend-config=key=t1 -reconfigure",
48
- "t1-status": "npm run t1 -- status --verbose",
49
- "t1-apply": " npm run t1 -- apply --auto-approve",
50
- "t1-delete": "npm run t1 -- delete",
51
- "-t2-": "",
52
- "t2-desc": "ephemeral env in CI (must have ENVCTL_API_KEY_ in env vars)",
53
- "t2": "CWD=../tt-core CI=true ENVCTL_HOME=non-existing ENVCTL_API_KEY=\"$ENVCTL_API_KEY_\" npm run it --",
54
- "t2-create": "npm run t2 -- create-ephemeral t2",
55
- "t2-init": "cd ../tt-core && terraform init -upgrade -backend-config=key=t2 -reconfigure",
56
- "t2-plan": " npm run t2 -- plan -var=env_size=min -var=env=t2 -out=plan",
57
- "t2-apply": " npm run t2 -- apply plan",
58
- "t2-delete": "npm run t2 -- delete",
59
- "-t3-": "",
60
- "t3-desc": "dev env destroy",
61
- "t3": "CWD=../tt-core npm run it --",
62
- "t3-init": "cd ../tt-core && terraform init -upgrade -backend-config=key=t3 -reconfigure",
63
- "t3-status": " npm run t3 -- status",
64
- "t3-apply": " npm run t3 -- apply --auto-approve -var=env_size=min",
65
- "t3-destroy": "npm run t3 -- destroy -var=env_size=min --auto-approve",
44
+ "-d1-": "",
45
+ "d1-desc": "dev env (fully fledged ~/.envctl/default.json)",
46
+ "d1": "CWD=../tt-core npm run it --",
47
+ "d1-init": "cd ../tt-core && terraform init -upgrade -backend-config=key=d1 -reconfigure",
48
+ "d1-status": "npm run d1 -- status --verbose",
49
+ "d1-apply": " npm run d1 -- apply --auto-approve",
50
+ "d1-delete": "npm run d1 -- delete",
51
+ "-d2-": "",
52
+ "d2-desc": "dev env destroy",
53
+ "d2": "CWD=../tt-core npm run it --",
54
+ "d2-init": "cd ../tt-core && terraform init -upgrade -backend-config=key=d2 -reconfigure",
55
+ "d2-status": " npm run d2 -- status",
56
+ "d2-apply": " npm run d2 -- apply --auto-approve -var=env_size=min",
57
+ "d2-destroy": "npm run d2 -- destroy -var=env_size=min --auto-approve",
58
+ "-d3-": "",
59
+ "d3-desc": "dev env plan apply",
60
+ "d3": "CWD=../tt-core npm run it --",
61
+ "d3-init": "cd ../tt-core && terraform init -upgrade -backend-config=key=d3 -reconfigure",
62
+ "d3-plan": " npm run d3 -- plan -var=env_size=min -var=env=d3 -out=plan",
63
+ "d3-apply": " npm run d3 -- apply plan",
64
+ "d3-delete": "npm run d3 -- delete",
65
+ "-e1-": "",
66
+ "e1-desc": "ephemeral env in CI (must have ENVCTL_API_KEY_ in env vars)",
67
+ "e1": "CWD=../tt-core CI=true ENVCTL_HOME=non-existing ENVCTL_API_KEY=\"$ENVCTL_API_KEY_\" npm run it --",
68
+ "e1-create": "npm run e1 -- create-ephemeral e1",
69
+ "e1-init": "cd ../tt-core && terraform init -upgrade -backend-config=key=e1 -reconfigure",
70
+ "e1-plan": " npm run e1 -- plan -var=env_size=min -var=env=e1 -out=plan",
71
+ "e1-apply": " npm run e1 -- apply plan",
72
+ "e1-delete": "npm run e1 -- delete",
66
73
  "-tt-": "",
67
74
  "tt-desc": "deploy TT project from local machine",
68
75
  "tt": "CWD=../tt-gitops AWS_PROFILE=ac-tt-dev-deployer npm run it --",