1 | /*
|
2 | * Copyright (c) 2022 Snowplow Analytics Ltd, 2010 Anthon Pang
|
3 | * All rights reserved.
|
4 | *
|
5 | * Redistribution and use in source and binary forms, with or without
|
6 | * modification, are permitted provided that the following conditions are met:
|
7 | *
|
8 | * 1. Redistributions of source code must retain the above copyright notice, this
|
9 | * list of conditions and the following disclaimer.
|
10 | *
|
11 | * 2. Redistributions in binary form must reproduce the above copyright notice,
|
12 | * this list of conditions and the following disclaimer in the documentation
|
13 | * and/or other materials provided with the distribution.
|
14 | *
|
15 | * 3. Neither the name of the copyright holder nor the names of its
|
16 | * contributors may be used to endorse or promote products derived from
|
17 | * this software without specific prior written permission.
|
18 | *
|
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
27 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29 | */
|
30 |
|
31 | import http from 'http';
|
32 | import Docker from 'dockerode';
|
33 | import { Writable } from 'stream';
|
34 |
|
35 | export interface DockerWrapper {
|
36 | url: string;
|
37 | container: Docker.Container;
|
38 | }
|
39 |
|
40 | const docker = new Docker();
|
41 |
|
42 | export const start = () => {
|
43 | return docker
|
44 | .createContainer({
|
45 | Image: 'snowplow/snowplow-micro:1.2.1',
|
46 | AttachStdin: false,
|
47 | AttachStdout: true,
|
48 | AttachStderr: true,
|
49 | Tty: true,
|
50 | Cmd: ['--collector-config', '/config/micro.conf', '--iglu', '/config/iglu.json'],
|
51 | OpenStdin: false,
|
52 | StdinOnce: false,
|
53 | HostConfig: {
|
54 | Binds: [`${process.cwd()}/test/micro-config:/config`],
|
55 | PortBindings: {
|
56 | '9090/tcp': [
|
57 | {
|
58 | HostIp: '',
|
59 | HostPort: '',
|
60 | },
|
61 | ],
|
62 | },
|
63 | },
|
64 | ExposedPorts: {
|
65 | '9090/tcp': {},
|
66 | },
|
67 | })
|
68 | .then((c) => {
|
69 | return c.start().then(() => {
|
70 | const outs = new Writable({
|
71 | write(chunk, _, callback) {
|
72 | let found = chunk.toString().includes('REST interface bound');
|
73 | if (found) this.end();
|
74 | callback();
|
75 | },
|
76 | });
|
77 |
|
78 | c.attach({ stream: true, stdout: true, stderr: true }, (_, stream) => {
|
79 | stream?.pipe(process.stdout);
|
80 | stream?.pipe(outs);
|
81 | });
|
82 |
|
83 | return new Promise<DockerWrapper>((resolve) => {
|
84 | outs.on('finish', () =>
|
85 | c.inspect().then((info) => {
|
86 | resolve({
|
87 | container: c,
|
88 | url: `snowplow-js-tracker.local:${info.NetworkSettings.Ports['9090/tcp'][0].HostPort}`,
|
89 | });
|
90 | })
|
91 | );
|
92 | });
|
93 | });
|
94 | });
|
95 | };
|
96 |
|
97 | export const stop = (container: Docker.Container) => container.stop().then(() => container.remove());
|
98 |
|
99 | const createMicroCall = (url: string) => () =>
|
100 | new Promise((resolve, reject) => {
|
101 | const req = http.request(url, (res) => {
|
102 | let body = '';
|
103 | res.on('data', (chunk) => {
|
104 | body += chunk;
|
105 | });
|
106 | res.on('end', () => {
|
107 | resolve(body);
|
108 | });
|
109 | });
|
110 | req.on('error', reject);
|
111 | req.end();
|
112 | });
|
113 |
|
114 | export const fetchResults = async (containerUrl: string) =>
|
115 | JSON.parse((await createMicroCall(`http://${containerUrl}/micro/good`)()) as string);
|
116 |
|
117 | export const clearCache = async (containerUrl: string) => {
|
118 | await createMicroCall(`http://${containerUrl}/micro/reset`)();
|
119 | return true;
|
120 | };
|