screwdriver-api 8.0.0 → 8.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "screwdriver-api",
3
- "version": "8.0.0",
3
+ "version": "8.0.2",
4
4
  "description": "API server for the Screwdriver.cd service",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -111,7 +111,7 @@
111
111
  "screwdriver-config-parser": "^12.0.0",
112
112
  "screwdriver-coverage-bookend": "^3.0.0",
113
113
  "screwdriver-coverage-sonar": "^5.0.0",
114
- "screwdriver-data-schema": "^25.0.0",
114
+ "screwdriver-data-schema": "^25.1.0",
115
115
  "screwdriver-datastore-sequelize": "^10.0.0",
116
116
  "screwdriver-executor-base": "^11.0.0",
117
117
  "screwdriver-executor-docker": "^8.0.1",
@@ -0,0 +1,70 @@
1
+ 'use strict';
2
+
3
+ const boom = require('@hapi/boom');
4
+ const joi = require('joi');
5
+ const schema = require('screwdriver-data-schema');
6
+ const logger = require('screwdriver-logger');
7
+ const idSchema = schema.models.job.base.extract('id');
8
+
9
+ module.exports = () => ({
10
+ method: 'DELETE',
11
+ path: '/jobs/{id}/buildCluster',
12
+ options: {
13
+ description: 'Delete the buildCluster override of a job',
14
+ notes: 'Returns null if successful',
15
+ tags: ['api', 'jobs'],
16
+ auth: {
17
+ strategies: ['token'],
18
+ scope: ['admin', '!guest']
19
+ },
20
+
21
+ handler: async (request, h) => {
22
+ const { jobFactory, pipelineFactory } = request.server.app;
23
+ const { username } = request.auth.credentials;
24
+ const { id } = request.params;
25
+ const adminAnnotation = 'screwdriver.cd/sdAdminBuildClusterOverride';
26
+ const job = await jobFactory.get(id);
27
+
28
+ if (!job) {
29
+ throw boom.notFound(`Job ${id} does not exist`);
30
+ }
31
+
32
+ const pipeline = await pipelineFactory.get(job.pipelineId);
33
+
34
+ if (!pipeline) {
35
+ throw boom.notFound('Pipeline does not exist');
36
+ }
37
+
38
+ // remove buildClusterOverride annotation from job
39
+ const [permutation] = job.permutations;
40
+ const buildClusterOverride =
41
+ permutation && permutation.annotations && permutation.annotations[adminAnnotation];
42
+
43
+ if (!buildClusterOverride) {
44
+ logger.info(`[Audit] ${adminAnnotation} does not exists for jobId:${id}.`);
45
+
46
+ return h.response().code(204);
47
+ }
48
+
49
+ logger.info(`[Audit] ${adminAnnotation} for jobId:${id} set to ${buildClusterOverride}, deleting.`);
50
+
51
+ delete permutation.annotations[adminAnnotation];
52
+
53
+ try {
54
+ const result = await job.updateBuildCluster();
55
+
56
+ logger.info(`[Audit] user ${username} deleted ${adminAnnotation} for jobId:${id}.`);
57
+
58
+ return h.response(result.toJson()).code(200);
59
+ } catch (err) {
60
+ logger.error(`Failed to remove ${adminAnnotation} for job ${id}: ${err.message}`);
61
+ throw boom.internal(`Failed to remove ${adminAnnotation} for job ${id}`);
62
+ }
63
+ },
64
+ validate: {
65
+ params: joi.object({
66
+ id: idSchema
67
+ })
68
+ }
69
+ }
70
+ });
@@ -0,0 +1,85 @@
1
+ 'use strict';
2
+
3
+ const boom = require('@hapi/boom');
4
+ const joi = require('joi');
5
+ const schema = require('screwdriver-data-schema');
6
+ const logger = require('screwdriver-logger');
7
+ const idSchema = schema.models.job.base.extract('id');
8
+
9
+ module.exports = () => ({
10
+ method: 'PUT',
11
+ path: '/jobs/{id}/buildCluster',
12
+ options: {
13
+ description: 'Update the buildCluster of a job',
14
+ notes: 'Update the buildCluster of a specific job',
15
+ tags: ['api', 'jobs'],
16
+ auth: {
17
+ strategies: ['token'],
18
+ scope: ['admin', '!guest']
19
+ },
20
+ handler: async (request, h) => {
21
+ const adminAnnotation = 'screwdriver.cd/sdAdminBuildClusterOverride';
22
+ const { payload } = request;
23
+ const { id } = request.params;
24
+
25
+ if (!payload[adminAnnotation]) {
26
+ throw boom.badRequest(`Payload must contain ${adminAnnotation}`);
27
+ }
28
+
29
+ const { jobFactory, buildClusterFactory, pipelineFactory } = request.server.app;
30
+ const { scmContext, username } = request.auth.credentials;
31
+
32
+ const job = await jobFactory.get(id);
33
+
34
+ if (!job) {
35
+ throw boom.notFound(`Job ${id} does not exist`);
36
+ }
37
+
38
+ const pipeline = await pipelineFactory.get(job.pipelineId);
39
+
40
+ if (!pipeline) {
41
+ throw boom.notFound('Pipeline does not exist');
42
+ }
43
+
44
+ // ensure that the buildCluster is a valid cluster
45
+ const buildClusterName = payload[adminAnnotation];
46
+ const buildCluster = await buildClusterFactory.get({ name: buildClusterName, scmContext });
47
+
48
+ if (!buildCluster || !buildCluster.isActive) {
49
+ throw boom.badRequest(`Build cluster ${buildClusterName} does not exist or is not active`);
50
+ }
51
+
52
+ // update job with buildClusterOverride annotation
53
+ const [permutation] = job.permutations;
54
+
55
+ permutation.annotations = permutation.annotations || {};
56
+
57
+ const annotations = permutation.annotations;
58
+
59
+ if (annotations[adminAnnotation]) {
60
+ logger.info(
61
+ `[Audit] ${adminAnnotation} for jobId:${id} already set to ${annotations[adminAnnotation]}, updating.`
62
+ );
63
+ }
64
+ permutation.annotations[adminAnnotation] = buildClusterName;
65
+
66
+ try {
67
+ const result = await job.updateBuildCluster();
68
+
69
+ logger.info(
70
+ `[Audit] user ${username} updates ${adminAnnotation} for jobId:${id} to ${buildClusterName}.`
71
+ );
72
+
73
+ return h.response(result.toJson()).code(200);
74
+ } catch (err) {
75
+ logger.error(`Failed to update ${adminAnnotation} for job ${id}: ${err.message}`);
76
+ throw boom.internal(`Failed to update ${adminAnnotation} for job ${id}`);
77
+ }
78
+ },
79
+ validate: {
80
+ params: joi.object({
81
+ id: idSchema
82
+ })
83
+ }
84
+ }
85
+ });
@@ -7,6 +7,8 @@ const lastSuccessfulMeta = require('./lastSuccessfulMeta');
7
7
  const latestBuild = require('./latestBuild');
8
8
  const metrics = require('./metrics');
9
9
  const notify = require('./notify');
10
+ const addBuildCluster = require('./buildCluster/update');
11
+ const removeBuildCluster = require('./buildCluster/remove');
10
12
 
11
13
  /**
12
14
  * Job API Plugin
@@ -23,7 +25,9 @@ const jobsPlugin = {
23
25
  lastSuccessfulMeta(),
24
26
  metrics(),
25
27
  latestBuild(),
26
- notify()
28
+ notify(),
29
+ addBuildCluster(),
30
+ removeBuildCluster()
27
31
  ]);
28
32
  }
29
33
  };