@agilecustoms/envctl 1.25.2 → 1.27.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.
@@ -1,4 +1,4 @@
1
- import { BusinessException, KnownException, NotFoundException } from '../exceptions.js';
1
+ import { KnownException, NotFoundException, UnauthorizedException } from '../exceptions.js';
2
2
  import { logger } from '../logger.js';
3
3
  import { EnvStatus } from '../model/index.js';
4
4
  import { format, toDate } from '../util.js';
@@ -14,7 +14,7 @@ export class EnvApiClient {
14
14
  async get(key) {
15
15
  logger.info(`Retrieve environment ${key}`);
16
16
  try {
17
- return await this.httpClient.fetch(`/ci/env/${key}`);
17
+ return await this.httpClient.fetch(`/env/${key}`);
18
18
  }
19
19
  catch (error) {
20
20
  if (error instanceof NotFoundException) {
@@ -29,37 +29,20 @@ export class EnvApiClient {
29
29
  result = await this.httpClient.post('/ci/env-ephemeral', env);
30
30
  }
31
31
  catch (error) {
32
- if (error instanceof BusinessException) {
33
- throw new KnownException(`Failed to create ephemeral environment: ${error.message}`);
32
+ if (error instanceof UnauthorizedException) {
33
+ throw new KnownException(`Developers are no authorized to create ephemeral environment\nPlease create dedicated CI user (with its own API key) per each pipeline`);
34
34
  }
35
35
  throw error;
36
36
  }
37
37
  return this.httpClient.getUrl(`/public/env/${env.key}/extend?token=${result.token}`);
38
38
  }
39
39
  async create(env) {
40
- let result;
41
- try {
42
- result = await this.httpClient.post('/ci/env', env);
43
- }
44
- catch (error) {
45
- if (error instanceof BusinessException) {
46
- throw new KnownException(`Failed to create environment: ${error.message}`);
47
- }
48
- throw error;
49
- }
40
+ const result = await this.httpClient.post('/env', env);
50
41
  logger.debug(`Environment ${env.key} created, will expire at ${format(toDate(result.ttl))}`);
51
42
  return { ...env, ephemeral: false, status: EnvStatus.Deploying, ttl: result.ttl };
52
43
  }
53
44
  async activate(env) {
54
- try {
55
- await this.httpClient.post(`/ci/env/${env.key}/activate`);
56
- }
57
- catch (error) {
58
- if (error instanceof BusinessException) {
59
- throw new KnownException(`Failed to activate environment ${env.key}: ${error.message}`);
60
- }
61
- throw error;
62
- }
45
+ await this.httpClient.post(`/env/${env.key}/activate`);
63
46
  env.status = EnvStatus.Active;
64
47
  }
65
48
  async lockForUpdate(env) {
@@ -68,23 +51,14 @@ export class EnvApiClient {
68
51
  stateFile: env.stateFile,
69
52
  lockFile: env.lockFile
70
53
  };
71
- let result;
72
- try {
73
- result = await this.httpClient.post(`/ci/env/${env.key}/lock-for-update`, body);
74
- }
75
- catch (error) {
76
- if (error instanceof BusinessException) {
77
- throw new KnownException(`Failed to lock environment ${env.key} for update: ${error.message}`);
78
- }
79
- throw error;
80
- }
54
+ const result = await this.httpClient.post(`/env/${env.key}/lock-for-update`, body);
81
55
  env.status = result.status;
82
56
  }
83
57
  async delete(key, force = false) {
84
58
  logger.info('Sending delete command');
85
59
  let result;
86
60
  try {
87
- result = await this.httpClient.fetch(`/ci/env/${key}?force=${force}`, {
61
+ result = await this.httpClient.fetch(`/env/${key}?force=${force}`, {
88
62
  method: 'DELETE'
89
63
  });
90
64
  }
@@ -99,7 +73,7 @@ export class EnvApiClient {
99
73
  async getLogs(key) {
100
74
  let result;
101
75
  try {
102
- result = await this.httpClient.fetch(`/ci/env/${key}/logs`);
76
+ result = await this.httpClient.fetch(`/env/${key}/logs`);
103
77
  }
104
78
  catch (error) {
105
79
  if (error instanceof NotFoundException) {
@@ -1,4 +1,4 @@
1
- import { BusinessException, HttpException, KnownException, NotFoundException } from '../exceptions.js';
1
+ import { HttpException, KnownException, NotFoundException, UnauthorizedException } from '../exceptions.js';
2
2
  import { logger } from '../logger.js';
3
3
  import { DEFAULT_HOST } from '../service/ConfigService.js';
4
4
  import { ConfigService } from '../service/index.js';
@@ -63,6 +63,7 @@ export class HttpClient {
63
63
  }
64
64
  throw new Error('Error (network?) making the request:', { cause: error });
65
65
  }
66
+ logger.debug(`response status: ${response.status}, text: ${response.statusText}`);
66
67
  const contentType = response.headers?.get('Content-Type') || '';
67
68
  let body = await response.text();
68
69
  if (contentType.includes('application/json')) {
@@ -79,11 +80,17 @@ export class HttpClient {
79
80
  if (response.ok) {
80
81
  return body;
81
82
  }
83
+ if (response.status === 401) {
84
+ throw new KnownException('API key is not recognized');
85
+ }
86
+ if (response.status === 403) {
87
+ throw new UnauthorizedException(JSON.stringify(body));
88
+ }
82
89
  if (response.status === 404) {
83
90
  throw new NotFoundException(body);
84
91
  }
85
92
  if (response.status === 422) {
86
- throw new BusinessException(body.message);
93
+ throw new KnownException(body.message);
87
94
  }
88
95
  if (response.status === 426) {
89
96
  throw new KnownException(body.message);
@@ -16,10 +16,10 @@ export class HttpException extends Error {
16
16
  this.name = 'HttpException';
17
17
  }
18
18
  }
19
- export class BusinessException extends HttpException {
19
+ export class UnauthorizedException extends HttpException {
20
20
  constructor(message) {
21
21
  super(message);
22
- this.name = 'BusinessException';
22
+ this.name = 'UnauthorizedException';
23
23
  }
24
24
  }
25
25
  export class NotFoundException extends HttpException {
@@ -34,7 +34,7 @@ export class EnvService extends BaseService {
34
34
  }
35
35
  async init(tfArgs) {
36
36
  await this.terraformAdapter.init(tfArgs);
37
- await this.terraformAdapter.lockProviders();
37
+ await this.terraformAdapter.lockProviders(tfArgs);
38
38
  }
39
39
  async plan(tfArgs) {
40
40
  this.terraformAdapter.validateAndGetStateFile();
@@ -136,11 +136,30 @@ export class TerraformAdapter {
136
136
  const config = this.localStateService.load();
137
137
  this.localStateService.save(config);
138
138
  }
139
- async lockProviders() {
139
+ getVars(args) {
140
+ const result = [];
141
+ for (let i = 0; i < args.length; i++) {
142
+ const arg = args[i];
143
+ if (arg.startsWith('-var=') || arg.startsWith('-var-file=')) {
144
+ result.push(arg);
145
+ continue;
146
+ }
147
+ if (arg === '-var' || arg === '-var-file') {
148
+ result.push(arg);
149
+ if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
150
+ result.push(args[i + 1]);
151
+ i++;
152
+ }
153
+ }
154
+ }
155
+ return result;
156
+ }
157
+ async lockProviders(args) {
140
158
  const linuxArm64 = process.platform === 'linux' && process.arch === 'arm64';
141
159
  if (!linuxArm64) {
142
160
  logger.info('Lock providers');
143
- await this.cli.run('terraform', ['providers', 'lock', '-platform=linux_arm64']);
161
+ const vars = this.getVars(args);
162
+ await this.cli.run('terraform', ['providers', 'lock', '-platform=linux_arm64', ...vars]);
144
163
  }
145
164
  const fileContent = this.getLockFile();
146
165
  const config = this.localStateService.load();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agilecustoms/envctl",
3
- "version": "1.25.2",
3
+ "version": "1.27.0",
4
4
  "description": "node.js CLI client for manage environments",
5
5
  "keywords": [
6
6
  "terraform wrapper",
@@ -74,7 +74,7 @@
74
74
  "-e1-": "",
75
75
  "e1-desc": "ephemeral env in CI (must have ENVCTL_API_KEY_ in env vars)",
76
76
  "e1": "CWD=../tt-core CI=true ENVCTL_HOME=non-existing ENVCTL_API_KEY=\"$ENVCTL_API_KEY_\" npm run it --",
77
- "e1-create": "npm run e1 -- create-ephemeral e1",
77
+ "e1-create": "npm run e1 -- create-ephemeral e1 --verbose",
78
78
  "e1-init": " npm run e1 -- init -reconfigure -upgrade -backend-config=key=e1",
79
79
  "e1-plan": " npm run e1 -- plan -var=env_size=min -var=env=e1 -out=plan",
80
80
  "e1-apply": " npm run e1 -- apply plan",
@@ -82,7 +82,7 @@
82
82
  "-tt-": "",
83
83
  "tt-desc": "deploy TT project from local machine",
84
84
  "tt": "CWD=../tt-gitops AWS_PROFILE=ac-tt-dev-deployer npm run it --",
85
- "run-init": " npm run tt -- init -reconfigure -upgrade -backend-config=key=laxa1986",
85
+ "run-init": " npm run tt -- init -reconfigure -upgrade -backend-config=key=laxa1986 -var-file=versions.tfvars",
86
86
  "run-status": " npm run tt -- status",
87
87
  "run-apply": " npm run tt -- apply --auto-approve -var=env_size=min -var-file=versions.tfvars",
88
88
  "run-delete": " npm run tt -- delete"