1 | const _ = require('lodash');
|
2 | const request = require('request');
|
3 | const net = require('net');
|
4 |
|
5 | const { ApiImplementation } = require('containership.plugin.v2');
|
6 |
|
7 | class ContainershipApiBridge extends ApiImplementation {
|
8 | constructor(ip, port, core) {
|
9 | super();
|
10 | this.apiIP = ip || "localhost";
|
11 | this.apiPort = port || "8081";
|
12 | this.myriadPort = 2666;
|
13 | this.apiAddr = `http://${ip}:${port}`;
|
14 | this.core = core;
|
15 | }
|
16 |
|
17 | makeHandler(path, cb) {
|
18 | cb = cb || _.identity;
|
19 |
|
20 | return (err, resp) => {
|
21 | if(err) {
|
22 | cb(err);
|
23 | } else {
|
24 | cb(null, _.get(resp, path));
|
25 | }
|
26 | };
|
27 |
|
28 | }
|
29 |
|
30 | apiVERB(verb, endpoint, data, path, cb) {
|
31 | request({
|
32 | baseUrl: this.apiAddr,
|
33 | url: endpoint,
|
34 | body: data,
|
35 | method: verb,
|
36 | json: true
|
37 | }, this.makeHandler(path, cb));
|
38 | }
|
39 |
|
40 | apiGET(endpoint, path, cb) {
|
41 | this.apiVERB('GET', endpoint, undefined, path, cb);
|
42 | }
|
43 |
|
44 | apiPOST(endpoint, data, path, cb) {
|
45 | this.apiVERB('POST', endpoint, data, path, cb);
|
46 | }
|
47 |
|
48 | apiPUT(endpoint, data, path, cb) {
|
49 | this.apiVERB('PUT', endpoint, data, path, cb);
|
50 | }
|
51 |
|
52 | apiDELETE(endpoint, path, cb) {
|
53 | this.apiVERB('DELETE', endpoint, null, path, cb);
|
54 | }
|
55 |
|
56 | getClusterId(cb) {
|
57 | this.apiGET('/v1/cluster', ['body', 'id'], cb);
|
58 | }
|
59 |
|
60 | getApplications(cb) {
|
61 | this.apiGET('/v1/applications', 'body', cb);
|
62 | }
|
63 |
|
64 | createContainers(appId, containerConfig, cb) {
|
65 | this.apiPOST(`/v1/applications/${appId}/containers?count=${containerConfig.count}`, {}, 'body', cb);
|
66 | }
|
67 |
|
68 | createApplication(appDesc, cb) {
|
69 | this.apiPOST(`/v1/aplications/${appId}`, appDesc, 'body', cb);
|
70 | }
|
71 |
|
72 | updateApplication(appId, appDesc, cb) {
|
73 | this.apiPUT(`/v1/aplications/${appId}`, appDesc, 'body', cb);
|
74 | }
|
75 |
|
76 | deleteApplication(appId, cb) {
|
77 | this.apiDELETE(`/v1/applications/${appId}`, 'body', cb);
|
78 | }
|
79 |
|
80 | getHosts(cb) {
|
81 | this.apiGET('/v1/hosts', 'body', cb);
|
82 | }
|
83 |
|
84 | discoverPeers(cidr) {
|
85 | if(!this.core) {
|
86 | throw new Error("A core reference is required to use this method.");
|
87 | }
|
88 |
|
89 | this.core.cluster.legiond.options.network.cidr = cidr;
|
90 | this.core.cluster.legiond.actions.discover_peers(cidr);
|
91 | }
|
92 |
|
93 | makeSocketRequest(message, cb) {
|
94 | const socket = new net.Socket();
|
95 |
|
96 | socket.connect(this.myriadPort, this.apiIP, () => {
|
97 | console.log("Connected!");
|
98 | socket.write(message);
|
99 | socket.write(ContainershipApiBridge.MYRIAD_DELIMETER);
|
100 | });
|
101 |
|
102 | socket.on('error', (err) => {
|
103 | socket.destroy();
|
104 | return cb(err);
|
105 | });
|
106 |
|
107 | let buffer = '';
|
108 | socket.on('data', (data) => {
|
109 | buffer += data.toString();
|
110 |
|
111 |
|
112 | if(!_.includes(buffer, ContainershipApiBridge.MYRIAD_DELIMETER)) {
|
113 | return;
|
114 | }
|
115 |
|
116 | socket.end();
|
117 |
|
118 | const messageJSON = _.first(_.split(buffer, ContainershipApiBridge.MYRIAD_DELIMIETER));
|
119 |
|
120 | let message;
|
121 |
|
122 | try {
|
123 | message = JSON.parse(messageJSON);
|
124 | } catch(err) {
|
125 | return cb(null, messageJSON);
|
126 | }
|
127 |
|
128 | if(!_.isEmpty(message.error)) {
|
129 | cb(new Error(message.error));
|
130 | } else {
|
131 | cb(null, message);
|
132 | }
|
133 |
|
134 | });
|
135 | }
|
136 |
|
137 | setDistributedKey(k, v, cb) {
|
138 | this.makeSocketRequest(`SET ${k} ${v}`, cb);
|
139 | }
|
140 |
|
141 | getDistributedKey(k, cb) {
|
142 | this.makeSocketRequest(`GET ${k}`, cb);
|
143 | }
|
144 |
|
145 | }
|
146 |
|
147 | ContainershipApiBridge.MYRIAD_DELIMETER = '\r\n';
|
148 |
|
149 | module.exports = ContainershipApiBridge;
|