UNPKG

16.8 kBJavaScriptView Raw
1'use strict';
2
3const Path = require('path');
4const { expect } = require('code');
5const Hapi = require('hapi');
6const Lab = require('lab');
7const StandIn = require('stand-in');
8const CloudApiGql = require('../lib/');
9const CloudApi = require('webconsole-cloudapi-client');
10
11
12const lab = exports.lab = Lab.script();
13const { describe, it, afterEach } = lab;
14
15
16describe('machines', () => {
17 afterEach(() => {
18 StandIn.restoreAll();
19 });
20
21 const register = {
22 plugin: CloudApiGql,
23 options: {
24 keyPath: Path.join(__dirname, 'test.key'),
25 keyId: 'test',
26 apiBaseUrl: 'http://localhost'
27 }
28 };
29
30 const machine = {
31 id: 'b6979942-7d5d-4fe6-a2ec-b812e950625a',
32 name: 'test',
33 type: 'smartmachine',
34 brand: 'joyent',
35 state: 'running',
36 image: '2b683a82-a066-11e3-97ab-2faa44701c5a',
37 ips: [
38 '10.88.88.26',
39 '192.168.128.5'
40 ],
41 memory: 128,
42 disk: 12288,
43 metadata: {
44 root_authorized_keys: '...'
45 },
46 tags: {},
47 created: '2016-01-04T12:55:50.539Z',
48 updated: '2016-01-21T08:56:59.000Z',
49 networks: [
50 'a9c130da-e3ba-40e9-8b18-112aba2d3ba7',
51 '45607081-4cd2-45c8-baf7-79da760fffaa'
52 ],
53 primaryIp: '10.88.88.26',
54 firewall_enabled: false,
55 compute_node: '564d0b8e-6099-7648-351e-877faf6c56f6',
56 package: 'sdc_128'
57 };
58
59 const metadata = {
60 foo: 'bar',
61 group: 'test',
62 credentials: {
63 root: 'boo',
64 admin: 'boo'
65 }
66 };
67
68 it('can get all machines', async () => {
69 const server = new Hapi.Server();
70 StandIn.replace(CloudApi.prototype, 'fetch', (stand) => {
71 return { payload: [machine], res: { headers: { 'x-resource-count': 10 }} };
72 }, { stopAfter: 2 });
73
74 await server.register(register);
75 await server.initialize();
76 const res = await server.inject({
77 url: '/graphql',
78 method: 'post',
79 payload: { query: 'query { machines { offset total results { id name } } }' }
80 });
81 expect(res.statusCode).to.equal(200);
82 expect(res.result.data.machines.total).to.equal(10);
83 expect(res.result.data.machines.offset).to.equal(0);
84 expect(res.result.data.machines.results.length).to.equal(1);
85 expect(res.result.data.machines.results[0].id).to.equal(machine.id);
86 expect(res.result.data.machines.results[0].name).to.equal(machine.name);
87 });
88
89 it('can get all machines with paging', async () => {
90 const server = new Hapi.Server();
91 StandIn.replace(CloudApi.prototype, 'fetch', (stand) => {
92 if (stand.invocations === 1) {
93 return { payload: [machine, machine], res: { headers: { 'x-resource-count': 20 }} };
94 }
95
96 return { payload: [machine, machine], res: { headers: { 'x-resource-count': 10 }} };
97 }, { stopAfter: 2 });
98
99 await server.register(register);
100 await server.initialize();
101 const res = await server.inject({
102 url: '/graphql',
103 method: 'post',
104 payload: { query: 'query { machines(offset: 1 limit: 2) { offset limit total results { id name } } }' }
105 });
106 expect(res.statusCode).to.equal(200);
107 expect(res.result.data.machines.total).to.equal(20);
108 expect(res.result.data.machines.offset).to.equal(1);
109 expect(res.result.data.machines.limit).to.equal(2);
110 expect(res.result.data.machines.results.length).to.equal(2);
111 expect(res.result.data.machines.results[0].id).to.equal(machine.id);
112 expect(res.result.data.machines.results[0].name).to.equal(machine.name);
113 });
114
115 it('can get a machine', async () => {
116 const server = new Hapi.Server();
117 StandIn.replaceOnce(CloudApi.prototype, 'fetch', (stand) => {
118 return machine;
119 });
120
121 await server.register(register);
122 await server.initialize();
123 const res = await server.inject({
124 url: '/graphql',
125 method: 'post',
126 payload: { query: `query { machine(id: "${machine.id}") { id name } }` }
127 });
128 expect(res.statusCode).to.equal(200);
129 expect(res.result.data.machine.id).to.equal(machine.id);
130 expect(res.result.data.machine.name).to.equal(machine.name);
131 });
132
133 it('can get a machines metadata', async () => {
134 const server = new Hapi.Server();
135 StandIn.replace(CloudApi.prototype, 'fetch', (stand) => {
136 if (stand.invocations === 1) {
137 return machine;
138 }
139
140 return metadata;
141 }, { stopAfter: 2 });
142
143 await server.register(register);
144 await server.initialize();
145 const res = await server.inject({
146 url: '/graphql',
147 method: 'post',
148 payload: { query: `query { machine(id: "${machine.id}") { id name brand state metadata { name } } }` }
149 });
150 expect(res.statusCode).to.equal(200);
151 expect(res.result.data.machine.id).to.equal(machine.id);
152 expect(res.result.data.machine.name).to.equal(machine.name);
153 expect(res.result.data.machine.metadata[0].name).to.equal(Object.keys(metadata)[0]);
154 });
155
156 it('can get a machines images', async () => {
157 const image = {
158 id: '2b683a82-a066-11e3-97ab-2faa44701c5a',
159 name: 'base',
160 version: '13.4.0',
161 os: 'smartos',
162 requirements: {},
163 type: 'zone-dataset',
164 description: 'A 32-bit SmartOS image with just essential packages installed. Ideal for users who are comfortable with setting up their own environment and tools.',
165 files: [
166 {
167 compression: 'gzip',
168 sha1: '3bebb6ae2cdb26eef20cfb30fdc4a00a059a0b7b',
169 size: 110742036
170 }
171 ],
172 tags: {
173 role: 'os',
174 group: 'base-32'
175 },
176 homepage: 'https://docs.joyent.com/images/smartos/base',
177 published_at: '2014-02-28T10:50:42Z',
178 owner: '930896af-bf8c-48d4-885c-6573a94b1853',
179 public: true,
180 state: 'active'
181 };
182
183 const server = new Hapi.Server();
184 StandIn.replace(CloudApi.prototype, 'fetch', (stand) => {
185 if (stand.invocations === 1) {
186 return machine;
187 }
188
189 return image;
190 }, { stopAfter: 3 });
191
192 await server.register(register);
193 await server.initialize();
194 const res = await server.inject({
195 url: '/graphql',
196 method: 'post',
197 payload: { query: `query { machine(id: "${machine.id}") { id name image { name } } }` }
198 });
199 expect(res.statusCode).to.equal(200);
200 expect(res.result.data.machine.id).to.equal(machine.id);
201 expect(res.result.data.machine.name).to.equal(machine.name);
202 expect(res.result.data.machine.image.name).to.equal(image.name);
203 });
204
205 it('can get a machines networks', async () => {
206 const network = {
207 id: '7326787b-8039-436c-a533-5038f7280f04',
208 name: 'default',
209 public: false,
210 fabric: true,
211 gateway: '192.168.128.1',
212 internet_nat: true,
213 provision_end_ip: '192.168.131.250',
214 provision_start_ip: '192.168.128.5',
215 resolvers: [
216 '8.8.8.8',
217 '8.8.4.4'
218 ],
219 subnet: '192.168.128.0/22',
220 vlan_id: 2
221 };
222
223 const server = new Hapi.Server();
224 StandIn.replace(CloudApi.prototype, 'fetch', (stand) => {
225 if (stand.invocations === 1) {
226 return machine;
227 }
228
229 return network;
230 }, { stopAfter: 3 });
231
232 await server.register(register);
233 await server.initialize();
234 const res = await server.inject({
235 url: '/graphql',
236 method: 'post',
237 payload: { query: `query { machine(id: "${machine.id}") { id name networks { name } } }` }
238 });
239 expect(res.statusCode).to.equal(200);
240 expect(res.result.data.machine.id).to.equal(machine.id);
241 expect(res.result.data.machine.name).to.equal(machine.name);
242 expect(res.result.data.machine.networks[0].name).to.equal(network.name);
243 });
244
245 it('can get a machines snapshots', async () => {
246 const snapshot = {
247 name: 'just-booted',
248 state: 'queued',
249 created: '2011-07-05T17:19:26+00:00',
250 updated: '2011-07-05T17:19:26+00:00'
251 };
252
253 const server = new Hapi.Server();
254 StandIn.replace(CloudApi.prototype, 'fetch', (stand) => {
255 if (stand.invocations === 1) {
256 return machine;
257 }
258
259 return [snapshot];
260 }, { stopAfter: 2 });
261
262 await server.register(register);
263 await server.initialize();
264 const res = await server.inject({
265 url: '/graphql',
266 method: 'post',
267 payload: { query: `query { machine(id: "${machine.id}") { id name snapshots { name } } }` }
268 });
269 expect(res.statusCode).to.equal(200);
270 expect(res.result.data.machine.id).to.equal(machine.id);
271 expect(res.result.data.machine.name).to.equal(machine.name);
272 expect(res.result.data.machine.snapshots[0].name).to.equal(snapshot.name);
273 });
274
275 it('can get a machines firewall rules', async () => {
276 const firewallRule = {
277 id: '38de17c4-39e8-48c7-a168-0f58083de860',
278 rule: 'FROM vm 3d51f2d5-46f2-4da5-bb04-3238f2f64768 TO subnet 10.99.99.0/24 BLOCK tcp PORT 25',
279 enabled: true,
280 description: 'test'
281 };
282
283 const server = new Hapi.Server();
284 StandIn.replace(CloudApi.prototype, 'fetch', (stand) => {
285 if (stand.invocations === 1) {
286 return machine;
287 }
288
289 return [firewallRule];
290 }, { stopAfter: 2 });
291
292 await server.register(register);
293 await server.initialize();
294 const res = await server.inject({
295 url: '/graphql',
296 method: 'post',
297 payload: { query: `query { machine(id: "${machine.id}") { id name firewall_rules { rule_str } } }` }
298 });
299 expect(res.statusCode).to.equal(200);
300 expect(res.result.data.machine.id).to.equal(machine.id);
301 expect(res.result.data.machine.name).to.equal(machine.name);
302 expect(res.result.data.machine.firewall_rules[0].rule_str).to.equal(firewallRule.rule);
303 });
304
305 it('can get a machines actions', async () => {
306 const audit = {
307 success: 'yes',
308 time: '2013-02-22T15:19:32.522Z',
309 action: 'provision',
310 caller: {
311 type: 'signature',
312 ip: '127.0.0.1',
313 keyId: '/:login/keys/:fingerprint'
314 }
315 };
316
317 const server = new Hapi.Server();
318 StandIn.replace(CloudApi.prototype, 'fetch', (stand) => {
319 if (stand.invocations === 1) {
320 return machine;
321 }
322
323 return [audit];
324 }, { stopAfter: 2 });
325
326 await server.register(register);
327 await server.initialize();
328 const res = await server.inject({
329 url: '/graphql',
330 method: 'post',
331 payload: { query: `query { machine(id: "${machine.id}") { id name actions { name } } }` }
332 });
333 expect(res.statusCode).to.equal(200);
334 expect(res.result.data.machine.id).to.equal(machine.id);
335 expect(res.result.data.machine.name).to.equal(machine.name);
336 expect(res.result.data.machine.actions[0].name).to.equal(audit.action);
337 });
338
339
340 it('can stop a machine', async () => {
341 const server = new Hapi.Server();
342 StandIn.replace(CloudApi.prototype, 'fetch', (stand, path) => {
343 const updatedMachine = Object.assign({}, machine, { state: 'stopping' });
344 return updatedMachine;
345 }, { stopAfter: 2 });
346
347 await server.register(register);
348 await server.initialize();
349 const res = await server.inject({
350 url: '/graphql',
351 method: 'post',
352 payload: { query: `mutation { stopMachine(id: "${machine.id}") { id state } }` }
353 });
354
355 expect(res.statusCode).to.equal(200);
356 expect(res.result.data.stopMachine.id).to.equal(machine.id);
357 expect(res.result.data.stopMachine.state).to.equal('STOPPING');
358 });
359
360 it('can start a machine', async () => {
361 const server = new Hapi.Server();
362 StandIn.replace(CloudApi.prototype, 'fetch', (stand, path) => {
363 const updatedMachine = Object.assign({}, machine, { state: 'running' });
364 return updatedMachine;
365 }, { stopAfter: 2 });
366
367 await server.register(register);
368 await server.initialize();
369 const res = await server.inject({
370 url: '/graphql',
371 method: 'post',
372 payload: { query: `mutation { startMachine(id: "${machine.id}") { id state } }` }
373 });
374
375 expect(res.statusCode).to.equal(200);
376 expect(res.result.data.startMachine.id).to.equal(machine.id);
377 expect(res.result.data.startMachine.state).to.equal('RUNNING');
378 });
379
380 it('can reboot a machine', async () => {
381 const server = new Hapi.Server();
382 StandIn.replace(CloudApi.prototype, 'fetch', (stand, path) => {
383 const updatedMachine = Object.assign({}, machine, { state: 'stopping' });
384 return updatedMachine;
385 }, { stopAfter: 2 });
386
387 await server.register(register);
388 await server.initialize();
389 const res = await server.inject({
390 url: '/graphql',
391 method: 'post',
392 payload: { query: `mutation { rebootMachine(id: "${machine.id}") { id state } }` }
393 });
394
395 expect(res.statusCode).to.equal(200);
396 expect(res.result.data.rebootMachine.id).to.equal(machine.id);
397 expect(res.result.data.rebootMachine.state).to.equal('STOPPING');
398 });
399
400 it('can resize a machine', async () => {
401 const packageObj = {
402 id: '7b17343c-94af-6266-e0e8-893a3b9993d0',
403 name: 'sdc_128',
404 memory: 128,
405 disk: 12288,
406 swap: 256,
407 vcpus: 1,
408 lwps: 1000,
409 default: false,
410 version: '1.0.0'
411 };
412
413 const server = new Hapi.Server();
414 StandIn.replace(CloudApi.prototype, 'fetch', (stand) => {
415 if (stand.invocations === 1) {
416 return '';
417 } else if (stand.invocations === 2) {
418 return machine;
419 }
420
421 return packageObj;
422 }, { stopAfter: 3 });
423
424 await server.register(register);
425 await server.initialize();
426 const res = await server.inject({
427 url: '/graphql',
428 method: 'post',
429 payload: { query: `mutation { resizeMachine(id: "${machine.id}", package: "${packageObj.id}") { id package {id name} } }` }
430 });
431
432 expect(res.statusCode).to.equal(200);
433 expect(res.result.data.resizeMachine.id).to.equal(machine.id);
434 expect(res.result.data.resizeMachine.package.id).to.equal(packageObj.id);
435 expect(res.result.data.resizeMachine.package.name).to.equal(packageObj.name);
436 });
437
438 describe('firewalls', () => {
439 it('can enable a firewall for a machine', async () => {
440 const server = new Hapi.Server();
441 StandIn.replace(CloudApi.prototype, 'fetch', () => {
442 const result = Object.assign({}, machine, { firewall_enabled: true });
443 return result;
444 }, { stopAfter: 2 });
445
446 await server.register(register);
447 await server.initialize();
448 const res = await server.inject({
449 url: '/graphql',
450 method: 'post',
451 payload: { query: `mutation { enableMachineFirewall(id: "${machine.id}") { id firewall_enabled } }` }
452 });
453 expect(res.statusCode).to.equal(200);
454 expect(res.result.data.enableMachineFirewall.id).to.equal(machine.id);
455 expect(res.result.data.enableMachineFirewall.firewall_enabled).to.equal(true);
456 });
457
458 it('can disable a firewall for a machine', async () => {
459 const server = new Hapi.Server();
460 StandIn.replace(CloudApi.prototype, 'fetch', () => {
461 const result = Object.assign({}, machine, { firewall_enabled: false });
462 return result;
463 }, { stopAfter: 2 });
464
465 await server.register(register);
466 await server.initialize();
467 const res = await server.inject({
468 url: '/graphql',
469 method: 'post',
470 payload: { query: `mutation { disableMachineFirewall(id: "${machine.id}") { id firewall_enabled } }` }
471 });
472 expect(res.statusCode).to.equal(200);
473 expect(res.result.data.disableMachineFirewall.id).to.equal(machine.id);
474 expect(res.result.data.disableMachineFirewall.firewall_enabled).to.equal(false);
475 });
476 });
477
478 describe('metadata', () => {
479 it('can get all machine metadata', async () => {
480 const server = new Hapi.Server();
481 StandIn.replaceOnce(CloudApi.prototype, 'fetch', (stand) => {
482 return metadata;
483 });
484
485 await server.register(register);
486 await server.initialize();
487 const res = await server.inject({
488 url: '/graphql',
489 method: 'post',
490 payload: { query: `query { metadata(machine: "${machine.id}") { name value } }` }
491 });
492 expect(res.statusCode).to.equal(200);
493 expect(res.result.data.metadata.length).to.equal(3);
494 expect(res.result.data.metadata[0].name).to.equal('foo');
495 });
496
497 it('can get an individual metadata value', async () => {
498 const server = new Hapi.Server();
499 StandIn.replaceOnce(CloudApi.prototype, 'fetch', (stand) => {
500 return 'bar';
501 });
502
503 await server.register(register);
504 await server.initialize();
505 const res = await server.inject({
506 url: '/graphql',
507 method: 'post',
508 payload: { query: `query { metadataValue(machine: "${machine.id}", name: "foo") { name value } }` }
509 });
510 expect(res.statusCode).to.equal(200);
511 expect(res.result.data.metadataValue.name).to.equal('foo');
512 expect(res.result.data.metadataValue.value).to.equal('bar');
513 });
514 });
515});