Skip to content

Commit 86fb8da

Browse files
author
Amir Moualem
authored
Merge pull request #292 from snyk/test/system
Test/system
2 parents 583459b + 76805c4 commit 86fb8da

File tree

7 files changed

+194
-2
lines changed

7 files changed

+194
-2
lines changed

.circleci/config.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,29 @@ jobs:
146146
echo "Current branch is $CIRCLE_BRANCH so skipping notifying Slack"
147147
fi
148148
when: on_fail
149+
150+
system_tests:
151+
<<: *default_machine_config
152+
steps:
153+
- checkout
154+
- run:
155+
name: SYSTEM TESTS
156+
command: |
157+
export NVM_DIR="/opt/circleci/.nvm" &&
158+
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" &&
159+
nvm install v10 &&
160+
npm install &&
161+
npm run build &&
162+
npm run test:system
163+
- run:
164+
name: Notify Slack on failure
165+
command: |
166+
if [[ "$CIRCLE_BRANCH" == "staging" ]]; then
167+
./scripts/slack-notify-failure.sh "staging-system-tests-${CIRCLE_SHA1}"
168+
else
169+
echo "Current branch is $CIRCLE_BRANCH so skipping notifying Slack"
170+
fi
171+
when: on_fail
149172

150173
integration_tests:
151174
<<: *default_machine_config
@@ -292,6 +315,8 @@ workflows:
292315
<<: *main_branches_filter
293316
- unit_tests:
294317
<<: *main_branches_filter
318+
- system_tests:
319+
<<: *main_branches_filter
295320
- integration_tests:
296321
requires:
297322
- build_image
@@ -315,6 +340,8 @@ workflows:
315340
<<: *staging_branch_only_filter
316341
- unit_tests:
317342
<<: *staging_branch_only_filter
343+
- system_tests:
344+
<<: *staging_branch_only_filter
318345
- integration_tests:
319346
requires:
320347
- build_image
@@ -339,6 +366,7 @@ workflows:
339366
requires:
340367
- build_image
341368
- unit_tests
369+
- system_tests
342370
- integration_tests
343371
- package_manager_test_apk
344372
- package_manager_test_apt

package-lock.json

Lines changed: 30 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"pretest": "./scripts/build-image.sh",
77
"test": "npm run lint && npm run build && npm run test:unit && npm run test:integration",
88
"test:unit": "NODE_ENV=test tap test/unit",
9+
"test:system": "tap test/system --timeout=600",
910
"test:integration": "TEST_PLATFORM=kind CREATE_CLUSTER=true tap test/integration/kubernetes.test.ts --timeout=1200",
1011
"test:integration:kind": "TEST_PLATFORM=kind CREATE_CLUSTER=true tap test/integration/kubernetes.test.ts --timeout=1200",
1112
"test:integration:eks": "TEST_PLATFORM=eks CREATE_CLUSTER=false tap test/integration/kubernetes.test.ts --timeout=1200",
@@ -51,6 +52,7 @@
5152
"@typescript-eslint/parser": "^2.6.1",
5253
"eslint": "^6.6.0",
5354
"eslint-config-prettier": "^6.5.0",
55+
"nock": "^11.7.2",
5456
"sinon": "^8.0.1",
5557
"tap": "^14.10.5",
5658
"ts-node": "^8.1.0",

test/fixtures/java-deployment.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: java
5+
namespace: services
6+
labels:
7+
app.kubernetes.io/name: java
8+
spec:
9+
replicas: 2
10+
selector:
11+
matchLabels:
12+
app.kubernetes.io/name: java
13+
template:
14+
metadata:
15+
labels:
16+
app.kubernetes.io/name: java
17+
spec:
18+
containers:
19+
- image: java:latest
20+
imagePullPolicy: Always
21+
name: java
22+
securityContext: {}

test/helpers/kubectl.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { accessSync, chmodSync, constants, writeFileSync } from 'fs';
33
import { platform } from 'os';
44
import { resolve } from 'path';
55
import * as needle from 'needle';
6+
import * as sleep from 'sleep-promise';
67

78
export async function downloadKubectl(): Promise<void> {
89
try {
@@ -83,6 +84,18 @@ export async function getDeploymentJson(deploymentName: string, namespace: strin
8384
return JSON.parse(getDeploymentResult.stdout);
8485
}
8586

87+
export async function waitForServiceAccount(name: string, namespace: string): Promise<void> {
88+
// TODO: add some timeout
89+
while (true) {
90+
try {
91+
await exec(`./kubectl get serviceaccount ${name} -n ${namespace}`);
92+
break;
93+
} catch (err) {
94+
await sleep(500);
95+
}
96+
}
97+
}
98+
8699
async function getLatestStableK8sRelease(): Promise<string> {
87100
const k8sRelease = await needle('get',
88101
'https://storage.googleapis.com/kubernetes-release/release/stable.txt',

test/setup/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,5 @@ export async function deployMonitor(): Promise<string> {
168168
// ... but make sure the test suite doesn't proceed if the setup failed
169169
process.exit(-1);
170170
}
171-
172-
throw err;
173171
}
174172
}

test/system/kind.test.ts

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import * as tap from 'tap';
2+
import * as nock from 'nock';
3+
import * as sleep from 'sleep-promise';
4+
import { exec } from 'child-process-promise';
5+
6+
import * as kubectl from '../helpers/kubectl';
7+
import * as kind from '../setup/platforms/kind';
8+
9+
// let integrationId: string;
10+
11+
async function tearDown() {
12+
console.log('Begin removing the snyk-monitor...');
13+
await kind.deleteCluster();
14+
console.log('Removed the snyk-monitor!');
15+
}
16+
17+
tap.tearDown(tearDown);
18+
19+
tap.test('Kubernetes-Monitor with KinD', async (t) => {
20+
21+
// Start fresh
22+
try {
23+
await tearDown();
24+
} catch (error) {
25+
console.log(`could not start with a clean environment: ${error.message}`);
26+
}
27+
28+
// install Skopeo
29+
// TODO: this thing should probably be in a setup test environment script
30+
// not in this file
31+
try {
32+
await exec('which skopeo');
33+
console.log('Skopeo already installed :tada:');
34+
} catch (err) {
35+
// linux-oriented, not mac
36+
// for mac, install skopeo with brew
37+
console.log('installing Skopeo');
38+
await exec('git clone https://github.com/containers/skopeo');
39+
await exec('(cd skopeo && make binary-static DISABLE_CGO=1)');
40+
await exec('sudo mkdir -p /etc/containers');
41+
await exec('sudo chown circleci:circleci /etc/containers');
42+
await exec('cp ./skopeo/default-policy.json /etc/containers/policy.json');
43+
44+
process.env['PATH'] = process.env['PATH'] + ':./skopeo';
45+
}
46+
47+
// kubectl
48+
await kubectl.downloadKubectl();
49+
50+
// KinD
51+
await kind.createCluster();
52+
await kind.exportKubeConfig();
53+
Promise.all([
54+
kubectl.createNamespace('snyk-monitor'),
55+
kubectl.createNamespace('services'),
56+
]);
57+
// wait for default service account
58+
await kubectl.waitForServiceAccount('default', 'default');
59+
60+
// Services
61+
await Promise.all([
62+
kubectl.applyK8sYaml('./test/fixtures/java-deployment.yaml'),
63+
]);
64+
65+
// TODO: wait for the services to start?
66+
67+
// Setup nocks
68+
nock('https://kubernetes-upstream.snyk.io')
69+
.post('/api/v1/workload')
70+
.times(1)
71+
.reply(200, (uri, requestBody) => {
72+
// TODO assert POST payload
73+
});
74+
75+
nock('https://kubernetes-upstream.snyk.io')
76+
.post('/api/v1/dependency-graph')
77+
.times(1)
78+
.reply(200, (uri, requestBody) => {
79+
// TODO assert POST payload
80+
});
81+
82+
// Start the monitor
83+
require('../../src');
84+
85+
// TODO: replace with being event driven?
86+
// will still need SOME timeout
87+
while (true) {
88+
if (nock.isDone()) {
89+
break;
90+
} else {
91+
await sleep(5 * 1000);
92+
}
93+
}
94+
95+
// additional asserts?
96+
t.ok(nock.isDone(), 'all outgoing calls were made');
97+
98+
// TODO cleanup the images we saved to /var/tmp?
99+
});

0 commit comments

Comments
 (0)