@alertlogic/al-collector-js 3.0.6 → 3.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/Makefile CHANGED
@@ -20,6 +20,7 @@ clean:
20
20
  rm -rf node_modules
21
21
  rm -f package-lock.json
22
22
  rm -f test/report.xml
23
+ rm -f *.report.xml
23
24
  rm -rf ./coverage/
24
25
 
25
26
  publish:
package/README.md CHANGED
@@ -25,7 +25,9 @@ const {
25
25
  AzcollectC,
26
26
  EndpointsC,
27
27
  AlLog,
28
- Parse
28
+ Parse ,
29
+ RestServiceClient,
30
+ CollectorStatusC
29
31
  } = require('@alertlogic/al-collector-js');
30
32
  ```
31
33
 
@@ -90,6 +92,14 @@ const azCollectClient = new AzcollectC(apiEndpoint, aimsCreds, collectorType, se
90
92
  ```javascript
91
93
  const alEndpointsClient = EndpointsC(apiEndpoint, aimsCreds, retryOption);
92
94
  ```
95
+ ## CollectorStatusC
96
+ * @param {string} apiEndpoint - Alert Logic API hostname.
97
+ * @param {Object} aimsCreds - Alert Logic API credentials object, refer to AimsC.
98
+ * @param {*} retryOptions.
99
+
100
+ ```javascript
101
+ const alCollectorStatusClient = CollectorStatusC(apiEndpoint, aimsCreds, retryOption);
102
+ ```
93
103
 
94
104
  ## AlLog
95
105
  * @param hostId - host uuid obtained at collector registration
package/al_log.js CHANGED
@@ -185,7 +185,7 @@ function buildHostmeta({hostId, hostmetaElems}, callback) {
185
185
  let meta = {
186
186
  hostUuid : hostId,
187
187
  data : hostmetaData,
188
- dataChecksum : new Buffer('')
188
+ dataChecksum : Buffer.from('')
189
189
  };
190
190
  let sha = crypto.createHash('sha1');
191
191
  let hashPayload = hostmetaType.encode(meta).finish();
package/al_servicec.js CHANGED
@@ -34,7 +34,7 @@ class AimsC extends m_alUtil.RestServiceClient {
34
34
  super(apiEndpoint, retryOptions);
35
35
  this._cid = cid;
36
36
  this._aimsAuth = {
37
- user: aimsCreds.access_key_id,
37
+ username: aimsCreds.access_key_id,
38
38
  password: aimsCreds.secret_key
39
39
  };
40
40
  var cache = cacheDir ? cacheDir : DEFAULT_CACHE_DIR;
package/al_util.js CHANGED
@@ -7,9 +7,10 @@
7
7
  * @end
8
8
  * -----------------------------------------------------------------------------
9
9
  */
10
-
11
- const rp = require('request-promise-native');
10
+ const axios = require('axios');
12
11
  const retry = require('retry');
12
+ const http = require('http');
13
+ const https = require('https');
13
14
 
14
15
  let MAX_CONNS_PER_SERVICE = 128;
15
16
 
@@ -22,18 +23,26 @@ let DEFAULT_RETRY = {
22
23
  factor: 7,
23
24
  minTimeout: 300,
24
25
  retries: 2,
25
- maxTimeout: 10000
26
+ maxTimeout: 10000,
27
+ maxRetryTime: 180000
28
+ };
29
+
30
+ /**
31
+ * @default Refer to httpAgent and httpAgents axios
32
+ */
33
+ let DEFAULT_HTTP_HTTPS_AGENT_CONFIG = {
34
+ keepAlive: true,
35
+ maxSockets: MAX_CONNS_PER_SERVICE, // Maximum number of sockets to open
26
36
  };
27
37
 
38
+
28
39
  /**
29
- * @function Default retry callback.
30
- * It doesn't retry 2XX, 3XX and 4XX.
40
+ * @function Default retry callback.
41
+ * It doesn't retry 2XX, 3XX, and 4XX.
31
42
  * Keeps retrying 5XX HTTP responses and any system level errors
32
43
  **/
33
- var defaultRetryCb = function(err){
34
- if (err &&
35
- (err.statusCode >= 500 ||
36
- (err.error && err.error.errno))) {
44
+ var defaultRetryCb = function (err) {
45
+ if (err && (err.status >= 500) || (err.response && err.response.status >= 500) || (err.errno)) {
37
46
  return true;
38
47
  } else {
39
48
  return false;
@@ -45,8 +54,7 @@ var defaultRetryCb = function(err){
45
54
  * Rest client.
46
55
  *
47
56
  * @constructor
48
- * @param {string} endpoint - hostname/address to sent HTTPS
49
- * requests to.
57
+ * @param {string} endpoint - hostname/address to sent HTTPS requests to.
50
58
  *
51
59
  */
52
60
  class RestServiceClient {
@@ -54,9 +62,6 @@ class RestServiceClient {
54
62
  'use strict';
55
63
  this._host = endpoint;
56
64
  this._url = 'https://' + endpoint;
57
- this._pool = {
58
- maxSockets: MAX_CONNS_PER_SERVICE
59
- };
60
65
  if (retryOptions) {
61
66
  this._retryCb = retryOptions.retryCb ? retryOptions.retryCb : defaultRetryCb;
62
67
  delete retryOptions.retryCb;
@@ -72,40 +77,43 @@ class RestServiceClient {
72
77
  const defaultOptions = {
73
78
  method: method,
74
79
  url: this._url + path,
75
- json: true,
76
80
  headers: {},
77
- pool: this._pool
81
+ json: true,
82
+ httpAgent: new http.Agent(DEFAULT_HTTP_HTTPS_AGENT_CONFIG),
83
+ httpsAgent: new https.Agent(DEFAULT_HTTP_HTTPS_AGENT_CONFIG)
78
84
  };
79
85
  const options = Object.assign({}, defaultOptions, extra);
80
86
  const defaultHeaders = {
81
87
  'Accept': 'application/json'
82
88
  };
83
- Object.assign(options.headers,
84
- defaultHeaders,
85
- extra.headers ? extra.headers : {});
89
+ if (!options.data || options.body) {
90
+ options.data = options.body;
91
+ }
92
+ Object.assign(options.headers, defaultHeaders, extra.headers ? extra.headers : {});
86
93
  return options;
87
94
  }
95
+
88
96
  request(method, path, extraOptions) {
89
97
  'use strict';
90
98
  const options = this._initRequestOptions(method, path, extraOptions);
91
99
  const retryOptions = this._retryOptions;
92
100
  var retryCb = this._retryCb;
93
-
101
+
94
102
  var operation = retry.operation(retryOptions);
95
-
96
- return new Promise(function(resolve, reject) {
97
- operation.attempt(function(currentAttempt) {
98
- rp(options)
99
- .then( resp => {
100
- // We need opertaion.retry here as we want to check if
103
+
104
+ return new Promise(function (resolve, reject) {
105
+ operation.attempt(function (currentAttempt) {
106
+ axios(options)
107
+ .then(resp => {
108
+ // We need operation.retry here as we want to check if
101
109
  // the maximum amount of retries has been reached
102
110
  if (retryCb(resp) && operation.retry('retry')) {
103
111
  return;
104
112
  } else {
105
- return resolve(resp);
113
+ return resolve(resp.data);
106
114
  }
107
115
  })
108
- .catch( err =>{
116
+ .catch(err => {
109
117
  if (retryCb(err) && operation.retry(err)) {
110
118
  return;
111
119
  } else {
@@ -115,21 +123,27 @@ class RestServiceClient {
115
123
  });
116
124
  });
117
125
  }
126
+
118
127
  post(path, extraOptions) {
119
128
  return this.request('POST', path, extraOptions);
120
129
  }
130
+
121
131
  get(path, extraOptions) {
122
132
  return this.request('GET', path, extraOptions);
123
133
  }
134
+
124
135
  deleteRequest(path, extraOptions) {
125
136
  return this.request('DELETE', path, extraOptions);
126
137
  }
138
+
127
139
  put(path, extraOptions) {
128
140
  return this.request('PUT', path, extraOptions);
129
141
  }
142
+
130
143
  get host() {
131
144
  return this._host;
132
145
  }
146
+
133
147
  get url() {
134
148
  return this._url;
135
149
  }
@@ -138,4 +152,3 @@ class RestServiceClient {
138
152
  module.exports = {
139
153
  RestServiceClient: RestServiceClient
140
154
  };
141
-
@@ -31,7 +31,9 @@ class CollectorStatusC extends AlServiceC {
31
31
  },
32
32
  body: data
33
33
  };
34
- return this.put(`/statuses/${statusId}/streams/${stream}`, payload);
34
+ // Few collector stream contain `/` which not excepted by collectors_status service. so Encode the stream before making the api call.It will encodes special characters including: , / ? : @ & = + $ #
35
+ const encodedStream = encodeURIComponent(stream);
36
+ return this.put(`/statuses/${statusId}/streams/${encodedStream}`, payload);
35
37
  }
36
38
  }
37
39
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alertlogic/al-collector-js",
3
- "version": "3.0.6",
3
+ "version": "3.0.8",
4
4
  "license": "MIT",
5
5
  "description": "Alert Logic Collector Common Library",
6
6
  "repository": {
@@ -20,26 +20,25 @@
20
20
  }
21
21
  ],
22
22
  "devDependencies": {
23
- "jshint": "^2.9.5",
23
+ "jshint": "^2.13.6",
24
24
  "mocha": "^10.2.0",
25
- "mocha-jenkins-reporter": "^0.4.2",
26
- "nock": "^13.2.9",
25
+ "mocha-jenkins-reporter": "^0.4.8",
26
+ "nock": "^13.3.2",
27
27
  "nyc": "^15.1.0",
28
- "rewire": "^5.0.0",
29
- "sinon": "^15.0.1",
30
- "timekeeper": "^2.2.0"
28
+ "rewire": "^6.0.0",
29
+ "sinon": "^15.2.0",
30
+ "timekeeper": "^2.3.1"
31
31
  },
32
32
  "dependencies": {
33
- "async": "^3.2.4",
34
- "debug": "^4.3.4",
33
+ "async": "3.2.4",
34
+ "axios": "^1.4.0",
35
+ "debug": "4.3.4",
35
36
  "lodash.clonedeep": "^4.5.0",
36
37
  "lodash.filter": "^4.6.0",
37
38
  "lodash.remove": "^4.7.0",
38
- "moment": "^2.29.4",
39
- "protobufjs": "^7.1.2",
40
- "request": "^2.88.2",
41
- "request-promise-native": "^1.0.9",
42
- "retry": "^0.13.1"
39
+ "moment": "2.29.4",
40
+ "protobufjs": "^7.2.4",
41
+ "retry": "0.13.1"
43
42
  },
44
43
  "author": "Alert Logic Inc."
45
44
  }
package/test/al_mock.js CHANGED
@@ -16,7 +16,7 @@ const AIMS_CREDS = {
16
16
 
17
17
  const AIMS_AUTH = {
18
18
  auth : {
19
- user: AIMS_CREDS.access_key_id,
19
+ username: AIMS_CREDS.access_key_id,
20
20
  password: AIMS_CREDS.secret_key
21
21
  }
22
22
  };
@@ -159,6 +159,10 @@ const AIMS_RESPONSE_200 = {
159
159
  }
160
160
  };
161
161
 
162
+ const SERVER_ERROR_500 = {
163
+ statusCode: 500,
164
+ message: "Internal Server Error"
165
+ };
162
166
  function gen_auth_response() {
163
167
  return {
164
168
  authentication : {
@@ -188,6 +192,7 @@ module.exports = {
188
192
  AZURE_CHECKIN_VALUES: AZURE_CHECKIN_VALUES,
189
193
  SEND_COLLECTOR_STATUS_BODY_DATA: SEND_COLLECTOR_STATUS_BODY_DATA,
190
194
  COLLECTOR_STATUS_API: COLLECTOR_STATUS_API,
195
+ SERVER_ERROR_500: SERVER_ERROR_500,
191
196
 
192
197
  gen_auth_response : gen_auth_response
193
198
  };
@@ -132,5 +132,51 @@ describe('Unit Tests', function() {
132
132
  done();
133
133
  });
134
134
 
135
+ it('check it should return server error after retry', function (done) {
136
+ var restC = new RestServiceClient(m_alMock.AL_API);
137
+
138
+ nock('https://' + m_alMock.AL_API, {
139
+ reqheaders: {
140
+ 'accept': 'application/json',
141
+ 'host': m_alMock.AL_API,
142
+ 'some_header': 'some_value'
143
+ }
144
+ })
145
+ .post(TEST_PATH, TEST_BODY)
146
+ .reply(500, m_alMock.SERVER_ERROR_500);
147
+
148
+ restC.post(TEST_PATH, {
149
+ headers: { 'some_header': 'some_value' },
150
+ data: TEST_BODY
151
+ })
152
+ .catch(err => {
153
+ console.log(`err ${err}`);
154
+ done();
155
+ });
156
+ });
157
+
158
+ it('check it should success if last response is successful after server error 500', function (done) {
159
+ var restC = new RestServiceClient(m_alMock.AL_API);
160
+ var restMock = nock('https://' + m_alMock.AL_API, {
161
+ reqheaders: {
162
+ 'accept': 'application/json',
163
+ 'host': m_alMock.AL_API,
164
+ 'content-type': 'application/json',
165
+ 'some_header': 'some_value'
166
+ }
167
+ })
168
+ .post(TEST_PATH, TEST_BODY)
169
+ .reply(500, m_alMock.SERVER_ERROR_500)
170
+ .post(TEST_PATH, TEST_BODY)
171
+ .reply(200, m_alMock.AIMS_RESPONSE_200);
172
+
173
+ restC.post(TEST_PATH, {
174
+ headers: { 'some_header': 'some_value' },
175
+ body: TEST_BODY
176
+ }).then(res => {
177
+ assert.ok(restMock.isDone());
178
+ done();
179
+ });
180
+ });
135
181
  });
136
182
  });
@@ -54,6 +54,24 @@ describe('Unit Tests', function () {
54
54
  });
55
55
  });
56
56
 
57
+ it('it should encode the stream if it contain special char', function (done) {
58
+ let stream = 'projects/appliance-builds';
59
+ const encodedStream = encodeURIComponent(stream);
60
+ fakePut = sinon.stub(AlServiceC.prototype, 'put').callsFake(
61
+ function fakeFn(path, extraOptions) {
62
+ assert.equal(extraOptions.body, m_alMock.SEND_COLLECTOR_STATUS_BODY_DATA);
63
+ assert.equal(path, `/statuses/${m_alMock.SEND_COLLECTOR_STATUS_BODY_DATA.status_id}/streams/${encodedStream}`);
64
+ done();
65
+ });
66
+
67
+ var aimsc = new AimsC(m_alMock.AL_API, m_alMock.AIMS_CREDS);
68
+ var collectorStatus = new CollectorStatusC(m_alMock.COLLECTOR_STATUS_API, aimsc);
69
+ m_alMock.SEND_COLLECTOR_STATUS_BODY_DATA.stream = stream;
70
+ collectorStatus.sendStatus(m_alMock.SEND_COLLECTOR_STATUS_BODY_DATA.status_id, m_alMock.SEND_COLLECTOR_STATUS_BODY_DATA.stream, m_alMock.SEND_COLLECTOR_STATUS_BODY_DATA).then(res => {
71
+ fakePut.restore();
72
+ });
73
+ });
74
+
57
75
  it('If sequence of parameter is not correct then api throw the error', function (done) {
58
76
  const error = {
59
77
  "errorinfo": {
@@ -129,10 +129,10 @@ describe('Common parse functions unit tests.', function() {
129
129
  done();
130
130
  });
131
131
 
132
- it('Wrong timestamp input', function(done) {
133
- var privParseTs = parseWire.__get__('parseTs');
134
- assert.deepEqual(privParseTs('foo'), {sec: 1234567, usec: null});
135
-
132
+ it('Wrong timestamp input', function (done) {
133
+ let parseWire1 = rewire('../parse');
134
+ var privParseTs = parseWire1.__get__('parseTs');
135
+ assert.deepEqual(privParseTs('foo'), { sec: 1234567, usec: null });
136
136
  done();
137
137
  });
138
138
 
@@ -14,6 +14,7 @@ const nock = require('nock');
14
14
  const m_alMock = require('./al_mock');
15
15
  const m_alService = require('../al_servicec');
16
16
  const EndpointsC = require('../al_servicec').EndpointsC;
17
+ const moment = require('moment');
17
18
 
18
19
  describe('HTTP request retry tests', function() {
19
20
  beforeEach(function(done) {
@@ -79,7 +80,7 @@ describe('HTTP request retry tests', function() {
79
80
  var endpointsC = new EndpointsC(m_alMock.AL_API, aimsc, 'cwe');
80
81
 
81
82
  endpointsC.getEndpoint('azcollect', 'default').then( resp => {
82
- assert.equal(resp, undefined);
83
+ assert.equal(resp, '');
83
84
  done();
84
85
  });
85
86
  });
@@ -134,7 +135,8 @@ describe('HTTP request retry tests', function() {
134
135
  return done();
135
136
  })
136
137
  .catch(err => {
137
- assert.equal(err.statusCode, 401);
138
+ assert.equal(err.code , 'ERR_BAD_REQUEST');
139
+ assert.equal(err.response.status , 401);
138
140
  return done();
139
141
  });
140
142
  });
@@ -147,7 +149,7 @@ describe('HTTP request retry tests', function() {
147
149
  .post('/aims/v1/authenticate')
148
150
  .reply(201, m_alMock.AIMS_RESPONSE_200);
149
151
  var customRetry = function(resp) {
150
- if (resp.retryCode === customRetryCode) {
152
+ if (resp.data.retryCode === customRetryCode) {
151
153
  return true;
152
154
  } else {
153
155
  return false;
@@ -177,7 +179,7 @@ describe('HTTP request retry tests', function() {
177
179
  .post('/aims/v1/authenticate')
178
180
  .reply(201, m_alMock.AIMS_RESPONSE_200);
179
181
  var customRetry = function(resp) {
180
- if (resp.error.customError === customRetryCode) {
182
+ if (resp.customError === customRetryCode) {
181
183
  return false;
182
184
  } else {
183
185
  return true;
@@ -198,7 +200,36 @@ describe('HTTP request retry tests', function() {
198
200
  return done();
199
201
  })
200
202
  .catch(err =>{
201
- assert.equal(err.error.customError, customRetryCode);
203
+ assert.equal(err.customError, customRetryCode);
204
+ return done();
205
+ });
206
+ });
207
+
208
+ it('Retry 500 with custom retry config with maxRetryTime', function (done) {
209
+ const maxRetryTime = 1500;
210
+ const retryOptions = {
211
+ retries: 3,
212
+ factor: 2,
213
+ minTimeout: 300,
214
+ maxTimeout: 1000,
215
+ maxRetryTime: maxRetryTime,
216
+ };
217
+ nock('https://' + m_alMock.AL_API)
218
+ .post('/aims/v1/authenticate')
219
+ .times(4)
220
+ .reply(500, m_alMock.SERVER_ERROR_500);
221
+ var startTime = moment();
222
+ var aimsc = new m_alService.AimsC(
223
+ m_alMock.AL_API, m_alMock.AIMS_CREDS, '/tmp', retryOptions);
224
+ aimsc.authenticate()
225
+ .catch(err => {
226
+ assert.equal(err.response.status, 500);
227
+ var nowMoment = moment();
228
+ const elapsedTime = nowMoment.diff(startTime, 'milliseconds');
229
+ assert.ok(
230
+ elapsedTime >= maxRetryTime && elapsedTime <= maxRetryTime + retryOptions.maxTimeout,
231
+ 'Test case failed: Request did not complete within maxRetryTime.'
232
+ );
202
233
  return done();
203
234
  });
204
235
  });