teraslice 2.14.3 → 2.14.4

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.
@@ -44,7 +44,7 @@ export class K8s {
44
44
  });
45
45
  throw error;
46
46
  }
47
- return namespaces.body;
47
+ return namespaces;
48
48
  }
49
49
  /**
50
50
  * Returns the first pod matching the provided selector after it has
@@ -67,10 +67,10 @@ export class K8s {
67
67
  let now = Date.now();
68
68
  const end = now + timeout;
69
69
  while (true) {
70
- const result = await pRetry(() => this.k8sCoreV1Api
71
- .listNamespacedPod(namespace, undefined, undefined, undefined, undefined, selector), getRetryConfig());
70
+ const podListObj = await pRetry(() => this.k8sCoreV1Api
71
+ .listNamespacedPod({ namespace, labelSelector: selector }), getRetryConfig());
72
72
  // NOTE: This assumes the first pod returned.
73
- const pod = get(result, 'body.items[0]');
73
+ const pod = get(podListObj, 'items[0]');
74
74
  if (pod && isTSPod(pod)) {
75
75
  if (statusType === 'readiness-probe') {
76
76
  if (pod.status.conditions) {
@@ -110,9 +110,9 @@ export class K8s {
110
110
  let now = Date.now();
111
111
  const end = now + timeout;
112
112
  while (true) {
113
- const result = await pRetry(() => this.k8sCoreV1Api
114
- .listNamespacedPod(namespace, undefined, undefined, undefined, undefined, selector), getRetryConfig());
115
- const podList = get(result, 'body.items');
113
+ const podListObj = await pRetry(() => this.k8sCoreV1Api
114
+ .listNamespacedPod({ namespace, labelSelector: selector }), getRetryConfig());
115
+ const podList = get(podListObj, 'items');
116
116
  if (podList.length === number)
117
117
  return podList;
118
118
  const msg = `Waiting: pods matching ${selector} is ${podList.length}/${number}`;
@@ -125,37 +125,33 @@ export class K8s {
125
125
  }
126
126
  async list(selector, objType, ns) {
127
127
  const namespace = ns || this.defaultNamespace;
128
- let responseObj;
129
- const params = [
128
+ let resourceListObj;
129
+ const params = {
130
130
  namespace,
131
- undefined,
132
- undefined,
133
- undefined,
134
- undefined,
135
- selector
136
- ];
131
+ labelSelector: selector
132
+ };
137
133
  try {
138
134
  if (objType === 'deployments') {
139
- responseObj = await pRetry(() => this.k8sAppsV1Api.listNamespacedDeployment(...params), getRetryConfig());
135
+ resourceListObj = await pRetry(() => this.k8sAppsV1Api.listNamespacedDeployment(params), getRetryConfig());
140
136
  }
141
137
  else if (objType === 'jobs') {
142
- responseObj = await pRetry(() => this.k8sBatchV1Api.listNamespacedJob(...params), getRetryConfig());
138
+ resourceListObj = await pRetry(() => this.k8sBatchV1Api.listNamespacedJob(params), getRetryConfig());
143
139
  }
144
140
  else if (objType === 'pods') {
145
- responseObj = await pRetry(() => this.k8sCoreV1Api.listNamespacedPod(...params), getRetryConfig());
141
+ resourceListObj = await pRetry(() => this.k8sCoreV1Api.listNamespacedPod(params), getRetryConfig());
146
142
  }
147
143
  else if (objType === 'replicasets') {
148
- responseObj = await pRetry(() => this.k8sAppsV1Api.listNamespacedReplicaSet(...params), getRetryConfig());
144
+ resourceListObj = await pRetry(() => this.k8sAppsV1Api.listNamespacedReplicaSet(params), getRetryConfig());
149
145
  }
150
146
  else if (objType === 'services') {
151
- responseObj = await pRetry(() => this.k8sCoreV1Api.listNamespacedService(...params), getRetryConfig());
147
+ resourceListObj = await pRetry(() => this.k8sCoreV1Api.listNamespacedService(params), getRetryConfig());
152
148
  }
153
149
  else {
154
150
  const error = new Error(`Invalid objType provided to get: ${objType}`);
155
151
  this.logger.error(error);
156
152
  return Promise.reject(error);
157
153
  }
158
- return convertToTSResourceList(responseObj.body);
154
+ return convertToTSResourceList(resourceListObj);
159
155
  }
160
156
  catch (e) {
161
157
  const err = new Error(`Request k8s.list of ${objType} with selector ${selector} failed: ${e}`);
@@ -180,33 +176,34 @@ export class K8s {
180
176
  }
181
177
  }
182
178
  async post(manifest) {
183
- let responseObj;
179
+ let resourceObj;
180
+ const namespace = this.defaultNamespace;
184
181
  try {
185
182
  if (isDeployment(manifest)) {
186
- responseObj = await this.k8sAppsV1Api
187
- .createNamespacedDeployment(this.defaultNamespace, manifest);
183
+ resourceObj = await this.k8sAppsV1Api
184
+ .createNamespacedDeployment({ namespace, body: manifest });
188
185
  }
189
186
  else if (isJob(manifest)) {
190
- responseObj = await this.k8sBatchV1Api
191
- .createNamespacedJob(this.defaultNamespace, manifest);
187
+ resourceObj = await this.k8sBatchV1Api
188
+ .createNamespacedJob({ namespace, body: manifest });
192
189
  }
193
190
  else if (isPod(manifest)) {
194
- responseObj = await this.k8sCoreV1Api
195
- .createNamespacedPod(this.defaultNamespace, manifest);
191
+ resourceObj = await this.k8sCoreV1Api
192
+ .createNamespacedPod({ namespace, body: manifest });
196
193
  }
197
194
  else if (isReplicaSet(manifest)) {
198
- responseObj = await this.k8sAppsV1Api
199
- .createNamespacedReplicaSet(this.defaultNamespace, manifest);
195
+ resourceObj = await this.k8sAppsV1Api
196
+ .createNamespacedReplicaSet({ namespace, body: manifest });
200
197
  }
201
198
  else if (isService(manifest)) {
202
- responseObj = await this.k8sCoreV1Api
203
- .createNamespacedService(this.defaultNamespace, manifest);
199
+ resourceObj = await this.k8sCoreV1Api
200
+ .createNamespacedService({ namespace, body: manifest });
204
201
  }
205
202
  else {
206
203
  const error = new Error('Invalid manifest type');
207
204
  return Promise.reject(error);
208
205
  }
209
- return convertToTSResource(responseObj.body);
206
+ return convertToTSResource(resourceObj);
210
207
  }
211
208
  catch (e) {
212
209
  const err = new Error(`Request k8s.post of ${manifest.kind} with body ${JSON.stringify(manifest)} failed: ${e}`);
@@ -217,7 +214,7 @@ export class K8s {
217
214
  * Patches specified k8s deployment with the provided record
218
215
  * @param {String} record record, like 'app=teraslice'
219
216
  * @param {String} name Name of the deployment to patch
220
- * @return {Object} body of k8s patch response.
217
+ * @return {Object} k8s V1Deployment object.
221
218
  */
222
219
  // TODO: I renamed this from patchDeployment to just patch because this is
223
220
  // the low level k8s api method, I expect to eventually change the interface
@@ -225,10 +222,13 @@ export class K8s {
225
222
  async patch(record, name) {
226
223
  let responseObj;
227
224
  try {
228
- const options = { headers: { 'Content-type': k8s.PatchUtils.PATCH_FORMAT_JSON_PATCH } };
229
- responseObj = await pRetry(() => this.k8sAppsV1Api
230
- .patchNamespacedDeployment(name, this.defaultNamespace, record, undefined, undefined, undefined, undefined, undefined, options), getRetryConfig());
231
- return responseObj.body;
225
+ const options = k8s.setHeaderOptions('Content-Type', k8s.PatchStrategy.JsonPatch);
226
+ responseObj = await pRetry(() => this.k8sAppsV1Api.patchNamespacedDeployment({
227
+ name,
228
+ namespace: this.defaultNamespace,
229
+ body: record
230
+ }, options), getRetryConfig());
231
+ return responseObj;
232
232
  }
233
233
  catch (e) {
234
234
  const err = new Error(`Request k8s.patch with name: ${name} failed with: ${e}`);
@@ -252,27 +252,23 @@ export class K8s {
252
252
  if (force) {
253
253
  deleteOptions.gracePeriodSeconds = 1;
254
254
  }
255
- const params = [
255
+ const params = {
256
256
  name,
257
- this.defaultNamespace,
258
- undefined,
259
- undefined,
260
- undefined,
261
- undefined,
262
- undefined,
263
- deleteOptions
264
- ];
257
+ namespace: this.defaultNamespace,
258
+ body: deleteOptions
259
+ };
265
260
  const deleteWithErrorHandling = async (deleteFn) => {
266
261
  try {
267
262
  const res = await deleteFn();
268
263
  return res;
269
264
  }
270
265
  catch (e) {
271
- if (e.statusCode) {
266
+ if (e.body) {
267
+ const bodyObj = JSON.parse(e.body);
272
268
  // 404 should be an acceptable response to a delete request, not an error
273
- if (e.statusCode === 404) {
269
+ if (bodyObj.code === 404) {
274
270
  this.logger.info(`No ${objType} with name ${name} found while attempting to delete.`);
275
- return e;
271
+ return bodyObj;
276
272
  }
277
273
  }
278
274
  throw e;
@@ -281,28 +277,28 @@ export class K8s {
281
277
  try {
282
278
  if (objType === 'services') {
283
279
  responseObj = await pRetry(() => deleteWithErrorHandling(() => this.k8sCoreV1Api
284
- .deleteNamespacedService(...params)), getRetryConfig());
280
+ .deleteNamespacedService(params)), getRetryConfig());
285
281
  }
286
282
  else if (objType === 'deployments') {
287
283
  responseObj = await pRetry(() => deleteWithErrorHandling(() => this.k8sAppsV1Api
288
- .deleteNamespacedDeployment(...params)), getRetryConfig());
284
+ .deleteNamespacedDeployment(params)), getRetryConfig());
289
285
  }
290
286
  else if (objType === 'jobs') {
291
287
  responseObj = await pRetry(() => deleteWithErrorHandling(() => this.k8sBatchV1Api
292
- .deleteNamespacedJob(...params)), getRetryConfig());
288
+ .deleteNamespacedJob(params)), getRetryConfig());
293
289
  }
294
290
  else if (objType === 'pods') {
295
291
  responseObj = await pRetry(() => deleteWithErrorHandling(() => this.k8sCoreV1Api
296
- .deleteNamespacedPod(...params)), getRetryConfig());
292
+ .deleteNamespacedPod(params)), getRetryConfig());
297
293
  }
298
294
  else if (objType === 'replicasets') {
299
295
  responseObj = await pRetry(() => deleteWithErrorHandling(() => this.k8sAppsV1Api
300
- .deleteNamespacedReplicaSet(...params)), getRetryConfig());
296
+ .deleteNamespacedReplicaSet(params)), getRetryConfig());
301
297
  }
302
298
  else {
303
299
  throw new Error(`Invalid objType: ${objType}`);
304
300
  }
305
- return responseObj.body;
301
+ return responseObj;
306
302
  }
307
303
  catch (e) {
308
304
  const err = new Error(`Request k8s.delete with name: ${name} failed with: ${e}`);
@@ -110,6 +110,12 @@ describe('k8s', () => {
110
110
  kind: 'Status',
111
111
  status: 'Success'
112
112
  };
113
+ const apiException = {
114
+ 'HTTP-Code': 400,
115
+ Message: 'Unknown API Status Code!',
116
+ Body: { statusCode: 400 },
117
+ Headers: { 'content-type': 'application/json' }
118
+ };
113
119
  beforeEach(async () => {
114
120
  nock(_url)
115
121
  .get('/api/v1/namespaces')
@@ -280,16 +286,16 @@ describe('k8s', () => {
280
286
  const response = await k8s.patch({ name: 'testName' }, 'test1');
281
287
  expect(response).toEqual({});
282
288
  });
283
- it('will throw on a reponse code >= 400', async () => {
289
+ it('will throw on a response code >= 400', async () => {
284
290
  nock(_url)
285
291
  .patch('/apis/apps/v1/namespaces/default/deployments/bad-response')
286
- .replyWithError({ statusCode: 400 })
292
+ .reply(400, apiException)
287
293
  .patch('/apis/apps/v1/namespaces/default/deployments/bad-response')
288
- .replyWithError({ statusCode: 400 })
294
+ .reply(400, apiException)
289
295
  .patch('/apis/apps/v1/namespaces/default/deployments/bad-response')
290
- .replyWithError({ statusCode: 400 });
296
+ .reply(400, apiException);
291
297
  await expect(k8s.patch({ name: 'bad-response' }, 'bad-response'))
292
- .rejects.toThrow('Request k8s.patch with name: bad-response failed with: TSError: {"statusCode":400}');
298
+ .rejects.toThrow('HTTP-Code: 400');
293
299
  });
294
300
  });
295
301
  describe('->delete', () => {
@@ -336,39 +342,36 @@ describe('k8s', () => {
336
342
  const response = await k8s.delete('test1', 'replicasets');
337
343
  expect(response).toEqual({});
338
344
  });
339
- it('will throw on a reponse code >= 400, excluding 404', async () => {
345
+ it('will throw on a response code >= 400, excluding 404', async () => {
340
346
  nock(_url)
341
347
  .delete('/api/v1/namespaces/default/pods/bad-response')
342
- .replyWithError({ statusCode: 400 })
348
+ .reply(400, apiException)
343
349
  .delete('/api/v1/namespaces/default/pods/bad-response')
344
- .replyWithError({ statusCode: 400 })
350
+ .reply(400, apiException)
345
351
  .delete('/api/v1/namespaces/default/pods/bad-response')
346
- .replyWithError({ statusCode: 400 });
352
+ .reply(400, apiException);
347
353
  await expect(k8s.delete('bad-response', 'pods'))
348
- .rejects.toThrow('Request k8s.delete with name: bad-response failed with: TSError: {"statusCode":400}');
354
+ .rejects.toThrow('HTTP-Code: 400');
349
355
  });
350
356
  it('will succeed on a 404 response code', async () => {
351
357
  const notFoundResponse = {
352
- body: {
353
- kind: 'Status',
354
- apiVersion: 'v1',
355
- metadata: {},
356
- status: 'Failure',
357
- message: 'pods "non-existent" not found',
358
- reason: 'NotFound',
359
- details: { name: 'non-existent', kind: 'pods' },
360
- code: 404
361
- },
362
- statusCode: 404
358
+ kind: 'Status',
359
+ apiVersion: 'v1',
360
+ metadata: {},
361
+ status: 'Failure',
362
+ message: 'pods "non-existent" not found',
363
+ reason: 'NotFound',
364
+ details: { name: 'non-existent', kind: 'pods' },
365
+ code: 404
363
366
  };
364
367
  nock(_url)
365
368
  .delete('/api/v1/namespaces/default/pods/non-existent')
366
- .replyWithError(notFoundResponse);
369
+ .reply(404, notFoundResponse);
367
370
  const response = await k8s.delete('non-existent', 'pods');
368
- expect(response).toEqual(notFoundResponse.body);
371
+ expect(response).toEqual(notFoundResponse);
369
372
  });
370
373
  });
371
- describe('->_deletObjByExId', () => {
374
+ describe('->_deleteObjByExId', () => {
372
375
  it('can delete a single object', async () => {
373
376
  nock(_url)
374
377
  .get('/apis/batch/v1/namespaces/default/jobs')
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "teraslice",
3
3
  "displayName": "Teraslice",
4
- "version": "2.14.3",
4
+ "version": "2.14.4",
5
5
  "description": "Distributed computing platform for processing JSON data",
6
6
  "homepage": "https://github.com/terascope/teraslice#readme",
7
7
  "bugs": {
@@ -38,7 +38,7 @@
38
38
  "ms": "~2.1.3"
39
39
  },
40
40
  "dependencies": {
41
- "@kubernetes/client-node": "~0.22.3",
41
+ "@kubernetes/client-node": "~1.1.1",
42
42
  "@terascope/elasticsearch-api": "~4.9.0",
43
43
  "@terascope/job-components": "~1.10.0",
44
44
  "@terascope/teraslice-messaging": "~1.11.0",
@@ -62,7 +62,7 @@
62
62
  "semver": "~7.7.1",
63
63
  "socket.io": "~1.7.4",
64
64
  "socket.io-client": "~1.7.4",
65
- "terafoundation": "~1.12.0",
65
+ "terafoundation": "~1.12.1",
66
66
  "uuid": "~11.1.0"
67
67
  },
68
68
  "devDependencies": {