@agilecustoms/envctl 1.25.1 → 1.25.2
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/dist/client/EnvApiClient.js +3 -2
- package/dist/logger.js +7 -1
- package/dist/service/EnvService.js +23 -39
- package/dist/service/TerraformAdapter.js +2 -5
- package/dist/util.js +4 -2
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BusinessException, KnownException, NotFoundException } from '../exceptions.js';
|
|
2
2
|
import { logger } from '../logger.js';
|
|
3
3
|
import { EnvStatus } from '../model/index.js';
|
|
4
|
-
import {
|
|
4
|
+
import { format, toDate } from '../util.js';
|
|
5
5
|
import { HttpClient } from './HttpClient.js';
|
|
6
6
|
export class EnvApiClient {
|
|
7
7
|
httpClient;
|
|
@@ -12,6 +12,7 @@ export class EnvApiClient {
|
|
|
12
12
|
return await fetch(url);
|
|
13
13
|
}
|
|
14
14
|
async get(key) {
|
|
15
|
+
logger.info(`Retrieve environment ${key}`);
|
|
15
16
|
try {
|
|
16
17
|
return await this.httpClient.fetch(`/ci/env/${key}`);
|
|
17
18
|
}
|
|
@@ -46,7 +47,7 @@ export class EnvApiClient {
|
|
|
46
47
|
}
|
|
47
48
|
throw error;
|
|
48
49
|
}
|
|
49
|
-
logger.debug(`
|
|
50
|
+
logger.debug(`Environment ${env.key} created, will expire at ${format(toDate(result.ttl))}`);
|
|
50
51
|
return { ...env, ephemeral: false, status: EnvStatus.Deploying, ttl: result.ttl };
|
|
51
52
|
}
|
|
52
53
|
async activate(env) {
|
package/dist/logger.js
CHANGED
|
@@ -22,7 +22,13 @@ export class Logger {
|
|
|
22
22
|
this.log('error', msg);
|
|
23
23
|
}
|
|
24
24
|
log(level, msg) {
|
|
25
|
-
const date = new Date(this.now()).
|
|
25
|
+
const date = new Date(this.now()).toLocaleString('en-US', {
|
|
26
|
+
hour: '2-digit',
|
|
27
|
+
minute: '2-digit',
|
|
28
|
+
second: '2-digit',
|
|
29
|
+
fractionalSecondDigits: 3,
|
|
30
|
+
hour12: false,
|
|
31
|
+
});
|
|
26
32
|
const detailedMessage = `${date} [${level}] ${msg}`;
|
|
27
33
|
this.buffer.push(detailedMessage);
|
|
28
34
|
if (!this.isDebugEnabled() && level === 'debug') {
|
|
@@ -3,7 +3,7 @@ import { EnvApiClient } from '../client/index.js';
|
|
|
3
3
|
import { KnownException } from '../exceptions.js';
|
|
4
4
|
import { logger } from '../logger.js';
|
|
5
5
|
import { EnvStatus } from '../model/index.js';
|
|
6
|
-
import {
|
|
6
|
+
import { format, toDate } from '../util.js';
|
|
7
7
|
import { BaseService } from './BaseService.js';
|
|
8
8
|
import { ApplyMode, getApplyMode } from './TerraformAdapter.js';
|
|
9
9
|
export class EnvService extends BaseService {
|
|
@@ -16,34 +16,22 @@ export class EnvService extends BaseService {
|
|
|
16
16
|
}
|
|
17
17
|
async status(key) {
|
|
18
18
|
key = this.getKey(key);
|
|
19
|
-
logger.info(`Retrieve env ${key}`);
|
|
20
19
|
const env = await this.envApi.get(key);
|
|
21
20
|
if (env === null) {
|
|
22
|
-
logger.info(`
|
|
21
|
+
logger.info(`Environment ${key} does not exist`);
|
|
23
22
|
return;
|
|
24
23
|
}
|
|
25
|
-
logger.info(`
|
|
24
|
+
logger.info(`Environment ${key} status: ${env.status}`);
|
|
26
25
|
if (env.status !== EnvStatus.Deleting && env.status !== EnvStatus.DeleteError) {
|
|
27
|
-
logger.info(`Expires at ${
|
|
26
|
+
logger.info(`Expires at ${format(toDate(env.ttl))}`);
|
|
28
27
|
}
|
|
29
28
|
if (env.dir) {
|
|
30
29
|
const dir = this.cli.getDir();
|
|
31
30
|
if (env.dir !== dir) {
|
|
32
|
-
logger.warn(`
|
|
31
|
+
logger.warn(`Environment ${key} was deployed from ${env.dir}`);
|
|
33
32
|
}
|
|
34
33
|
}
|
|
35
34
|
}
|
|
36
|
-
async getEnv(key) {
|
|
37
|
-
logger.info(`Check if env ${key} already exists`);
|
|
38
|
-
const env = await this.envApi.get(key);
|
|
39
|
-
if (env) {
|
|
40
|
-
logger.info(`Env ${key} status: ${env.status}`);
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
logger.info(`Env ${key} does not exist`);
|
|
44
|
-
}
|
|
45
|
-
return env;
|
|
46
|
-
}
|
|
47
35
|
async init(tfArgs) {
|
|
48
36
|
await this.terraformAdapter.init(tfArgs);
|
|
49
37
|
await this.terraformAdapter.lockProviders();
|
|
@@ -64,7 +52,7 @@ export class EnvService extends BaseService {
|
|
|
64
52
|
if (env.dir) {
|
|
65
53
|
const dir = this.cli.getDir();
|
|
66
54
|
if (dir !== env.dir) {
|
|
67
|
-
throw new KnownException(`
|
|
55
|
+
throw new KnownException(`Environment ${env.key} was deployed from ${env.dir} - make sure you run this command from the same directory`);
|
|
68
56
|
}
|
|
69
57
|
}
|
|
70
58
|
}
|
|
@@ -72,27 +60,29 @@ export class EnvService extends BaseService {
|
|
|
72
60
|
const { stateFile, stateUpdated } = this.terraformAdapter.validateAndGetStateFile();
|
|
73
61
|
const key = this.terraformAdapter.getKey();
|
|
74
62
|
const { lockFile, lockUpdated } = this.terraformAdapter.validateAndGetLockFile();
|
|
75
|
-
|
|
76
|
-
let env = await this.getEnv(key);
|
|
63
|
+
let env = await this.envApi.get(key);
|
|
77
64
|
if (env === null) {
|
|
65
|
+
logger.info(`Environment ${key} does not exist`);
|
|
78
66
|
const dir = this.cli.getDir();
|
|
79
67
|
const createEnv = { key, dir, stateFile, lockFile };
|
|
80
|
-
logger.info('Creating
|
|
68
|
+
logger.info('Creating environment metadata');
|
|
81
69
|
env = await this.envApi.create(createEnv);
|
|
82
70
|
await this.runApply(env, tfArgs);
|
|
83
71
|
return env;
|
|
84
72
|
}
|
|
73
|
+
logger.info(`Environment ${key} status: ${env.status}`);
|
|
85
74
|
this.checkDir(env);
|
|
86
75
|
if (env.status === EnvStatus.Deleting) {
|
|
87
|
-
throw new KnownException(`
|
|
76
|
+
throw new KnownException(`Environment ${env.key} status is DELETING, please wait.\n
|
|
88
77
|
If it is DELETING more than 10 minutes, you can try to run 'envctl delete ${env.key} --force' to remove it`);
|
|
89
78
|
}
|
|
90
79
|
if (env.status === EnvStatus.DeleteError) {
|
|
91
|
-
throw new KnownException(`
|
|
80
|
+
throw new KnownException(`Environment ${env.key} status is DELETE_ERROR, most likely lack of permissions.\n
|
|
92
81
|
Check logs with 'envctl logs', address the issue and re-run 'envctl delete ${env.key}'`);
|
|
93
82
|
}
|
|
94
83
|
const status = env.status;
|
|
95
84
|
if (status === EnvStatus.Init) {
|
|
85
|
+
const applyMode = getApplyMode(tfArgs);
|
|
96
86
|
if (applyMode === ApplyMode.Default) {
|
|
97
87
|
throw new KnownException('Either run apply with planfile or with flag -auto-approve');
|
|
98
88
|
}
|
|
@@ -115,9 +105,8 @@ export class EnvService extends BaseService {
|
|
|
115
105
|
}
|
|
116
106
|
async runApply(env, tfArgs) {
|
|
117
107
|
this.terraformAdapter.saveHashes();
|
|
118
|
-
logger.info('Deploying resources');
|
|
119
108
|
await this.terraformAdapter.apply(env, tfArgs);
|
|
120
|
-
logger.info('
|
|
109
|
+
logger.info('Activate environment');
|
|
121
110
|
await this.envApi.activate(env);
|
|
122
111
|
return env;
|
|
123
112
|
}
|
|
@@ -127,30 +116,25 @@ export class EnvService extends BaseService {
|
|
|
127
116
|
}
|
|
128
117
|
async destroy(tfArgs, force) {
|
|
129
118
|
const key = this.terraformAdapter.getKey();
|
|
130
|
-
const env = await this.get(key);
|
|
119
|
+
const env = await this.envApi.get(key);
|
|
120
|
+
if (!env) {
|
|
121
|
+
throw new KnownException(`Environment ${key} is not found`);
|
|
122
|
+
}
|
|
123
|
+
logger.info(`Environment status: ${env.status}`);
|
|
131
124
|
if (env.status === EnvStatus.Init) {
|
|
132
|
-
logger.info(`
|
|
125
|
+
logger.info(`Environment ${env.key} status is INIT - no resources, nothing to destroy, just deleting metadata`);
|
|
133
126
|
await this.envApi.delete(key, force);
|
|
134
127
|
return;
|
|
135
128
|
}
|
|
136
129
|
if (env.status === EnvStatus.Deleting && !force) {
|
|
137
|
-
throw new KnownException(`
|
|
130
|
+
throw new KnownException(`Environment ${env.key} status is DELETING, please wait or re-run with --force`);
|
|
138
131
|
}
|
|
139
132
|
if (env.status === EnvStatus.Active) {
|
|
140
|
-
logger.info('Lock
|
|
133
|
+
logger.info('Lock environment to run destroy');
|
|
141
134
|
await this.envApi.lockForUpdate(env);
|
|
142
135
|
}
|
|
143
136
|
await this.terraformAdapter.destroy(key, tfArgs, force);
|
|
144
137
|
await this.envApi.delete(key, force);
|
|
145
|
-
logger.info('Please wait for ~30 sec before you can create
|
|
146
|
-
}
|
|
147
|
-
async get(key) {
|
|
148
|
-
logger.info(`Retrieve env ${key}`);
|
|
149
|
-
const env = await this.envApi.get(key);
|
|
150
|
-
if (!env) {
|
|
151
|
-
throw new KnownException(`Environment ${key} is not found`);
|
|
152
|
-
}
|
|
153
|
-
logger.info(`Env status: ${env.status}`);
|
|
154
|
-
return env;
|
|
138
|
+
logger.info('Please wait for ~30 sec before you can create environment with same name');
|
|
155
139
|
}
|
|
156
140
|
}
|
|
@@ -5,6 +5,7 @@ import { confirm } from '@inquirer/prompts';
|
|
|
5
5
|
import {} from '../client/Cli.js';
|
|
6
6
|
import { AbortedException, KnownException, ProcessException, TimeoutException } from '../exceptions.js';
|
|
7
7
|
import { logger } from '../logger.js';
|
|
8
|
+
import { format } from '../util.js';
|
|
8
9
|
import { LocalStateService } from './LocalStateService.js';
|
|
9
10
|
export const MAX_ATTEMPTS = 2;
|
|
10
11
|
export const RETRYABLE_ERRORS = [
|
|
@@ -148,11 +149,7 @@ export class TerraformAdapter {
|
|
|
148
149
|
}
|
|
149
150
|
printTime() {
|
|
150
151
|
const now = new Date();
|
|
151
|
-
|
|
152
|
-
const edt = now.toLocaleString('en-US', {
|
|
153
|
-
timeZone: 'America/New_York'
|
|
154
|
-
});
|
|
155
|
-
logger.info(`\nTime EDT: ${edt}, UTC: ${utc}\n`);
|
|
152
|
+
logger.info(`\nLocal time: ${format(now)}, UTC: ${now.toISOString()}\n`);
|
|
156
153
|
}
|
|
157
154
|
tfArgs(key, args) {
|
|
158
155
|
const varDefs = this.getVarDefs();
|
package/dist/util.js
CHANGED