Skip to content

Commit 52c0c6c

Browse files
committedOct 15, 2016
Read from the new log service (store.sd)
- Add a local dockerfile (for testing) - Remove "extra" users from admin access - Add Swarm plugin - Remove snyk as it's done via GitHub webhooks now - Allow overriding the whitelist via environment
1 parent 9fe0749 commit 52c0c6c

10 files changed

+252
-54
lines changed
 

‎.dockerignore

-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,3 @@ node_modules/
22
test/
33
features/
44
artifacts/
5-
kubernetes/

‎Dockerfile.local

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
FROM node:6
2+
3+
# Create our application directory
4+
RUN mkdir -p /usr/src/app
5+
WORKDIR /usr/src/app
6+
7+
# Install Screwdriver API
8+
COPY package.json /usr/src/app/
9+
RUN npm install --production
10+
11+
# Copy everything else
12+
COPY . /usr/src/app
13+
14+
# Expose the web service port
15+
EXPOSE 8080
16+
17+
# Run the service
18+
CMD [ "npm", "start" ]

‎bin/server

+24-17
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,12 @@
11
#!/usr/bin/env node
2-
'use strict';
32

3+
'use strict';
44

5+
/* eslint-disable import/no-dynamic-require */
56
const winston = require('winston');
67
const config = require('config');
78
const server = require('../');
8-
9-
// Setup Datastore
10-
const datastoreConfig = config.get('datastore');
11-
const DatastorePlugin = require(`screwdriver-datastore-${datastoreConfig.plugin}`);
12-
const datastore = new DatastorePlugin(datastoreConfig[datastoreConfig.plugin] || {});
13-
14-
// Setup Executor
15-
const executorConfig = config.get('executor');
16-
const ExecutorPlugin = require(`screwdriver-executor-${executorConfig.plugin}`);
17-
const executor = new ExecutorPlugin(executorConfig[executorConfig.plugin] || {});
18-
19-
// Source Code Plugin
20-
const scmConfig = config.get('scm');
21-
const ScmPlugin = require(`screwdriver-scm-${scmConfig.plugin}`);
22-
const scm = new ScmPlugin(scmConfig[scmConfig.plugin] || {});
9+
const hoek = require('hoek');
2310

2411
// Setup Authentication
2512
const authConfig = config.get('auth');
@@ -33,6 +20,26 @@ const gitHubSecret = config.get('webhooks.github.secret');
3320
// Special urls for things like the UI
3421
const ecosystem = config.get('ecosystem');
3522

23+
ecosystem.api = httpdConfig.uri;
24+
25+
// Setup Datastore
26+
const datastoreConfig = config.get('datastore');
27+
const DatastorePlugin = require(`screwdriver-datastore-${datastoreConfig.plugin}`);
28+
const datastore = new DatastorePlugin(hoek.applyToDefaults({ ecosystem },
29+
(datastoreConfig[datastoreConfig.plugin] || {})));
30+
31+
// Setup Executor
32+
const executorConfig = config.get('executor');
33+
const ExecutorPlugin = require(`screwdriver-executor-${executorConfig.plugin}`);
34+
const executor = new ExecutorPlugin(hoek.applyToDefaults({ ecosystem },
35+
(executorConfig[executorConfig.plugin] || {})));
36+
37+
// Source Code Plugin
38+
const scmConfig = config.get('scm');
39+
const ScmPlugin = require(`screwdriver-scm-${scmConfig.plugin}`);
40+
const scm = new ScmPlugin(hoek.applyToDefaults({ ecosystem },
41+
(scmConfig[scmConfig.plugin] || {})));
42+
3643
// Setup Model Factories
3744
const Models = require('screwdriver-models');
3845
const pipelineFactory = Models.PipelineFactory.getInstance({
@@ -76,7 +83,7 @@ datastore.setup()
7683
}
7784
}))
7885
.then(instance => winston.info('Server running at %s', instance.info.uri))
79-
.catch(err => {
86+
.catch((err) => {
8087
winston.error(err);
8188
process.exit(1);
8289
});

‎config/custom-environment-variables.yaml

+16-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ auth:
2727
# A flag to set if the server is running over https.
2828
# Used as a flag for the OAuth flow
2929
https: IS_HTTPS
30+
whitelist:
31+
__name: SECRET_WHITELIST
32+
__format: json
33+
admins:
34+
__name: SECRET_ADMINS
35+
__format: json
3036

3137
httpd:
3238
# Port to listen on
@@ -60,15 +66,21 @@ datastore:
6066
secretAccessKey: DATASTORE_DYNAMODB_SECRET
6167

6268
executor:
69+
plugin: EXECUTOR_PLUGIN
6370
k8s:
6471
# The host or IP of the kubernetes cluster
6572
host: K8S_HOST
6673
# The jwt token used for authenticating kubernetes requests
6774
token: K8S_TOKEN
6875
# Launcher container tag to use
6976
launchVersion: LAUNCH_VERSION
70-
# Log Service container tag to use
71-
logVersion: LOG_VERSION
77+
s3m:
78+
# Configuration of Docker
79+
docker:
80+
__name: EXECUTOR_S3M_DOCKER
81+
__format: json
82+
# Launcher container tag to use
83+
launchVersion: LAUNCH_VERSION
7284

7385

7486
webhooks:
@@ -79,5 +91,7 @@ webhooks:
7991
ecosystem:
8092
# URL for the User Interface
8193
ui: ECOSYSTEM_UI
94+
# Externally routable URL for the Artifact Store
95+
store: ECOSYSTEM_STORE
8296
# Badge service (needs to add a status and color)
8397
badges: ECOSYSTEM_BADGES

‎config/default.yaml

+21-18
Original file line numberDiff line numberDiff line change
@@ -52,27 +52,23 @@ auth:
5252
- jpcollins
5353
admins:
5454
- FenrirUnbound
55-
- Filbird
5655
- cynthiax
5756
- d2lam
5857
- dvdizon
5958
- jer
6059
- minz1027
61-
- nicolaifsf
62-
- nkatzman
6360
- outofjungle
6461
- petey
65-
- shruthi-venkateswaran
6662
- stjohnjohnson
6763
- tkyi
6864

6965
httpd:
7066
# Port to listen on
71-
port: 8080
67+
port: 80
7268
# Host to listen on (set to localhost to only accept connections from this machine)
7369
host: 0.0.0.0
7470
# Externally routable URI (usually your load balancer or CNAME)
75-
uri: http://localhost:8080
71+
uri: http://localhost:80
7672
# SSL Support
7773
tls: false
7874
# If you want SSL, you can easily add it by replacing `tls: false` with an object that
@@ -88,25 +84,32 @@ datastore:
8884
sequelize:
8985
# Type of server to talk to
9086
dialect: sqlite
87+
# More arguments here:
88+
# http://docs.sequelizejs.com/en/latest/api/sequelize/
9189
dynamodb:
9290
# Prefix to table names
9391
prefix: ""
94-
# AWS Access Key ID
95-
accessKeyId: WHAT-A-LEGITIMATE-LOOKING-KEY-ID
96-
# AWS Secret Access Key
97-
secretAccessKey: TOTALLY-REAL-LOOKING-AWS-KEYS
92+
# AWS Access Keys (required)
93+
# accessKeyId:
94+
# secretAccessKey:
9895

9996
executor:
10097
plugin: k8s
10198
k8s:
10299
# The host or IP of the kubernetes cluster
103100
host: kubernetes
104101
# The jwt token used for authenticating kubernetes requests
105-
token: NOT-A-REAL-JWT-TOKEN
106-
# Launcher container tag to use
107-
launchVersion: latest
108-
# Log Service container tag to use
109-
logVersion: latest
102+
# Loaded from /var/run/secrets/kubernetes.io/serviceaccount/token by default
103+
# token:
104+
105+
# Container tags to use
106+
launchVersion: stable
107+
s3m:
108+
# Dockerode configuration https://github.com/apocas/dockerode#getting-started
109+
docker: {}
110+
111+
# Container tags to use
112+
launchVersion: stable
110113

111114
scm:
112115
plugin: github
@@ -117,9 +120,9 @@ webhooks:
117120
secret: SUPER-SECRET-SIGNING-THING
118121

119122
ecosystem:
120-
# URL for the User Interface
123+
# Externally routable URL for the User Interface
121124
ui: https://cd.screwdriver.cd
122-
# URL for the Artifact Store
123-
store: https://s3-us-west-2.amazonaws.com/logs.screwdriver.cd
125+
# Externally routable URL for the Artifact Store
126+
store: https://store.screwdriver.cd
124127
# Badge service (needs to add a status and color)
125128
badges: https://img.shields.io/badge/build-{{status}}-{{color}}.svg

‎package.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"description": "API server for the Screwdriver CD service",
55
"main": "index.js",
66
"scripts": {
7-
"pretest": "eslint . && snyk test",
7+
"pretest": "eslint .",
88
"test": "jenkins-mocha --recursive",
99
"start": "./bin/server",
1010
"functional": "cucumber-js --format=pretty ./features/server.feature ./features/secrets.feature ./features/git-flow.feature ./features/authorization.feature"
@@ -80,7 +80,8 @@
8080
"screwdriver-data-schema": "^13.0.0",
8181
"screwdriver-datastore-dynamodb": "^3.0.0",
8282
"screwdriver-datastore-sequelize": "^1.0.2",
83-
"screwdriver-executor-k8s": "^8.0.0",
83+
"screwdriver-executor-k8s": "^9.0.0",
84+
"screwdriver-executor-s3m": "^1.0.0",
8485
"screwdriver-models": "^15.0.0",
8586
"screwdriver-scm-github": "^1.0.1",
8687
"tinytim": "^0.1.1",
@@ -104,7 +105,6 @@
104105
"npm-auto-version": "^1.0.0",
105106
"request": "^2.73.0",
106107
"sinon": "~1.17.4",
107-
"sinon-as-promised": "^4.0.2",
108-
"snyk": "^1.17.5"
108+
"sinon-as-promised": "^4.0.2"
109109
}
110110
}

‎plugins/builds/steps/logs.js

+9-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const boom = require('boom');
44
const schema = require('screwdriver-data-schema');
55
const request = require('request');
66
const ndjson = require('ndjson');
7+
const MAX_LINES = 100;
78

89
module.exports = config => ({
910
method: 'GET',
@@ -31,15 +32,18 @@ module.exports = config => ({
3132
throw boom.notFound('Step does not exist');
3233
}
3334

34-
const isNotDone = stepModel.code === undefined;
3535
const isNotStarted = stepModel.startTime === undefined;
36-
const url = `${config.ecosystem.store}/${buildId}/${stepName}`;
3736
const output = [];
3837

3938
if (isNotStarted) {
4039
return reply(output).header('X-More-Data', 'false');
4140
}
4241

42+
const page = Math.floor(req.query.from / MAX_LINES);
43+
const isDone = stepModel.code !== undefined;
44+
const url = `${config.ecosystem.store}/v1/builds/`
45+
+ `${buildId}/${stepName}/log.${page}`;
46+
4347
return request
4448
// Load NDJson from S3 bucket
4549
.get(url)
@@ -52,9 +56,10 @@ module.exports = config => ({
5256
output.push(line);
5357
}
5458
})
55-
// Set header X-More-Data: true if step not done
59+
// Set header X-More-Data: false if lines < MAX_LINES && step done
5660
.on('end', () =>
57-
reply(output).header('X-More-Data', isNotDone.toString()));
61+
reply(output).header('X-More-Data',
62+
(!(output.length < MAX_LINES && isDone)).toString()));
5863
})
5964
.catch(err => reply(boom.wrap(err)));
6065
},

‎test/plugins/builds.test.js

+58-8
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ describe('build plugin test', () => {
5050
let secretAccessMock;
5151
let plugin;
5252
let server;
53-
const logBaseUrl = 'http://example.com/screwdriver-logs';
53+
const logBaseUrl = 'https://store.screwdriver.cd';
5454

5555
before(() => {
5656
mockery.enable({
@@ -889,9 +889,6 @@ describe('build plugin test', () => {
889889
];
890890

891891
beforeEach(() => {
892-
nock('http://example.com')
893-
.get(`/screwdriver-logs/${id}/${step}`)
894-
.replyWithFile(200, `${__dirname}/data/step.log.ndjson`);
895892
nock.disableNetConnect();
896893
});
897894

@@ -904,6 +901,9 @@ describe('build plugin test', () => {
904901
const buildMock = getMockBuilds(testBuild);
905902

906903
buildFactoryMock.get.withArgs(id).resolves(buildMock);
904+
nock('https://store.screwdriver.cd')
905+
.get(`/v1/builds/${id}/${step}/log.0`)
906+
.replyWithFile(200, `${__dirname}/data/step.log.ndjson`);
907907

908908
return server.inject(`/builds/${id}/steps/${step}/logs`).then((reply) => {
909909
assert.equal(reply.statusCode, 200);
@@ -912,10 +912,58 @@ describe('build plugin test', () => {
912912
});
913913
});
914914

915+
it('returns more-data for a step that is over but max lines', () => {
916+
const buildMock = getMockBuilds(testBuild);
917+
918+
buildFactoryMock.get.withArgs(id).resolves(buildMock);
919+
nock('https://store.screwdriver.cd')
920+
.get(`/v1/builds/${id}/${step}/log.0`)
921+
.replyWithFile(200, `${__dirname}/data/step.long.log.ndjson`);
922+
923+
return server.inject(`/builds/${id}/steps/${step}/logs`).then((reply) => {
924+
assert.equal(reply.statusCode, 200);
925+
assert.equal(reply.result.length, 100);
926+
assert.propertyVal(reply.headers, 'x-more-data', 'true');
927+
});
928+
});
929+
930+
it('returns from second page', () => {
931+
const buildMock = getMockBuilds(testBuild);
932+
933+
buildFactoryMock.get.withArgs(id).resolves(buildMock);
934+
nock('https://store.screwdriver.cd')
935+
.get(`/v1/builds/${id}/${step}/log.1`)
936+
.replyWithFile(200, `${__dirname}/data/step.long2.log.ndjson`);
937+
938+
return server.inject(`/builds/${id}/steps/${step}/logs?from=100`).then((reply) => {
939+
assert.equal(reply.statusCode, 200);
940+
assert.equal(reply.result.length, 2);
941+
assert.propertyVal(reply.headers, 'x-more-data', 'false');
942+
});
943+
});
944+
945+
it('returns from second empty page', () => {
946+
const buildMock = getMockBuilds(testBuild);
947+
948+
buildFactoryMock.get.withArgs(id).resolves(buildMock);
949+
nock('https://store.screwdriver.cd')
950+
.get(`/v1/builds/${id}/${step}/log.1`)
951+
.reply(200, '');
952+
953+
return server.inject(`/builds/${id}/steps/${step}/logs?from=100`).then((reply) => {
954+
assert.equal(reply.statusCode, 200);
955+
assert.equal(reply.result.length, 0);
956+
assert.propertyVal(reply.headers, 'x-more-data', 'false');
957+
});
958+
});
959+
915960
it('returns correct lines after a given line', () => {
916961
const buildMock = getMockBuilds(testBuild);
917962

918963
buildFactoryMock.get.withArgs(id).resolves(buildMock);
964+
nock('https://store.screwdriver.cd')
965+
.get(`/v1/builds/${id}/${step}/log.0`)
966+
.replyWithFile(200, `${__dirname}/data/step.log.ndjson`);
919967

920968
return server.inject(`/builds/${id}/steps/${step}/logs?from=2`).then((reply) => {
921969
assert.equal(reply.statusCode, 200);
@@ -928,6 +976,9 @@ describe('build plugin test', () => {
928976
const buildMock = getMockBuilds(testBuild);
929977

930978
buildFactoryMock.get.withArgs(id).resolves(buildMock);
979+
nock('https://store.screwdriver.cd')
980+
.get(`/v1/builds/${id}/${step}/log.0`)
981+
.replyWithFile(200, `${__dirname}/data/step.log.ndjson`);
931982

932983
return server.inject(`/builds/${id}/steps/publish/logs`).then((reply) => {
933984
assert.equal(reply.statusCode, 200);
@@ -939,11 +990,10 @@ describe('build plugin test', () => {
939990
it('returns empty array on invalid data', () => {
940991
const buildMock = getMockBuilds(testBuild);
941992

942-
nock('http://example.com')
943-
.get(`/screwdriver-logs/${id}/test`)
944-
.reply(200, '<invalid JSON>\n<more bad JSON>');
945-
946993
buildFactoryMock.get.withArgs(id).resolves(buildMock);
994+
nock('https://store.screwdriver.cd')
995+
.get(`/v1/builds/${id}/test/log.0`)
996+
.reply(200, '<invalid JSON>\n<more bad JSON>');
947997

948998
return server.inject(`/builds/${id}/steps/test/logs`).then((reply) => {
949999
assert.equal(reply.statusCode, 200);
+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
{"t":1476390518243,"m":"Building stuff","n":0}
2+
{"t":1476390518244,"m":"Building stuff","n":1}
3+
{"t":1476390518244,"m":"Building stuff","n":2}
4+
{"t":1476390518244,"m":"Building stuff","n":3}
5+
{"t":1476390518244,"m":"Building stuff","n":4}
6+
{"t":1476390518244,"m":"Building stuff","n":5}
7+
{"t":1476390518244,"m":"Building stuff","n":6}
8+
{"t":1476390518244,"m":"Building stuff","n":7}
9+
{"t":1476390518244,"m":"Building stuff","n":8}
10+
{"t":1476390518244,"m":"Building stuff","n":9}
11+
{"t":1476390518244,"m":"Building stuff","n":10}
12+
{"t":1476390518244,"m":"Building stuff","n":11}
13+
{"t":1476390518244,"m":"Building stuff","n":12}
14+
{"t":1476390518244,"m":"Building stuff","n":13}
15+
{"t":1476390518244,"m":"Building stuff","n":14}
16+
{"t":1476390518244,"m":"Building stuff","n":15}
17+
{"t":1476390518244,"m":"Building stuff","n":16}
18+
{"t":1476390518244,"m":"Building stuff","n":17}
19+
{"t":1476390518244,"m":"Building stuff","n":18}
20+
{"t":1476390518244,"m":"Building stuff","n":19}
21+
{"t":1476390518244,"m":"Building stuff","n":20}
22+
{"t":1476390518244,"m":"Building stuff","n":21}
23+
{"t":1476390518244,"m":"Building stuff","n":22}
24+
{"t":1476390518244,"m":"Building stuff","n":23}
25+
{"t":1476390518244,"m":"Building stuff","n":24}
26+
{"t":1476390518244,"m":"Building stuff","n":25}
27+
{"t":1476390518244,"m":"Building stuff","n":26}
28+
{"t":1476390518244,"m":"Building stuff","n":27}
29+
{"t":1476390518244,"m":"Building stuff","n":28}
30+
{"t":1476390518244,"m":"Building stuff","n":29}
31+
{"t":1476390518245,"m":"Building stuff","n":30}
32+
{"t":1476390518245,"m":"Building stuff","n":31}
33+
{"t":1476390518245,"m":"Building stuff","n":32}
34+
{"t":1476390518245,"m":"Building stuff","n":33}
35+
{"t":1476390518245,"m":"Building stuff","n":34}
36+
{"t":1476390518245,"m":"Building stuff","n":35}
37+
{"t":1476390518245,"m":"Building stuff","n":36}
38+
{"t":1476390518245,"m":"Building stuff","n":37}
39+
{"t":1476390518245,"m":"Building stuff","n":38}
40+
{"t":1476390518245,"m":"Building stuff","n":39}
41+
{"t":1476390518245,"m":"Building stuff","n":40}
42+
{"t":1476390518245,"m":"Building stuff","n":41}
43+
{"t":1476390518245,"m":"Building stuff","n":42}
44+
{"t":1476390518245,"m":"Building stuff","n":43}
45+
{"t":1476390518245,"m":"Building stuff","n":44}
46+
{"t":1476390518245,"m":"Building stuff","n":45}
47+
{"t":1476390518245,"m":"Building stuff","n":46}
48+
{"t":1476390518245,"m":"Building stuff","n":47}
49+
{"t":1476390518245,"m":"Building stuff","n":48}
50+
{"t":1476390518245,"m":"Building stuff","n":49}
51+
{"t":1476390518245,"m":"Building stuff","n":50}
52+
{"t":1476390518245,"m":"Building stuff","n":51}
53+
{"t":1476390518245,"m":"Building stuff","n":52}
54+
{"t":1476390518245,"m":"Building stuff","n":53}
55+
{"t":1476390518245,"m":"Building stuff","n":54}
56+
{"t":1476390518245,"m":"Building stuff","n":55}
57+
{"t":1476390518245,"m":"Building stuff","n":56}
58+
{"t":1476390518245,"m":"Building stuff","n":57}
59+
{"t":1476390518245,"m":"Building stuff","n":58}
60+
{"t":1476390518245,"m":"Building stuff","n":59}
61+
{"t":1476390518245,"m":"Building stuff","n":60}
62+
{"t":1476390518245,"m":"Building stuff","n":61}
63+
{"t":1476390518245,"m":"Building stuff","n":62}
64+
{"t":1476390518245,"m":"Building stuff","n":63}
65+
{"t":1476390518245,"m":"Building stuff","n":64}
66+
{"t":1476390518245,"m":"Building stuff","n":65}
67+
{"t":1476390518245,"m":"Building stuff","n":66}
68+
{"t":1476390518245,"m":"Building stuff","n":67}
69+
{"t":1476390518245,"m":"Building stuff","n":68}
70+
{"t":1476390518245,"m":"Building stuff","n":69}
71+
{"t":1476390518245,"m":"Building stuff","n":70}
72+
{"t":1476390518245,"m":"Building stuff","n":71}
73+
{"t":1476390518245,"m":"Building stuff","n":72}
74+
{"t":1476390518245,"m":"Building stuff","n":73}
75+
{"t":1476390518245,"m":"Building stuff","n":74}
76+
{"t":1476390518245,"m":"Building stuff","n":75}
77+
{"t":1476390518246,"m":"Building stuff","n":76}
78+
{"t":1476390518246,"m":"Building stuff","n":77}
79+
{"t":1476390518246,"m":"Building stuff","n":78}
80+
{"t":1476390518246,"m":"Building stuff","n":79}
81+
{"t":1476390518246,"m":"Building stuff","n":80}
82+
{"t":1476390518246,"m":"Building stuff","n":81}
83+
{"t":1476390518246,"m":"Building stuff","n":82}
84+
{"t":1476390518246,"m":"Building stuff","n":83}
85+
{"t":1476390518246,"m":"Building stuff","n":84}
86+
{"t":1476390518246,"m":"Building stuff","n":85}
87+
{"t":1476390518246,"m":"Building stuff","n":86}
88+
{"t":1476390518246,"m":"Building stuff","n":87}
89+
{"t":1476390518246,"m":"Building stuff","n":88}
90+
{"t":1476390518246,"m":"Building stuff","n":89}
91+
{"t":1476390518246,"m":"Building stuff","n":90}
92+
{"t":1476390518246,"m":"Building stuff","n":91}
93+
{"t":1476390518246,"m":"Building stuff","n":92}
94+
{"t":1476390518246,"m":"Building stuff","n":93}
95+
{"t":1476390518246,"m":"Building stuff","n":94}
96+
{"t":1476390518246,"m":"Building stuff","n":95}
97+
{"t":1476390518246,"m":"Building stuff","n":96}
98+
{"t":1476390518246,"m":"Building stuff","n":97}
99+
{"t":1476390518246,"m":"Building stuff","n":98}
100+
{"t":1476390518247,"m":"Building stuff","n":99}
+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{"t":1476390518247,"m":"Building stuff","n":100}
2+
{"t":1476390518248,"m":"Done!","n":101}

0 commit comments

Comments
 (0)
Please sign in to comment.