@terascope/scripts 2.0.6 → 2.0.8
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/src/cmds/test.d.ts +0 -1
- package/dist/src/cmds/test.d.ts.map +1 -1
- package/dist/src/cmds/test.js +0 -7
- package/dist/src/cmds/test.js.map +1 -1
- package/dist/src/helpers/config.d.ts.map +1 -1
- package/dist/src/helpers/config.js +0 -5
- package/dist/src/helpers/config.js.map +1 -1
- package/dist/src/helpers/kind.d.ts.map +1 -1
- package/dist/src/helpers/kind.js +14 -2
- package/dist/src/helpers/kind.js.map +1 -1
- package/dist/src/helpers/scripts.d.ts +0 -3
- package/dist/src/helpers/scripts.d.ts.map +1 -1
- package/dist/src/helpers/scripts.js +1 -58
- package/dist/src/helpers/scripts.js.map +1 -1
- package/dist/src/helpers/test-runner/index.d.ts.map +1 -1
- package/dist/src/helpers/test-runner/index.js +12 -15
- package/dist/src/helpers/test-runner/index.js.map +1 -1
- package/dist/src/helpers/test-runner/interfaces.d.ts +0 -1
- package/dist/src/helpers/test-runner/interfaces.d.ts.map +1 -1
- package/dist/src/helpers/test-runner/services.d.ts.map +1 -1
- package/dist/src/helpers/test-runner/services.js +1 -9
- package/dist/src/helpers/test-runner/services.js.map +1 -1
- package/dist/src/helpers/test-runner/utils.d.ts.map +1 -1
- package/dist/src/helpers/test-runner/utils.js +0 -1
- package/dist/src/helpers/test-runner/utils.js.map +1 -1
- package/dist/src/index.d.ts +0 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +0 -1
- package/dist/src/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/src/helpers/k8s-env/k8s.d.ts +0 -29
- package/dist/src/helpers/k8s-env/k8s.d.ts.map +0 -1
- package/dist/src/helpers/k8s-env/k8s.js +0 -323
- package/dist/src/helpers/k8s-env/k8s.js.map +0 -1
|
@@ -1,323 +0,0 @@
|
|
|
1
|
-
import * as k8sClient from '@kubernetes/client-node';
|
|
2
|
-
import fs from 'node:fs';
|
|
3
|
-
import ms from 'ms';
|
|
4
|
-
import path from 'node:path';
|
|
5
|
-
import { execaCommand } from 'execa';
|
|
6
|
-
import { cloneDeep, debugLogger, pDelay, TSError } from '@terascope/core-utils';
|
|
7
|
-
import { getE2eK8sDir } from '../../helpers/packages.js';
|
|
8
|
-
import signale from '../signale.js';
|
|
9
|
-
import config from '../config.js';
|
|
10
|
-
import { getVolumesFromDockerfile } from '../kind.js';
|
|
11
|
-
const logger = debugLogger('ts-scripts:k8s-env');
|
|
12
|
-
export class K8s {
|
|
13
|
-
kc;
|
|
14
|
-
k8sAppsV1Api;
|
|
15
|
-
k8sCoreV1Api;
|
|
16
|
-
k8sRbacAuthorizationV1Api;
|
|
17
|
-
k8sSchedulingV1Api;
|
|
18
|
-
terasliceNamespace;
|
|
19
|
-
servicesNamespace;
|
|
20
|
-
tsPort;
|
|
21
|
-
kindClusterName;
|
|
22
|
-
constructor(tsPort, kindClusterName) {
|
|
23
|
-
this.kc = new k8sClient.KubeConfig();
|
|
24
|
-
this.kc.loadFromDefault();
|
|
25
|
-
this.k8sAppsV1Api = this.kc.makeApiClient(k8sClient.AppsV1Api);
|
|
26
|
-
this.k8sCoreV1Api = this.kc.makeApiClient(k8sClient.CoreV1Api);
|
|
27
|
-
this.k8sRbacAuthorizationV1Api = this.kc.makeApiClient(k8sClient.RbacAuthorizationV1Api);
|
|
28
|
-
this.k8sSchedulingV1Api = this.kc.makeApiClient(k8sClient.SchedulingV1Api);
|
|
29
|
-
this.terasliceNamespace = 'default';
|
|
30
|
-
this.servicesNamespace = 'default';
|
|
31
|
-
this.tsPort = tsPort;
|
|
32
|
-
this.kindClusterName = kindClusterName;
|
|
33
|
-
}
|
|
34
|
-
async createNamespace(yamlFile, namespaceCategory) {
|
|
35
|
-
signale.pending(`Creating new namespace for ${namespaceCategory}`);
|
|
36
|
-
const namespaceSpec = this.loadYamlFile(yamlFile);
|
|
37
|
-
try {
|
|
38
|
-
const createNamespaceRes = await this.k8sCoreV1Api.createNamespace({
|
|
39
|
-
body: namespaceSpec
|
|
40
|
-
});
|
|
41
|
-
if (createNamespaceRes?.metadata?.name) {
|
|
42
|
-
if (namespaceCategory === 'teraslice') {
|
|
43
|
-
this.terasliceNamespace = createNamespaceRes.metadata.name;
|
|
44
|
-
signale.success(`Teraslice namespace set to ${createNamespaceRes.metadata.name}`);
|
|
45
|
-
}
|
|
46
|
-
else if (namespaceCategory === 'services') {
|
|
47
|
-
this.servicesNamespace = createNamespaceRes.metadata.name;
|
|
48
|
-
signale.success(`Services namespace set to ${createNamespaceRes.metadata.name}`);
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
signale.success(`Namespace ${createNamespaceRes.metadata.name} created`);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
catch (err) {
|
|
56
|
-
throw new Error(`Error creating namespace for ${namespaceCategory}: ${err}`);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
mountLocalTeraslice(masterDeployment) {
|
|
60
|
-
const dockerfileMounts = getVolumesFromDockerfile(true, logger);
|
|
61
|
-
if (masterDeployment.spec?.template.spec?.containers[0].volumeMounts) {
|
|
62
|
-
masterDeployment.spec.template.spec.containers[0].volumeMounts
|
|
63
|
-
.push(...dockerfileMounts.volumeMounts);
|
|
64
|
-
}
|
|
65
|
-
if (masterDeployment.spec?.template.spec?.volumes) {
|
|
66
|
-
masterDeployment.spec.template.spec.volumes
|
|
67
|
-
.push(...dockerfileMounts.volumes);
|
|
68
|
-
}
|
|
69
|
-
/// Pass in env so master passes volumes to ex's and workers
|
|
70
|
-
if (masterDeployment.spec?.template.spec?.containers[0].env) {
|
|
71
|
-
masterDeployment.spec.template.spec.containers[0].env.push({
|
|
72
|
-
name: 'MOUNT_LOCAL_TERASLICE',
|
|
73
|
-
value: JSON.stringify(dockerfileMounts)
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
else if (masterDeployment.spec?.template.spec?.containers[0]) {
|
|
77
|
-
masterDeployment.spec.template.spec.containers[0].env = [
|
|
78
|
-
{
|
|
79
|
-
name: 'MOUNT_LOCAL_TERASLICE',
|
|
80
|
-
value: JSON.stringify(dockerfileMounts)
|
|
81
|
-
}
|
|
82
|
-
];
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
async deployK8sTeraslice(clustering, wait, dev, assetStorage = 'elasticsearch-next') {
|
|
86
|
-
signale.pending('Begin teraslice deployment...');
|
|
87
|
-
const e2eK8sDir = getE2eK8sDir();
|
|
88
|
-
if (!e2eK8sDir) {
|
|
89
|
-
throw new Error('Missing k8s e2e test directory');
|
|
90
|
-
}
|
|
91
|
-
await this.deleteTerasliceNamespace('ts-ns.yaml');
|
|
92
|
-
await this.createNamespace('ts-ns.yaml', 'teraslice');
|
|
93
|
-
await this.k8sSetup();
|
|
94
|
-
const baseConfigMap = this.loadYamlFile('baseConfigmap.yaml');
|
|
95
|
-
try {
|
|
96
|
-
/// Creates configmap for teraslice-master
|
|
97
|
-
const masterTerafoundation = this.loadYamlFile('masterConfig/teraslice.yaml');
|
|
98
|
-
const { teraslice } = masterTerafoundation;
|
|
99
|
-
teraslice.kubernetes_image = `teraslice-workspace:e2e-nodev${config.NODE_VERSION}`;
|
|
100
|
-
teraslice.cluster_manager_type = clustering;
|
|
101
|
-
teraslice.asset_storage_connection_type = assetStorage;
|
|
102
|
-
const masterConfigMap = cloneDeep(baseConfigMap);
|
|
103
|
-
masterConfigMap.data = { 'teraslice.yaml': k8sClient.dumpYaml(masterTerafoundation) };
|
|
104
|
-
masterConfigMap.metadata = { name: 'teraslice-master' };
|
|
105
|
-
const response = await this.k8sCoreV1Api.createNamespacedConfigMap({
|
|
106
|
-
namespace: this.terasliceNamespace,
|
|
107
|
-
body: masterConfigMap
|
|
108
|
-
});
|
|
109
|
-
logger.debug('deployK8sTeraslice masterConfigMap:', response);
|
|
110
|
-
}
|
|
111
|
-
catch (err) {
|
|
112
|
-
throw new Error(`Error creating Teraslice Master Configmap: ${err}`);
|
|
113
|
-
}
|
|
114
|
-
try {
|
|
115
|
-
/// Creates configmap for teraslice-worker
|
|
116
|
-
const workerTerafoundation = this.loadYamlFile('workerConfig/teraslice.yaml');
|
|
117
|
-
const { teraslice } = workerTerafoundation;
|
|
118
|
-
teraslice.kubernetes_image = `teraslice-workspace:e2e-nodev${config.NODE_VERSION}`;
|
|
119
|
-
teraslice.cluster_manager_type = clustering;
|
|
120
|
-
teraslice.asset_storage_connection_type = assetStorage;
|
|
121
|
-
const workerConfigMap = cloneDeep(baseConfigMap);
|
|
122
|
-
workerConfigMap.data = { 'teraslice.yaml': k8sClient.dumpYaml(workerTerafoundation) };
|
|
123
|
-
workerConfigMap.metadata = { name: 'teraslice-worker' };
|
|
124
|
-
const response = await this.k8sCoreV1Api.createNamespacedConfigMap({
|
|
125
|
-
namespace: this.terasliceNamespace,
|
|
126
|
-
body: workerConfigMap
|
|
127
|
-
});
|
|
128
|
-
logger.debug('deployK8sTeraslice workerConfigMap:', response);
|
|
129
|
-
}
|
|
130
|
-
catch (err) {
|
|
131
|
-
throw new Error(`Error creating Teraslice Worker Configmap: ${err}`);
|
|
132
|
-
}
|
|
133
|
-
try {
|
|
134
|
-
/// Creates master deployment for teraslice
|
|
135
|
-
const yamlTSMasterDeployment = this.loadYamlFile('masterDeployment.yaml');
|
|
136
|
-
if (yamlTSMasterDeployment.spec?.template.metadata?.labels) {
|
|
137
|
-
yamlTSMasterDeployment.spec.template.metadata.labels['app.kubernetes.io/instance'] = this.kindClusterName;
|
|
138
|
-
}
|
|
139
|
-
if (yamlTSMasterDeployment.spec?.template.spec?.containers[0]) {
|
|
140
|
-
yamlTSMasterDeployment.spec.template.spec.containers[0].image = `teraslice-workspace:e2e-nodev${config.NODE_VERSION}`;
|
|
141
|
-
}
|
|
142
|
-
if (dev) {
|
|
143
|
-
this.mountLocalTeraslice(yamlTSMasterDeployment);
|
|
144
|
-
}
|
|
145
|
-
const response = await this.k8sAppsV1Api.createNamespacedDeployment({
|
|
146
|
-
namespace: this.terasliceNamespace,
|
|
147
|
-
body: yamlTSMasterDeployment
|
|
148
|
-
});
|
|
149
|
-
logger.debug('deployK8sTeraslice yamlTSMasterDeployment: ', response);
|
|
150
|
-
}
|
|
151
|
-
catch (err) {
|
|
152
|
-
throw new Error(`Error creating Teraslice Master Deployment: ${err}`);
|
|
153
|
-
}
|
|
154
|
-
try {
|
|
155
|
-
/// Creates master service for teraslice
|
|
156
|
-
const yamlTSMasterService = this.loadYamlFile('masterService.yaml');
|
|
157
|
-
const response = await this.k8sCoreV1Api.createNamespacedService({
|
|
158
|
-
namespace: this.terasliceNamespace,
|
|
159
|
-
body: yamlTSMasterService
|
|
160
|
-
});
|
|
161
|
-
logger.debug('deployK8sTeraslice yamlTSMasterService: ', response);
|
|
162
|
-
if (wait) {
|
|
163
|
-
await this.waitForTerasliceRunning();
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
catch (err) {
|
|
167
|
-
throw new Error(`Error creating Teraslice Master Service: ${err}`);
|
|
168
|
-
}
|
|
169
|
-
signale.success('Teraslice deployment complete');
|
|
170
|
-
}
|
|
171
|
-
async waitForTerasliceRunning() {
|
|
172
|
-
const startTime = Date.now();
|
|
173
|
-
signale.pending('Waiting for Teraslice...');
|
|
174
|
-
await this.waitForTerasliceResponse();
|
|
175
|
-
const elapsed = Date.now() - startTime;
|
|
176
|
-
signale.success(`Teraslice is ready to go at port ${config.TERASLICE_PORT}, took ${ms(elapsed)}`);
|
|
177
|
-
}
|
|
178
|
-
waitForTerasliceResponse(timeoutMs = 120000) {
|
|
179
|
-
const endAt = Date.now() + timeoutMs;
|
|
180
|
-
const _waitForTerasliceRunning = async () => {
|
|
181
|
-
let response;
|
|
182
|
-
if (Date.now() > endAt) {
|
|
183
|
-
throw new Error(`Failure to communicate with teraslice after ${timeoutMs}ms. Last response from curl request to teraslice root: ${response}`);
|
|
184
|
-
}
|
|
185
|
-
let terasliceRunning = false;
|
|
186
|
-
try {
|
|
187
|
-
// TODO: switch to a teraslice client
|
|
188
|
-
const tsResponse = await execaCommand(`curl http://${config.HOST_IP}:${this.tsPort}`);
|
|
189
|
-
response = JSON.parse(tsResponse.stdout);
|
|
190
|
-
if (response.clustering_type === 'kubernetesV2') {
|
|
191
|
-
terasliceRunning = true;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
catch (err) {
|
|
195
|
-
await pDelay(3000);
|
|
196
|
-
return _waitForTerasliceRunning();
|
|
197
|
-
}
|
|
198
|
-
if (terasliceRunning) {
|
|
199
|
-
return true;
|
|
200
|
-
}
|
|
201
|
-
await pDelay(3000);
|
|
202
|
-
return _waitForTerasliceRunning();
|
|
203
|
-
};
|
|
204
|
-
return _waitForTerasliceRunning();
|
|
205
|
-
}
|
|
206
|
-
async k8sSetup() {
|
|
207
|
-
const e2eK8sDir = getE2eK8sDir();
|
|
208
|
-
if (!e2eK8sDir) {
|
|
209
|
-
throw new Error('Missing k8s e2e test directory');
|
|
210
|
-
}
|
|
211
|
-
try {
|
|
212
|
-
const yamlServiceAccount = this.loadYamlFile('masterServiceAccount.yaml');
|
|
213
|
-
const response = await this.k8sCoreV1Api.createNamespacedServiceAccount({
|
|
214
|
-
namespace: this.terasliceNamespace,
|
|
215
|
-
body: yamlServiceAccount
|
|
216
|
-
});
|
|
217
|
-
logger.debug('deployK8sTeraslice yamlmasterServiceAccount: ', response);
|
|
218
|
-
}
|
|
219
|
-
catch (err) {
|
|
220
|
-
throw new Error(`Error creating ServiceAccount: ${err}`);
|
|
221
|
-
}
|
|
222
|
-
try {
|
|
223
|
-
const yamlRole = this.loadYamlFile('role.yaml');
|
|
224
|
-
const response = await this.k8sRbacAuthorizationV1Api.createNamespacedRole({
|
|
225
|
-
namespace: this.terasliceNamespace,
|
|
226
|
-
body: yamlRole
|
|
227
|
-
});
|
|
228
|
-
logger.debug('deployK8sTeraslice yamlRole: ', response);
|
|
229
|
-
}
|
|
230
|
-
catch (err) {
|
|
231
|
-
throw new Error(`Error creating role: ${err}`);
|
|
232
|
-
}
|
|
233
|
-
try {
|
|
234
|
-
const yamlRoleBinding = this.loadYamlFile('roleBinding.yaml');
|
|
235
|
-
const response = await this.k8sRbacAuthorizationV1Api.createNamespacedRoleBinding({
|
|
236
|
-
namespace: this.terasliceNamespace,
|
|
237
|
-
body: yamlRoleBinding
|
|
238
|
-
});
|
|
239
|
-
logger.debug('deployK8sTeraslice yamlRoleBinding: ', response);
|
|
240
|
-
}
|
|
241
|
-
catch (err) {
|
|
242
|
-
throw new Error(`Error creating roleBinding: ${err}`);
|
|
243
|
-
}
|
|
244
|
-
try {
|
|
245
|
-
const yamlPriorityClass = this.loadYamlFile('priorityClass.yaml', 'utf8');
|
|
246
|
-
const response = await this.k8sSchedulingV1Api.createPriorityClass({
|
|
247
|
-
body: yamlPriorityClass
|
|
248
|
-
});
|
|
249
|
-
logger.debug('deployK8sTeraslice yamlPriorityClass: ', response);
|
|
250
|
-
}
|
|
251
|
-
catch (err) {
|
|
252
|
-
if (err.code !== 409) { // don't throw if priorityClass already exists
|
|
253
|
-
throw new Error(`Error creating priorityClass: ${err}`);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
async deleteTerasliceNamespace(yamlFile) {
|
|
258
|
-
const namespaceSpec = this.loadYamlFile(yamlFile);
|
|
259
|
-
if (!namespaceSpec.metadata?.name) {
|
|
260
|
-
logger.error(`Failure to delete Teraslice namespace: Missing 'metadata.name' from ${yamlFile} namespace yaml file.`);
|
|
261
|
-
process.exit(1);
|
|
262
|
-
}
|
|
263
|
-
const terasliceNamespace = namespaceSpec.metadata.name;
|
|
264
|
-
try {
|
|
265
|
-
const response = await this.k8sCoreV1Api.deleteNamespace({ name: terasliceNamespace });
|
|
266
|
-
logger.debug('Teraslice namespace delete response: ', response);
|
|
267
|
-
}
|
|
268
|
-
catch (err) {
|
|
269
|
-
logger.debug('Teraslice namespace cannot be deleted. It might not yet exist: ', err.response);
|
|
270
|
-
}
|
|
271
|
-
await this.confirmNamespaceDeletion(terasliceNamespace, this.k8sCoreV1Api);
|
|
272
|
-
}
|
|
273
|
-
async confirmNamespaceDeletion(terasliceNamespace, coreV1Api) {
|
|
274
|
-
let existingNamespace;
|
|
275
|
-
const timeoutMs = 120000;
|
|
276
|
-
try {
|
|
277
|
-
const endAt = Date.now() + timeoutMs;
|
|
278
|
-
do {
|
|
279
|
-
if (Date.now() > endAt) {
|
|
280
|
-
throw new Error(`Failure to delete Teraslice namespace after ${timeoutMs}ms. Aborting. You may need to restart the k8s environment.`);
|
|
281
|
-
}
|
|
282
|
-
await pDelay(1000);
|
|
283
|
-
const response = await coreV1Api.listNamespace();
|
|
284
|
-
const namespaceList = response.items;
|
|
285
|
-
existingNamespace = namespaceList
|
|
286
|
-
.filter((namespace) => namespace.metadata?.name === terasliceNamespace);
|
|
287
|
-
} while (existingNamespace.length > 0);
|
|
288
|
-
}
|
|
289
|
-
catch (err) {
|
|
290
|
-
logger.error('Error confirming deletion of Teraslice namespace: ', err);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
loadYamlFile(yamlFile, encoding = 'utf8') {
|
|
294
|
-
const e2eK8sDir = getE2eK8sDir();
|
|
295
|
-
if (!e2eK8sDir) {
|
|
296
|
-
throw new Error('Missing k8s e2e test directory');
|
|
297
|
-
}
|
|
298
|
-
try {
|
|
299
|
-
return k8sClient.loadYaml(fs.readFileSync(`${path.join(e2eK8sDir, yamlFile)}`, encoding));
|
|
300
|
-
}
|
|
301
|
-
catch (err) {
|
|
302
|
-
throw new Error(`Failed to load ${yamlFile} yaml file: ${err}`);
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
// TODO: add functions to create services
|
|
306
|
-
/**
|
|
307
|
-
* Create a kubernetes secret within a specified namespace.
|
|
308
|
-
* The namespace MUST already exist or it will throw
|
|
309
|
-
* @param secret
|
|
310
|
-
*/
|
|
311
|
-
async createKubernetesSecret(namespace, secret) {
|
|
312
|
-
try {
|
|
313
|
-
await this.k8sCoreV1Api.createNamespacedSecret({
|
|
314
|
-
namespace,
|
|
315
|
-
body: secret
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
catch (err) {
|
|
319
|
-
throw new TSError(`Unable to make kubernetes secret. \n ${err}`);
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
//# sourceMappingURL=k8s.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"k8s.js","sourceRoot":"","sources":["../../../../src/helpers/k8s-env/k8s.ts"],"names":[],"mappings":"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"}
|