screwdriver-queue-service 2.0.18 → 2.0.22

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.
@@ -290,4 +290,6 @@ kafka:
290
290
  # Amazon secret access key
291
291
  secretAccessKey: KAFKA_ACCESS_KEY_SECRET
292
292
  # AWS region
293
- region: AWS_REGION
293
+ region: AWS_REGION
294
+ # Flag to use Short Region Name like use2,usw2
295
+ shortRegion : USE_SHORT_REGION_NAME
@@ -221,4 +221,6 @@ kafka:
221
221
  # Amazon secret access key
222
222
  secretAccessKey: KAFKA_ACCESS_KEY_SECRET
223
223
  # AWS region
224
- region: AWS_REGION
224
+ region: AWS_REGION
225
+ # Flag to use Short Region Name like use2,usw2
226
+ shortRegion : true
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+
3
+ const config = require('config');
4
+ const kafkaConfig = config.get('kafka');
5
+
6
+ /**
7
+ * get config
8
+ * @returns Object containing kafka config values
9
+ */
10
+ function get() {
11
+ return {
12
+ kafkaEnabled: kafkaConfig.enabled === 'true',
13
+ useShortRegionName: kafkaConfig.shortRegion === 'true'
14
+ };
15
+ }
16
+
17
+ module.exports = {
18
+ get
19
+ };
package/lib/queue.js CHANGED
@@ -58,20 +58,6 @@ module.exports = class ExecutorQueue {
58
58
  this.redis[funcName](...args),
59
59
  breakerOptions
60
60
  );
61
- this.requestRetryStrategy = response => {
62
- if (Math.floor(response.statusCode / 100) !== 2) {
63
- throw new Error('Retry limit reached');
64
- }
65
-
66
- return response;
67
- };
68
- this.requestRetryStrategyPostEvent = response => {
69
- if (Math.floor(response.statusCode / 100) !== 2 && response.statusCode !== 404) {
70
- throw new Error('Retry limit reached');
71
- }
72
-
73
- return response;
74
- };
75
61
  this.fuseBox = new FuseBox();
76
62
  this.fuseBox.addFuse(this.queueBreaker);
77
63
  this.fuseBox.addFuse(this.redisBreaker);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "screwdriver-queue-service",
3
- "version": "2.0.18",
3
+ "version": "2.0.22",
4
4
  "description": "Screwdriver Queue Service API",
5
5
  "main": "app.js",
6
6
  "directories": {
@@ -11,28 +11,28 @@
11
11
  "@hapi/good": "^9.0.1",
12
12
  "@hapi/good-console": "^9.0.1",
13
13
  "@hapi/good-squeeze": "^6.0.0",
14
- "@hapi/hapi": "^20.1.0",
14
+ "@hapi/hapi": "^20.2.1",
15
15
  "@hapi/hoek": "^9.1.1",
16
- "amqp-connection-manager": "^3.2.2",
16
+ "amqp-connection-manager": "^3.8.1",
17
17
  "amqplib": "^0.8.0",
18
18
  "blipp": "^4.0.2",
19
19
  "circuit-fuses": "^4.0.5",
20
20
  "config": "^1.31.0",
21
- "cron-parser": "^2.18.0",
21
+ "cron-parser": "^4.2.1",
22
22
  "hapi-auth-jwt2": "^10.2.0",
23
23
  "ioredis": "^3.2.2",
24
- "joi": "^17.4.0",
24
+ "joi": "^17.5.0",
25
25
  "js-yaml": "^3.14.1",
26
26
  "jsonwebtoken": "^8.5.1",
27
27
  "laabr": "^6.1.3",
28
28
  "node-resque": "^5.5.3",
29
29
  "npm-auto-version": "^1.0.0",
30
30
  "redlock": "^4.2.0",
31
- "screwdriver-aws-producer-service": "^1.1.0",
32
- "screwdriver-data-schema": "^21.10.2",
31
+ "screwdriver-aws-producer-service": "^1.3.0",
32
+ "screwdriver-data-schema": "^21.16.0",
33
33
  "screwdriver-executor-docker": "^5.0.2",
34
34
  "screwdriver-executor-jenkins": "^5.0.1",
35
- "screwdriver-executor-k8s": "^14.14.4",
35
+ "screwdriver-executor-k8s": "^14.16.0",
36
36
  "screwdriver-executor-k8s-vm": "^4.3.2",
37
37
  "screwdriver-executor-router": "^2.1.2",
38
38
  "screwdriver-logger": "^1.0.2",
@@ -53,7 +53,7 @@
53
53
  "mockery": "^2.1.0",
54
54
  "nyc": "^15.1.0",
55
55
  "sinon": "^9.2.4",
56
- "snyk": "^1.712.0",
56
+ "snyk": "^1.814.0",
57
57
  "util": "^0.12.2"
58
58
  },
59
59
  "scripts": {
package/plugins/helper.js CHANGED
@@ -7,6 +7,34 @@ const { queuePrefix } = require('../config/redis');
7
7
  const RETRY_LIMIT = 3;
8
8
  const RETRY_DELAY = 5;
9
9
 
10
+ /**
11
+ * Callback function to retry when HTTP status code is not 2xx
12
+ * @param {Object} response
13
+ * @param {Function} retryWithMergedOptions
14
+ * @return {Object} response
15
+ */
16
+ function requestRetryStrategy(response) {
17
+ if (Math.floor(response.statusCode / 100) !== 2) {
18
+ throw new Error('Retry limit reached');
19
+ }
20
+
21
+ return response;
22
+ }
23
+
24
+ /**
25
+ * Callback function to retry when HTTP status code is not 2xx and 404
26
+ * @param {Object} response
27
+ * @param {Function} retryWithMergedOptions
28
+ * @return {Object} response
29
+ */
30
+ function requestRetryStrategyPostEvent(response) {
31
+ if (Math.floor(response.statusCode / 100) !== 2 && response.statusCode !== 404) {
32
+ throw new Error('Retry limit reached');
33
+ }
34
+
35
+ return response;
36
+ }
37
+
10
38
  /**
11
39
  *
12
40
  * @param {String} method
@@ -241,6 +269,8 @@ async function processHooks(apiUri, token, webhookConfig, retryStrategyFn) {
241
269
  }
242
270
 
243
271
  module.exports = {
272
+ requestRetryStrategy,
273
+ requestRetryStrategyPostEvent,
244
274
  updateBuildStatus,
245
275
  updateStepStop,
246
276
  getCurrentStep,
@@ -38,7 +38,7 @@ async function postBuildEvent(executor, eventConfig) {
38
38
  scope: ['user']
39
39
  });
40
40
 
41
- const admin = await helper.getPipelineAdmin(token, apiUri, pipelineId, executor.requestRetryStrategy);
41
+ const admin = await helper.getPipelineAdmin(token, apiUri, pipelineId, helper.requestRetryStrategy);
42
42
 
43
43
  if (admin) {
44
44
  logger.info(
@@ -64,7 +64,7 @@ async function postBuildEvent(executor, eventConfig) {
64
64
  buildEvent.buildId = buildId;
65
65
  }
66
66
 
67
- await helper.createBuildEvent(apiUri, jwt, buildEvent, executor.requestRetryStrategyPostEvent);
67
+ await helper.createBuildEvent(apiUri, jwt, buildEvent, helper.requestRetryStrategyPostEvent);
68
68
  } else {
69
69
  logger.error(
70
70
  `POST event for pipeline failed as no admin found: ${pipelineId}:${job.name}:${job.id}:${buildId}`
@@ -337,7 +337,7 @@ async function start(executor, config) {
337
337
  apiUri,
338
338
  payload
339
339
  },
340
- executor.requestRetryStrategy
340
+ helper.requestRetryStrategy
341
341
  )
342
342
  .catch(err => {
343
343
  logger.error(`frozenBuilds: failed to update build status for build ${buildId}: ${err}`);
@@ -399,7 +399,7 @@ async function start(executor, config) {
399
399
  apiUri,
400
400
  payload: { stats: build.stats, status: 'QUEUED' }
401
401
  },
402
- executor.requestRetryStrategy
402
+ helper.requestRetryStrategy
403
403
  );
404
404
  }
405
405
  }
@@ -730,7 +730,13 @@ async function queueWebhook(executor, webhookConfig) {
730
730
  'enqueue',
731
731
  executor.webhookQueue,
732
732
  'sendWebhook',
733
- JSON.stringify(webhookConfig)
733
+ JSON.stringify({
734
+ webhookConfig,
735
+ token: executor.tokenGen({
736
+ service: 'queue',
737
+ scope: ['webhook_worker']
738
+ })
739
+ })
734
740
  );
735
741
  }
736
742
 
@@ -74,12 +74,11 @@ const timeOutOfWindow = (cronExp, timeToCheck) => {
74
74
  const utcDayOfWeek = timeToCheck.getUTCDay();
75
75
  const utcMonth = timeToCheck.getUTCMonth() + 1;
76
76
 
77
- /* eslint no-underscore-dangle: ["error", { "allow": ["_fields"] }] */
78
- const minuteField = cronObj._fields.minute;
79
- const hourField = cronObj._fields.hour;
80
- const dayOfMonthField = cronObj._fields.dayOfMonth;
81
- const dayOfWeekField = cronObj._fields.dayOfWeek;
82
- const monthField = cronObj._fields.month;
77
+ const minuteField = cronObj.fields.minute;
78
+ const hourField = cronObj.fields.hour;
79
+ const dayOfMonthField = cronObj.fields.dayOfMonth;
80
+ const dayOfWeekField = cronObj.fields.dayOfWeek;
81
+ const monthField = cronObj.fields.month;
83
82
 
84
83
  const includesMinute = minuteField.includes(utcMinutes);
85
84
  const includesHour = hourField.includes(utcHours);
@@ -15,8 +15,8 @@ const blockedByConfig = config.get('plugins').blockedBy;
15
15
  const { connectionDetails, queuePrefix, runningJobsPrefix, waitingJobsPrefix } = require('../../../config/redis');
16
16
  const rabbitmqConf = require('../../../config/rabbitmq');
17
17
  const { amqpURI, exchange, connectOptions } = rabbitmqConf.getConfig();
18
- const kafkaEnabled = config.get('kafka').enabled === 'true';
19
-
18
+ const kafkaConfig = require('../../../config/kafka');
19
+ const { kafkaEnabled, useShortRegionName } = kafkaConfig.get();
20
20
  const RETRY_LIMIT = 3;
21
21
  // This is in milliseconds, reference: https://github.com/actionhero/node-resque/blob/2ffdf0/lib/plugins/Retry.js#L12
22
22
  const RETRY_DELAY = 5 * 1000;
@@ -57,6 +57,17 @@ const blockedByOptions = {
57
57
 
58
58
  collapse: blockedByConfig.collapse
59
59
  };
60
+ // AWS region map
61
+ const AWS_REGION_MAP = {
62
+ north: 'n',
63
+ west: 'w',
64
+ northeast: 'nw',
65
+ east: 'e',
66
+ south: 's',
67
+ central: 'c',
68
+ southeast: 'se'
69
+ };
70
+
60
71
  let rabbitmqConn;
61
72
 
62
73
  /**
@@ -125,15 +136,33 @@ async function pushToRabbitMq(message, queue, messageId) {
125
136
  * Push message to Kafka topic
126
137
  * @param {Object} message Job and build config metadata
127
138
  * @param {String} topic Topic name
139
+ * @param {String} messageId The message id
128
140
  */
129
- async function pushToKafka(message, topic) {
130
- const conn = await AWSProducer.connect();
141
+ async function pushToKafka(message, topic, messageId) {
142
+ const producer = await AWSProducer.connect();
131
143
 
132
- if (conn) {
133
- await AWSProducer.sendMessage(message, topic);
144
+ if (producer) {
145
+ await AWSProducer.sendMessage(producer, message, topic, messageId);
134
146
  }
135
147
  }
136
148
 
149
+ /**
150
+ *
151
+ * @param {*String} accountId The AWS accountId
152
+ * @param {*String} region The region name
153
+ * @returns String topicName
154
+ */
155
+ function getTopicName(accountId, region) {
156
+ const items = region.split('-');
157
+
158
+ if (items.length < 3 || !useShortRegionName) {
159
+ return `builds-${accountId}-${region}`;
160
+ }
161
+
162
+ const shortRegion = ''.concat(items[0], AWS_REGION_MAP[items[1]], items[2]);
163
+
164
+ return `builds-${accountId}-${shortRegion}`;
165
+ }
137
166
  /**
138
167
  * Schedule a job based on mode
139
168
  * @method schedule
@@ -153,9 +182,9 @@ async function schedule(job, buildConfig) {
153
182
 
154
183
  if (kafkaEnabled && buildConfig.provider) {
155
184
  const { accountId, region } = buildConfig.provider;
156
- const topic = `builds-${accountId}-${region}`;
185
+ const messageId = `${job}-${buildConfig.buildId}`;
157
186
 
158
- return pushToKafka(msg, topic);
187
+ return pushToKafka(msg, getTopicName(accountId, region), messageId);
159
188
  }
160
189
 
161
190
  if (rabbitmqConf.getConfig().schedulerMode) {
@@ -276,18 +305,14 @@ async function clear(cacheConfig) {
276
305
 
277
306
  /**
278
307
  * Send message to processHooks API
279
- * @param {String} webhookConfig as String
308
+ * @param {String} configs as String
280
309
  */
281
- async function sendWebhook(webhookConfig) {
282
- const parsedConfig = JSON.parse(webhookConfig);
310
+ async function sendWebhook(configs) {
311
+ const parsedConfig = JSON.parse(configs);
312
+ const { webhookConfig, token } = parsedConfig;
283
313
  const apiUri = ecosystem.api;
284
- const token = executor.tokenGen({
285
- service: 'queue',
286
- scope: ['webhook_worker']
287
- });
288
- const retryFn = executor.requestRetryStrategyPostEvent;
289
314
 
290
- await helper.processHooks(apiUri, token, parsedConfig, retryFn);
315
+ await helper.processHooks(apiUri, token, webhookConfig, helper.requestRetryStrategyPostEvent);
291
316
 
292
317
  return null;
293
318
  }