UNPKG

39.3 kBJavaScriptView Raw
1var EventEmitter = require('events').EventEmitter,
2 Modem = require('docker-modem'),
3 tar = require('tar-fs'),
4 zlib = require('zlib'),
5 fs = require('fs'),
6 concat = require('concat-stream'),
7 path = require('path'),
8 Container = require('./container'),
9 Image = require('./image'),
10 Volume = require('./volume'),
11 Network = require('./network'),
12 Service = require('./service'),
13 Plugin = require('./plugin'),
14 Secret = require('./secret'),
15 Config = require('./config'),
16 Task = require('./task'),
17 Node = require('./node'),
18 Exec = require('./exec'),
19 util = require('./util'),
20 extend = util.extend;
21
22var Docker = function(opts) {
23 if (!(this instanceof Docker)) return new Docker(opts);
24
25 var plibrary = global.Promise;
26
27 if (opts && opts.Promise) {
28 plibrary = opts.Promise;
29
30 if (Object.keys(opts).length === 1) {
31 opts = undefined;
32 }
33 }
34
35 this.modem = new Modem(opts);
36 this.modem.Promise = plibrary;
37};
38
39/**
40 * Creates a new container
41 * @param {Object} opts Create options
42 * @param {Function} callback Callback
43 */
44Docker.prototype.createContainer = function(opts, callback) {
45 var self = this;
46 var optsf = {
47 path: '/containers/create?',
48 method: 'POST',
49 options: opts,
50 authconfig: opts.authconfig,
51 statusCodes: {
52 200: true, // unofficial, but proxies may return it
53 201: true,
54 404: 'no such container',
55 406: 'impossible to attach',
56 500: 'server error'
57 }
58 };
59
60 delete opts.authconfig;
61
62 if (callback === undefined) {
63 return new this.modem.Promise(function(resolve, reject) {
64 self.modem.dial(optsf, function(err, data) {
65 if (err) {
66 return reject(err);
67 }
68 resolve(self.getContainer(data.Id));
69 });
70 });
71 } else {
72 this.modem.dial(optsf, function(err, data) {
73 if (err) return callback(err, data);
74 callback(err, self.getContainer(data.Id));
75 });
76 }
77};
78
79/**
80 * Creates a new image
81 * @param {Object} auth Authentication (optional)
82 * @param {Object} opts Create options
83 * @param {Function} callback Callback
84 */
85Docker.prototype.createImage = function(auth, opts, callback) {
86 var self = this;
87 if (!callback && typeof opts === 'function') {
88 callback = opts;
89 opts = auth;
90 auth = opts.authconfig || undefined;
91 } else if (!callback && !opts) {
92 opts = auth;
93 auth = opts.authconfig;
94 }
95
96 var optsf = {
97 path: '/images/create?',
98 method: 'POST',
99 options: opts,
100 authconfig: auth,
101 isStream: true,
102 statusCodes: {
103 200: true,
104 500: 'server error'
105 }
106 };
107
108 if (callback === undefined) {
109 return new this.modem.Promise(function(resolve, reject) {
110 self.modem.dial(optsf, function(err, data) {
111 if (err) {
112 return reject(err);
113 }
114 resolve(data);
115 });
116 });
117 } else {
118 this.modem.dial(optsf, function(err, data) {
119 callback(err, data);
120 });
121 }
122};
123
124/**
125 * Load image
126 * @param {String} file File
127 * @param {Object} opts Options (optional)
128 * @param {Function} callback Callback
129 */
130Docker.prototype.loadImage = function(file, opts, callback) {
131 var self = this;
132 if (!callback && typeof opts === 'function') {
133 callback = opts;
134 opts = null;
135 }
136
137 var optsf = {
138 path: '/images/load?',
139 method: 'POST',
140 options: opts,
141 file: file,
142 isStream: true,
143 statusCodes: {
144 200: true,
145 500: 'server error'
146 }
147 };
148
149 if (callback === undefined) {
150 return new this.modem.Promise(function(resolve, reject) {
151 self.modem.dial(optsf, function(err, data) {
152 if (err) {
153 return reject(err);
154 }
155 resolve(data);
156 });
157 });
158 } else {
159 this.modem.dial(optsf, function(err, data) {
160 callback(err, data);
161 });
162 }
163};
164
165/**
166 * Import image from a tar archive
167 * @param {String} file File
168 * @param {Object} opts Options (optional)
169 * @param {Function} callback Callback
170 */
171Docker.prototype.importImage = function(file, opts, callback) {
172 var self = this;
173 if (!callback && typeof opts === 'function') {
174 callback = opts;
175 opts = {};
176 }
177
178 opts.fromSrc = '-';
179
180 var optsf = {
181 path: '/images/create?',
182 method: 'POST',
183 options: opts,
184 file: file,
185 isStream: true,
186 statusCodes: {
187 200: true,
188 500: 'server error'
189 }
190 };
191
192 if (callback === undefined) {
193 return new this.modem.Promise(function(resolve, reject) {
194 self.modem.dial(optsf, function(err, data) {
195 if (err) {
196 return reject(err);
197 }
198 resolve(data);
199 });
200 });
201 } else {
202 this.modem.dial(optsf, function(err, data) {
203 callback(err, data);
204 });
205 }
206};
207
208/**
209 * Verifies auth
210 * @param {Object} opts Options
211 * @param {Function} callback Callback
212 */
213Docker.prototype.checkAuth = function(opts, callback) {
214 var self = this;
215 var optsf = {
216 path: '/auth',
217 method: 'POST',
218 options: opts,
219 statusCodes: {
220 200: true,
221 204: true,
222 500: 'server error'
223 }
224 };
225
226 if (callback === undefined) {
227 return new this.modem.Promise(function(resolve, reject) {
228 self.modem.dial(optsf, function(err, data) {
229 if (err) {
230 return reject(err);
231 }
232 resolve(data);
233 });
234 });
235 } else {
236 this.modem.dial(optsf, function(err, data) {
237 callback(err, data);
238 });
239 }
240};
241
242/**
243 * Builds an image
244 * @param {String} file File
245 * @param {Object} opts Options (optional)
246 * @param {Function} callback Callback
247 */
248Docker.prototype.buildImage = function(file, opts, callback) {
249 var self = this;
250 var content;
251 var pack;
252
253 if (!callback && typeof opts === 'function') {
254 callback = opts;
255 opts = null;
256 }
257
258 function build(file) {
259 var optsf = {
260 path: '/build?',
261 method: 'POST',
262 file: file,
263 options: opts,
264 isStream: true,
265 statusCodes: {
266 200: true,
267 500: 'server error'
268 }
269 };
270
271 if (opts) {
272 if (opts.registryconfig) {
273 optsf.registryconfig = optsf.options.registryconfig;
274 delete optsf.options.registryconfig;
275 }
276
277 //undocumented?
278 if (opts.authconfig) {
279 optsf.authconfig = optsf.options.authconfig;
280 delete optsf.options.authconfig;
281 }
282 }
283
284 if (callback === undefined) {
285 return new self.modem.Promise(function(resolve, reject) {
286 self.modem.dial(optsf, function(err, data) {
287 if (err) {
288 return reject(err);
289 }
290 resolve(data);
291 });
292 });
293 } else {
294 self.modem.dial(optsf, function(err, data) {
295 callback(err, data);
296 });
297 }
298 }
299
300 if (file && file.context) {
301 pack = tar.pack(file.context, {
302 entries: file.src
303 });
304
305 if (callback === undefined) {
306 return new self.modem.Promise(function(resolve, reject) {
307 pack.on('error', function(error) {
308 return reject(error);
309 });
310 pack.on('end', function() {
311 return resolve(build(stream));
312 });
313 var stream = pack.pipe(zlib.createGzip());
314 });
315 } else {
316 pack.on('error', function(error) {
317 return callback(error);
318 });
319 pack.on('end', function() {
320 return build(stream);
321 });
322 var stream = pack.pipe(zlib.createGzip());
323 }
324 } else {
325 return build(file);
326 }
327};
328
329/**
330 * Fetches a Container by ID
331 * @param {String} id Container's ID
332 */
333Docker.prototype.getContainer = function(id) {
334 return new Container(this.modem, id);
335};
336
337/**
338 * Fetches an Image by name
339 * @param {String} name Image's name
340 */
341Docker.prototype.getImage = function(name) {
342 return new Image(this.modem, name);
343};
344
345/**
346 * Fetches a Volume by name
347 * @param {String} name Volume's name
348 */
349Docker.prototype.getVolume = function(name) {
350 return new Volume(this.modem, name);
351};
352
353/**
354 * Fetches a Plugin by name
355 * @param {String} name Volume's name
356 */
357Docker.prototype.getPlugin = function(name, remote) {
358 return new Plugin(this.modem, name, remote);
359};
360
361/**
362 * Fetches a Service by id
363 * @param {String} id Services's id
364 */
365Docker.prototype.getService = function(id) {
366 return new Service(this.modem, id);
367};
368
369/**
370 * Fetches a Task by id
371 * @param {String} id Task's id
372 */
373Docker.prototype.getTask = function(id) {
374 return new Task(this.modem, id);
375};
376
377/**
378 * Fetches Node by id
379 * @param {String} id Node's id
380 */
381Docker.prototype.getNode = function(id) {
382 return new Node(this.modem, id);
383};
384
385/**
386 * Fetches a Network by id
387 * @param {String} id network's id
388 */
389Docker.prototype.getNetwork = function(id) {
390 return new Network(this.modem, id);
391};
392
393/**
394 * Fetches a Secret by id
395 * @param {String} id network's id
396 */
397Docker.prototype.getSecret = function(id) {
398 return new Secret(this.modem, id);
399};
400
401/**
402 * Fetches a Config by id
403 * @param {String} id network's id
404 */
405Docker.prototype.getConfig = function(id) {
406 return new Config(this.modem, id);
407};
408
409/**
410 * Fetches an Exec instance by ID
411 * @param {String} id Exec instance's ID
412 */
413Docker.prototype.getExec = function(id) {
414 return new Exec(this.modem, id);
415};
416
417/**
418 * Lists containers
419 * @param {Object} opts Options (optional)
420 * @param {Function} callback Callback
421 */
422Docker.prototype.listContainers = function(opts, callback) {
423 var self = this;
424 var args = util.processArgs(opts, callback);
425
426 var optsf = {
427 path: '/containers/json?',
428 method: 'GET',
429 options: args.opts,
430 statusCodes: {
431 200: true,
432 400: 'bad parameter',
433 500: 'server error'
434 }
435 };
436
437 if (args.callback === undefined) {
438 return new this.modem.Promise(function(resolve, reject) {
439 self.modem.dial(optsf, function(err, data) {
440 if (err) {
441 return reject(err);
442 }
443 resolve(data);
444 });
445 });
446 } else {
447 this.modem.dial(optsf, function(err, data) {
448 args.callback(err, data);
449 });
450 }
451};
452
453/**
454 * Lists images
455 * @param {Object} opts Options (optional)
456 * @param {Function} callback Callback
457 */
458Docker.prototype.listImages = function(opts, callback) {
459 var self = this;
460 var args = util.processArgs(opts, callback);
461
462 var optsf = {
463 path: '/images/json?',
464 method: 'GET',
465 options: args.opts,
466 statusCodes: {
467 200: true,
468 400: 'bad parameter',
469 500: 'server error'
470 }
471 };
472
473 if (args.callback === undefined) {
474 return new this.modem.Promise(function(resolve, reject) {
475 self.modem.dial(optsf, function(err, data) {
476 if (err) {
477 return reject(err);
478 }
479 resolve(data);
480 });
481 });
482 } else {
483 this.modem.dial(optsf, function(err, data) {
484 args.callback(err, data);
485 });
486 }
487};
488
489/**
490 * Lists Services
491 * @param {Object} opts
492 * @param {Function} callback Callback
493 */
494Docker.prototype.listServices = function(opts, callback) {
495 var self = this;
496 var args = util.processArgs(opts, callback);
497
498 var optsf = {
499 path: '/services?',
500 method: 'GET',
501 options: args.opts,
502 statusCodes: {
503 200: true,
504 500: 'server error'
505 }
506 };
507
508 if (args.callback === undefined) {
509 return new this.modem.Promise(function(resolve, reject) {
510 self.modem.dial(optsf, function(err, data) {
511 if (err) {
512 return reject(err);
513 }
514 resolve(data);
515 });
516 });
517 } else {
518 this.modem.dial(optsf, function(err, data) {
519 args.callback(err, data);
520 });
521 }
522};
523
524/**
525 * Lists Nodes
526 * @param {Object} opts
527 * @param {Function} callback Callback
528 */
529Docker.prototype.listNodes = function(opts, callback) {
530 var self = this;
531 var args = util.processArgs(opts, callback);
532
533 var optsf = {
534 path: '/nodes?',
535 method: 'GET',
536 options: args.opts,
537 statusCodes: {
538 200: true,
539 400: 'bad parameter',
540 404: 'no such node',
541 500: 'server error',
542 503: 'node is not part of a swarm',
543 }
544 };
545
546 if (args.callback === undefined) {
547 return new this.modem.Promise(function(resolve, reject) {
548 self.modem.dial(optsf, function(err, data) {
549 if (err) {
550 return reject(err);
551 }
552 resolve(data);
553 });
554 });
555 } else {
556 this.modem.dial(optsf, function(err, data) {
557 args.callback(err, data);
558 });
559 }
560};
561
562/**
563 * Lists Tasks
564 * @param {Object} opts
565 * @param {Function} callback Callback
566 */
567Docker.prototype.listTasks = function(opts, callback) {
568 var self = this;
569 var args = util.processArgs(opts, callback);
570
571 var optsf = {
572 path: '/tasks?',
573 method: 'GET',
574 options: args.opts,
575 statusCodes: {
576 200: true,
577 500: 'server error'
578 }
579 };
580
581 if (args.callback === undefined) {
582 return new this.modem.Promise(function(resolve, reject) {
583 self.modem.dial(optsf, function(err, data) {
584 if (err) {
585 return reject(err);
586 }
587 resolve(data);
588 });
589 });
590 } else {
591 this.modem.dial(optsf, function(err, data) {
592 args.callback(err, data);
593 });
594 }
595};
596
597/**
598 * Creates a new secret
599 * @param {Object} opts Create options
600 * @param {Function} callback Callback
601 */
602Docker.prototype.createSecret = function(opts, callback) {
603 var args = util.processArgs(opts, callback);
604 var self = this;
605 var optsf = {
606 path: '/secrets/create?',
607 method: 'POST',
608 options: args.opts,
609 statusCodes: {
610 200: true, // unofficial, but proxies may return it
611 201: true,
612 406: 'server error or node is not part of a swarm',
613 409: 'name conflicts with an existing object',
614 500: 'server error'
615 }
616 };
617
618
619 if (args.callback === undefined) {
620 return new this.modem.Promise(function(resolve, reject) {
621 self.modem.dial(optsf, function(err, data) {
622 if (err) {
623 return reject(err);
624 }
625 resolve(self.getSecret(data.ID));
626 });
627 });
628 } else {
629 this.modem.dial(optsf, function(err, data) {
630 if (err) return args.callback(err, data);
631 args.callback(err, self.getSecret(data.ID));
632 });
633 }
634};
635
636
637/**
638 * Creates a new config
639 * @param {Object} opts Config options
640 * @param {Function} callback Callback
641 */
642Docker.prototype.createConfig = function(opts, callback) {
643 var args = util.processArgs(opts, callback);
644 var self = this;
645 var optsf = {
646 path: '/configs/create?',
647 method: 'POST',
648 options: args.opts,
649 statusCodes: {
650 200: true, // unofficial, but proxies may return it
651 201: true,
652 406: 'server error or node is not part of a swarm',
653 409: 'name conflicts with an existing object',
654 500: 'server error'
655 }
656 };
657
658
659 if (args.callback === undefined) {
660 return new this.modem.Promise(function(resolve, reject) {
661 self.modem.dial(optsf, function(err, data) {
662 if (err) {
663 return reject(err);
664 }
665 resolve(self.getConfig(data.ID));
666 });
667 });
668 } else {
669 this.modem.dial(optsf, function(err, data) {
670 if (err) return args.callback(err, data);
671 args.callback(err, self.getConfig(data.ID));
672 });
673 }
674};
675
676
677/**
678 * Lists secrets
679 * @param {Object} opts
680 * @param {Function} callback Callback
681 */
682Docker.prototype.listSecrets = function(opts, callback) {
683 var self = this;
684 var args = util.processArgs(opts, callback);
685
686 var optsf = {
687 path: '/secrets?',
688 method: 'GET',
689 options: args.opts,
690 statusCodes: {
691 200: true,
692 500: 'server error'
693 }
694 };
695
696 if (args.callback === undefined) {
697 return new this.modem.Promise(function(resolve, reject) {
698 self.modem.dial(optsf, function(err, data) {
699 if (err) {
700 return reject(err);
701 }
702 resolve(data);
703 });
704 });
705 } else {
706 this.modem.dial(optsf, function(err, data) {
707 args.callback(err, data);
708 });
709 }
710};
711
712/**
713 * Lists configs
714 * @param {Object} opts
715 * @param {Function} callback Callback
716 */
717Docker.prototype.listConfigs = function(opts, callback) {
718 var self = this;
719 var args = util.processArgs(opts, callback);
720
721 var optsf = {
722 path: '/configs?',
723 method: 'GET',
724 options: args.opts,
725 statusCodes: {
726 200: true,
727 500: 'server error'
728 }
729 };
730
731 if (args.callback === undefined) {
732 return new this.modem.Promise(function(resolve, reject) {
733 self.modem.dial(optsf, function(err, data) {
734 if (err) {
735 return reject(err);
736 }
737 resolve(data);
738 });
739 });
740 } else {
741 this.modem.dial(optsf, function(err, data) {
742 args.callback(err, data);
743 });
744 }
745};
746
747/**
748 * Creates a new plugin
749 * @param {Object} opts Create options
750 * @param {Function} callback Callback
751 */
752Docker.prototype.createPlugin = function(opts, callback) {
753 var self = this;
754 var args = util.processArgs(opts, callback);
755 var optsf = {
756 path: '/plugins/create?',
757 method: 'POST',
758 options: args.opts,
759 statusCodes: {
760 200: true, // unofficial, but proxies may return it
761 204: true,
762 500: 'server error'
763 }
764 };
765
766
767 if (args.callback === undefined) {
768 return new this.modem.Promise(function(resolve, reject) {
769 self.modem.dial(optsf, function(err, data) {
770 if (err) {
771 return reject(err);
772 }
773 resolve(self.getPlugin(args.opts.name));
774 });
775 });
776 } else {
777 this.modem.dial(optsf, function(err, data) {
778 if (err) return args.callback(err, data);
779 args.callback(err, self.getPlugin(args.opts.name));
780 });
781 }
782};
783
784
785/**
786 * Lists plugins
787 * @param {Object} opts
788 * @param {Function} callback Callback
789 */
790Docker.prototype.listPlugins = function(opts, callback) {
791 var self = this;
792 var args = util.processArgs(opts, callback);
793
794 var optsf = {
795 path: '/plugins?',
796 method: 'GET',
797 options: args.opts,
798 statusCodes: {
799 200: true,
800 500: 'server error'
801 }
802 };
803
804 if (args.callback === undefined) {
805 return new this.modem.Promise(function(resolve, reject) {
806 self.modem.dial(optsf, function(err, data) {
807 if (err) {
808 return reject(err);
809 }
810 resolve(data);
811 });
812 });
813 } else {
814 this.modem.dial(optsf, function(err, data) {
815 args.callback(err, data);
816 });
817 }
818};
819
820/**
821 * Prune images
822 * @param {Object} opts Options (optional)
823 * @param {Function} callback Callback
824 */
825Docker.prototype.pruneImages = function(opts, callback) {
826 var self = this;
827 var args = util.processArgs(opts, callback);
828
829 var optsf = {
830 path: '/images/prune?',
831 method: 'POST',
832 options: args.opts,
833 statusCodes: {
834 200: true,
835 500: 'server error'
836 }
837 };
838
839 if (args.callback === undefined) {
840 return new this.modem.Promise(function(resolve, reject) {
841 self.modem.dial(optsf, function(err, data) {
842 if (err) {
843 return reject(err);
844 }
845 resolve(data);
846 });
847 });
848 } else {
849 this.modem.dial(optsf, function(err, data) {
850 args.callback(err, data);
851 });
852 }
853};
854
855/**
856 * Prune builder
857 * @param {Function} callback Callback
858 */
859Docker.prototype.pruneBuilder = function(callback) {
860 var self = this;
861
862 var optsf = {
863 path: '/build/prune',
864 method: 'POST',
865 statusCodes: {
866 200: true,
867 500: 'server error'
868 }
869 };
870
871 if (args.callback === undefined) {
872 return new this.modem.Promise(function(resolve, reject) {
873 self.modem.dial(optsf, function(err, data) {
874 if (err) {
875 return reject(err);
876 }
877 resolve(data);
878 });
879 });
880 } else {
881 this.modem.dial(optsf, function(err, data) {
882 callback(err, data);
883 });
884 }
885};
886
887/**
888 * Prune containers
889 * @param {Object} opts Options (optional)
890 * @param {Function} callback Callback
891 */
892Docker.prototype.pruneContainers = function(opts, callback) {
893 var self = this;
894 var args = util.processArgs(opts, callback);
895
896 var optsf = {
897 path: '/containers/prune?',
898 method: 'POST',
899 options: args.opts,
900 statusCodes: {
901 200: true,
902 500: 'server error'
903 }
904 };
905
906 if (args.callback === undefined) {
907 return new this.modem.Promise(function(resolve, reject) {
908 self.modem.dial(optsf, function(err, data) {
909 if (err) {
910 return reject(err);
911 }
912 resolve(data);
913 });
914 });
915 } else {
916 this.modem.dial(optsf, function(err, data) {
917 args.callback(err, data);
918 });
919 }
920};
921
922/**
923 * Prune volumes
924 * @param {Object} opts Options (optional)
925 * @param {Function} callback Callback
926 */
927Docker.prototype.pruneVolumes = function(opts, callback) {
928 var self = this;
929 var args = util.processArgs(opts, callback);
930
931 var optsf = {
932 path: '/volumes/prune?',
933 method: 'POST',
934 options: args.opts,
935 statusCodes: {
936 200: true,
937 500: 'server error'
938 }
939 };
940
941 if (args.callback === undefined) {
942 return new this.modem.Promise(function(resolve, reject) {
943 self.modem.dial(optsf, function(err, data) {
944 if (err) {
945 return reject(err);
946 }
947 resolve(data);
948 });
949 });
950 } else {
951 this.modem.dial(optsf, function(err, data) {
952 args.callback(err, data);
953 });
954 }
955};
956
957/**
958 * Prune networks
959 * @param {Object} opts Options (optional)
960 * @param {Function} callback Callback
961 */
962Docker.prototype.pruneNetworks = function(opts, callback) {
963 var self = this;
964 var args = util.processArgs(opts, callback);
965
966 var optsf = {
967 path: '/networks/prune?',
968 method: 'POST',
969 options: args.opts,
970 statusCodes: {
971 200: true,
972 500: 'server error'
973 }
974 };
975
976 if (args.callback === undefined) {
977 return new this.modem.Promise(function(resolve, reject) {
978 self.modem.dial(optsf, function(err, data) {
979 if (err) {
980 return reject(err);
981 }
982 resolve(data);
983 });
984 });
985 } else {
986 this.modem.dial(optsf, function(err, data) {
987 args.callback(err, data);
988 });
989 }
990};
991
992
993/**
994 * Creates a new volume
995 * @param {Object} opts Create options
996 * @param {Function} callback Callback
997 */
998Docker.prototype.createVolume = function(opts, callback) {
999 var self = this;
1000 var args = util.processArgs(opts, callback);
1001 var optsf = {
1002 path: '/volumes/create?',
1003 method: 'POST',
1004 options: args.opts,
1005 statusCodes: {
1006 200: true, // unofficial, but proxies may return it
1007 201: true,
1008 500: 'server error'
1009 }
1010 };
1011
1012
1013 if (args.callback === undefined) {
1014 return new this.modem.Promise(function(resolve, reject) {
1015 self.modem.dial(optsf, function(err, data) {
1016 if (err) {
1017 return reject(err);
1018 }
1019 resolve(self.getVolume(data.Name));
1020 });
1021 });
1022 } else {
1023 this.modem.dial(optsf, function(err, data) {
1024 if (err) return args.callback(err, data);
1025 args.callback(err, self.getVolume(data.Name));
1026 });
1027 }
1028};
1029
1030/**
1031 * Creates a new service
1032 * @param {Object} auth
1033 * @param {Object} opts Create options
1034 * @param {Function} callback Callback
1035 */
1036Docker.prototype.createService = function(auth, opts, callback) {
1037 if (!callback && typeof opts === 'function') {
1038 callback = opts;
1039 opts = auth;
1040 auth = opts.authconfig || undefined;
1041 } else if (!opts && !callback) {
1042 opts = auth;
1043 }
1044
1045
1046 var self = this;
1047 var optsf = {
1048 path: '/services/create',
1049 method: 'POST',
1050 options: opts,
1051 authconfig: auth,
1052 statusCodes: {
1053 200: true,
1054 201: true,
1055 500: 'server error'
1056 }
1057 };
1058
1059
1060 if (callback === undefined) {
1061 return new this.modem.Promise(function(resolve, reject) {
1062 self.modem.dial(optsf, function(err, data) {
1063 if (err) {
1064 return reject(err);
1065 }
1066 resolve(self.getService(data.ID || data.Id));
1067 });
1068 });
1069 } else {
1070 this.modem.dial(optsf, function(err, data) {
1071 if (err) return callback(err, data);
1072 callback(err, self.getService(data.ID || data.Id));
1073 });
1074 }
1075};
1076
1077/**
1078 * Lists volumes
1079 * @param {Object} opts Options (optional)
1080 * @param {Function} callback Callback
1081 */
1082Docker.prototype.listVolumes = function(opts, callback) {
1083 var self = this;
1084 var args = util.processArgs(opts, callback);
1085
1086 var optsf = {
1087 path: '/volumes?',
1088 method: 'GET',
1089 options: args.opts,
1090 statusCodes: {
1091 200: true,
1092 400: 'bad parameter',
1093 500: 'server error'
1094 }
1095 };
1096
1097 if (args.callback === undefined) {
1098 return new this.modem.Promise(function(resolve, reject) {
1099 self.modem.dial(optsf, function(err, data) {
1100 if (err) {
1101 return reject(err);
1102 }
1103 resolve(data);
1104 });
1105 });
1106 } else {
1107 this.modem.dial(optsf, function(err, data) {
1108 args.callback(err, data);
1109 });
1110 }
1111};
1112
1113/**
1114 * Creates a new network
1115 * @param {Object} opts Create options
1116 * @param {Function} callback Callback
1117 */
1118Docker.prototype.createNetwork = function(opts, callback) {
1119 var self = this;
1120 var args = util.processArgs(opts, callback);
1121 var optsf = {
1122 path: '/networks/create?',
1123 method: 'POST',
1124 options: args.opts,
1125 statusCodes: {
1126 200: true, // unofficial, but proxies may return it
1127 201: true,
1128 404: 'driver not found',
1129 500: 'server error'
1130 }
1131 };
1132
1133
1134 if (args.callback === undefined) {
1135 return new this.modem.Promise(function(resolve, reject) {
1136 self.modem.dial(optsf, function(err, data) {
1137 if (err) {
1138 return reject(err);
1139 }
1140 resolve(self.getNetwork(data.Id));
1141 });
1142 });
1143 } else {
1144 this.modem.dial(optsf, function(err, data) {
1145 if (err) return args.callback(err, data);
1146 args.callback(err, self.getNetwork(data.Id));
1147 });
1148 }
1149};
1150
1151/**
1152 * Lists networkss
1153 * @param {Object} opts Options (optional)
1154 * @param {Function} callback Callback
1155 */
1156Docker.prototype.listNetworks = function(opts, callback) {
1157 var self = this;
1158 var args = util.processArgs(opts, callback);
1159
1160 var optsf = {
1161 path: '/networks?',
1162 method: 'GET',
1163 options: args.opts,
1164 statusCodes: {
1165 200: true,
1166 400: 'bad parameter',
1167 500: 'server error'
1168 }
1169 };
1170
1171 if (args.callback === undefined) {
1172 return new this.modem.Promise(function(resolve, reject) {
1173 self.modem.dial(optsf, function(err, data) {
1174 if (err) {
1175 return reject(err);
1176 }
1177 resolve(data);
1178 });
1179 });
1180 } else {
1181 this.modem.dial(optsf, function(err, data) {
1182 args.callback(err, data);
1183 });
1184 }
1185};
1186
1187/**
1188 * Search images
1189 * @param {Object} opts Options
1190 * @param {Function} callback Callback
1191 */
1192Docker.prototype.searchImages = function(opts, callback) {
1193 var self = this;
1194 var optsf = {
1195 path: '/images/search?',
1196 method: 'GET',
1197 options: opts,
1198 authconfig: opts.authconfig,
1199 statusCodes: {
1200 200: true,
1201 500: 'server error'
1202 }
1203 };
1204
1205 if (callback === undefined) {
1206 return new this.modem.Promise(function(resolve, reject) {
1207 self.modem.dial(optsf, function(err, data) {
1208 if (err) {
1209 return reject(err);
1210 }
1211 resolve(data);
1212 });
1213 });
1214 } else {
1215 this.modem.dial(optsf, function(err, data) {
1216 callback(err, data);
1217 });
1218 }
1219};
1220
1221/**
1222 * Info
1223 * @param {Function} callback Callback with info
1224 */
1225Docker.prototype.info = function(callback) {
1226 var self = this;
1227 var opts = {
1228 path: '/info',
1229 method: 'GET',
1230 statusCodes: {
1231 200: true,
1232 500: 'server error'
1233 }
1234 };
1235
1236
1237 if (callback === undefined) {
1238 return new this.modem.Promise(function(resolve, reject) {
1239 self.modem.dial(opts, function(err, data) {
1240 if (err) {
1241 return reject(err);
1242 }
1243 resolve(data);
1244 });
1245 });
1246 } else {
1247 this.modem.dial(opts, function(err, data) {
1248 callback(err, data);
1249 });
1250 }
1251};
1252
1253/**
1254 * Version
1255 * @param {Function} callback Callback
1256 */
1257Docker.prototype.version = function(callback) {
1258 var self = this;
1259 var opts = {
1260 path: '/version',
1261 method: 'GET',
1262 statusCodes: {
1263 200: true,
1264 500: 'server error'
1265 }
1266 };
1267
1268 if (callback === undefined) {
1269 return new this.modem.Promise(function(resolve, reject) {
1270 self.modem.dial(opts, function(err, data) {
1271 if (err) {
1272 return reject(err);
1273 }
1274 resolve(data);
1275 });
1276 });
1277 } else {
1278 this.modem.dial(opts, function(err, data) {
1279 callback(err, data);
1280 });
1281 }
1282};
1283
1284/**
1285 * Ping
1286 * @param {Function} callback Callback
1287 */
1288Docker.prototype.ping = function(callback) {
1289 var self = this;
1290 var optsf = {
1291 path: '/_ping',
1292 method: 'GET',
1293 statusCodes: {
1294 200: true,
1295 500: 'server error'
1296 }
1297 };
1298
1299 if (callback === undefined) {
1300 return new this.modem.Promise(function(resolve, reject) {
1301 self.modem.dial(optsf, function(err, data) {
1302 if (err) {
1303 return reject(err);
1304 }
1305 resolve(data);
1306 });
1307 });
1308 } else {
1309 this.modem.dial(optsf, function(err, data) {
1310 callback(err, data);
1311 });
1312 }
1313};
1314
1315/**
1316 * SystemDf equivalent to system/df API Engine
1317 * get usage data information
1318 * @param {Function} callback Callback
1319 */
1320Docker.prototype.df = function(callback) {
1321 var self = this;
1322 var optsf = {
1323 path: '/system/df',
1324 method: 'GET',
1325 statusCodes: {
1326 200: true,
1327 500: 'server error'
1328 }
1329 };
1330
1331 if (callback === undefined) {
1332 return new this.modem.Promise(function(resolve, reject) {
1333 self.modem.dial(optsf, function(err, data) {
1334 if (err) {
1335 return reject(err);
1336 }
1337 resolve(data);
1338 });
1339 });
1340 } else {
1341 this.modem.dial(optsf, function(err, data) {
1342 callback(err, data);
1343 });
1344 }
1345};
1346
1347/**
1348 * Events
1349 * @param {Object} opts Events options, like 'since' (optional)
1350 * @param {Function} callback Callback
1351 */
1352Docker.prototype.getEvents = function(opts, callback) {
1353 var self = this;
1354 var args = util.processArgs(opts, callback);
1355
1356 var optsf = {
1357 path: '/events?',
1358 method: 'GET',
1359 options: args.opts,
1360 isStream: true,
1361 statusCodes: {
1362 200: true,
1363 500: 'server error'
1364 }
1365 };
1366
1367 if (args.callback === undefined) {
1368 return new this.modem.Promise(function(resolve, reject) {
1369 self.modem.dial(optsf, function(err, data) {
1370 if (err) {
1371 return reject(err);
1372 }
1373 resolve(data);
1374 });
1375 });
1376 } else {
1377 this.modem.dial(optsf, function(err, data) {
1378 args.callback(err, data);
1379 });
1380 }
1381};
1382
1383/**
1384 * Pull is a wrapper around createImage, parsing image's tags.
1385 * @param {String} repoTag Repository tag
1386 * @param {Object} opts Options (optional)
1387 * @param {Function} callback Callback
1388 * @param {Object} auth Authentication (optional)
1389 * @return {Object} Image
1390 */
1391Docker.prototype.pull = function(repoTag, opts, callback, auth) {
1392 var args = util.processArgs(opts, callback);
1393
1394 var imageSrc = util.parseRepositoryTag(repoTag);
1395 args.opts.fromImage = imageSrc.repository;
1396 args.opts.tag = imageSrc.tag || 'latest';
1397
1398 var argsf = [args.opts, args.callback];
1399 if (auth) {
1400 argsf = [auth, args.opts, args.callback];
1401 }
1402 return this.createImage.apply(this, argsf);
1403};
1404
1405/**
1406 * Like run command from Docker's CLI
1407 * @param {String} image Image name to be used.
1408 * @param {Array} cmd Command to run in array format.
1409 * @param {Object} streamo Output stream
1410 * @param {Object} createOptions Container create options (optional)
1411 * @param {Object} startOptions Container start options (optional)
1412 * @param {Function} callback Callback
1413 * @return {Object} EventEmitter
1414 */
1415Docker.prototype.run = function(image, cmd, streamo, createOptions, startOptions, callback) {
1416 if (typeof arguments[arguments.length - 1] === 'function') {
1417 return this.runCallback(image, cmd, streamo, createOptions, startOptions, callback);
1418 } else {
1419 return this.runPromise(image, cmd, streamo, createOptions, startOptions);
1420 }
1421};
1422
1423
1424Docker.prototype.runCallback = function(image, cmd, streamo, createOptions, startOptions, callback) {
1425 if (!callback && typeof createOptions === 'function') {
1426 callback = createOptions;
1427 createOptions = {};
1428 startOptions = {};
1429 } else if (!callback && typeof startOptions === 'function') {
1430 callback = startOptions;
1431 startOptions = {};
1432 }
1433
1434 var hub = new EventEmitter();
1435
1436 function handler(err, container) {
1437 if (err) return callback(err, null, container);
1438
1439 hub.emit('container', container);
1440
1441 container.attach({
1442 stream: true,
1443 stdout: true,
1444 stderr: true
1445 }, function handler(err, stream) {
1446 if (err) return callback(err, null, container);
1447
1448 hub.emit('stream', stream);
1449
1450 if (streamo) {
1451 if (streamo instanceof Array) {
1452 stream.on('end', function() {
1453 try {
1454 streamo[0].end();
1455 } catch (e) {}
1456 try {
1457 streamo[1].end();
1458 } catch (e) {}
1459 });
1460 container.modem.demuxStream(stream, streamo[0], streamo[1]);
1461 } else {
1462 stream.setEncoding('utf8');
1463 stream.pipe(streamo, {
1464 end: true
1465 });
1466 }
1467 }
1468
1469 container.start(startOptions, function(err, data) {
1470 if (err) return callback(err, data, container);
1471 hub.emit('start', container);
1472
1473 container.wait(function(err, data) {
1474 hub.emit('data', data);
1475 callback(err, data, container);
1476 });
1477 });
1478 });
1479 }
1480
1481 var optsc = {
1482 'Hostname': '',
1483 'User': '',
1484 'AttachStdin': false,
1485 'AttachStdout': true,
1486 'AttachStderr': true,
1487 'Tty': true,
1488 'OpenStdin': false,
1489 'StdinOnce': false,
1490 'Env': null,
1491 'Cmd': cmd,
1492 'Image': image,
1493 'Volumes': {},
1494 'VolumesFrom': []
1495 };
1496
1497 extend(optsc, createOptions);
1498
1499 this.createContainer(optsc, handler);
1500
1501 return hub;
1502};
1503
1504Docker.prototype.runPromise = function(image, cmd, streamo, createOptions, startOptions) {
1505 var self = this;
1506
1507 createOptions = createOptions || {};
1508 startOptions = startOptions || {};
1509
1510 var optsc = {
1511 'Hostname': '',
1512 'User': '',
1513 'AttachStdin': false,
1514 'AttachStdout': true,
1515 'AttachStderr': true,
1516 'Tty': true,
1517 'OpenStdin': false,
1518 'StdinOnce': false,
1519 'Env': null,
1520 'Cmd': cmd,
1521 'Image': image,
1522 'Volumes': {},
1523 'VolumesFrom': []
1524 };
1525
1526 extend(optsc, createOptions);
1527
1528 var containero;
1529
1530 return new this.modem.Promise(function(resolve, reject) {
1531 self.createContainer(optsc).then(function(container) {
1532 containero = container;
1533 return container.attach({
1534 stream: true,
1535 stdout: true,
1536 stderr: true
1537 });
1538 }).then(function(stream) {
1539 if (streamo) {
1540 if (streamo instanceof Array) {
1541 stream.on('end', function() {
1542 try {
1543 streamo[0].end();
1544 } catch (e) {}
1545 try {
1546 streamo[1].end();
1547 } catch (e) {}
1548 });
1549 containero.modem.demuxStream(stream, streamo[0], streamo[1]);
1550 } else {
1551 stream.setEncoding('utf8');
1552 stream.pipe(streamo, {
1553 end: true
1554 });
1555 }
1556 }
1557 return containero.start(startOptions);
1558 }).then(function(data) {
1559 return containero.wait();
1560 }).then(function(data) {
1561 resolve([data, containero]);
1562 }).catch(function(err) {
1563 reject(err);
1564 });
1565 });
1566};
1567
1568/**
1569 * Init swarm.
1570 *
1571 * @param {object} opts
1572 * @param {function} callback
1573 */
1574Docker.prototype.swarmInit = function(opts, callback) {
1575 var self = this;
1576 var args = util.processArgs(opts, callback);
1577
1578 var optsf = {
1579 path: '/swarm/init',
1580 method: 'POST',
1581 statusCodes: {
1582 200: true,
1583 400: 'bad parameter',
1584 406: 'node is already part of a Swarm'
1585 },
1586 options: args.opts
1587 };
1588
1589 if (args.callback === undefined) {
1590 return new this.modem.Promise(function(resolve, reject) {
1591 self.modem.dial(optsf, function(err, data) {
1592 if (err) {
1593 return reject(err);
1594 }
1595 resolve(data);
1596 });
1597 });
1598 } else {
1599 this.modem.dial(optsf, function(err, data) {
1600 args.callback(err, data);
1601 });
1602 }
1603};
1604
1605/**
1606 * Join swarm.
1607 *
1608 * @param {object} opts
1609 * @param {function} callback
1610 */
1611Docker.prototype.swarmJoin = function(opts, callback) {
1612 var self = this;
1613 var args = util.processArgs(opts, callback);
1614
1615 var optsf = {
1616 path: '/swarm/join',
1617 method: 'POST',
1618 statusCodes: {
1619 200: true,
1620 400: 'bad parameter',
1621 406: 'node is already part of a Swarm'
1622 },
1623 options: args.opts
1624 };
1625
1626 if (args.callback === undefined) {
1627 return new this.modem.Promise(function(resolve, reject) {
1628 self.modem.dial(optsf, function(err, data) {
1629 if (err) {
1630 return reject(err);
1631 }
1632 resolve(data);
1633 });
1634 });
1635 } else {
1636 this.modem.dial(optsf, function(err, data) {
1637 args.callback(err, data);
1638 });
1639 }
1640};
1641
1642/**
1643 * Leave swarm.
1644 *
1645 * @param {object} opts
1646 * @param {function} callback
1647 */
1648Docker.prototype.swarmLeave = function(opts, callback) {
1649 var self = this;
1650 var args = util.processArgs(opts, callback);
1651
1652 var optsf = {
1653 path: '/swarm/leave?',
1654 method: 'POST',
1655 statusCodes: {
1656 200: true,
1657 406: 'node is not part of a Swarm'
1658 },
1659 options: args.opts
1660 };
1661
1662 if (args.callback === undefined) {
1663 return new this.modem.Promise(function(resolve, reject) {
1664 self.modem.dial(optsf, function(err, data) {
1665 if (err) {
1666 return reject(err);
1667 }
1668 resolve(data);
1669 });
1670 });
1671 } else {
1672 this.modem.dial(optsf, function(err, data) {
1673 args.callback(err, data);
1674 });
1675 }
1676};
1677
1678/**
1679 * Update swarm.
1680 *
1681 * @param {object} opts
1682 * @param {function} callback
1683 */
1684Docker.prototype.swarmUpdate = function(opts, callback) {
1685 var self = this;
1686 var args = util.processArgs(opts, callback);
1687
1688 var optsf = {
1689 path: '/swarm/update?',
1690 method: 'POST',
1691 statusCodes: {
1692 200: true,
1693 400: 'bad parameter',
1694 406: 'node is already part of a Swarm'
1695 },
1696 options: args.opts
1697 };
1698
1699 if (args.callback === undefined) {
1700 return new this.modem.Promise(function(resolve, reject) {
1701 self.modem.dial(optsf, function(err, data) {
1702 if (err) {
1703 return reject(err);
1704 }
1705 resolve(data);
1706 });
1707 });
1708 } else {
1709 this.modem.dial(optsf, function(err, data) {
1710 args.callback(err, data);
1711 });
1712 }
1713};
1714
1715
1716/**
1717 * Inspect a Swarm.
1718 * Warning: This method is not documented in the API
1719 *
1720 * @param {Function} callback Callback
1721 */
1722Docker.prototype.swarmInspect = function(callback) {
1723 var self = this;
1724 var optsf = {
1725 path: '/swarm',
1726 method: 'GET',
1727 statusCodes: {
1728 200: true,
1729 406: 'This node is not a swarm manager',
1730 500: 'server error'
1731 }
1732 };
1733
1734 if (callback === undefined) {
1735 return new this.modem.Promise(function(resolve, reject) {
1736 self.modem.dial(optsf, function(err, data) {
1737 if (err) {
1738 return reject(err);
1739 }
1740 resolve(data);
1741 });
1742 });
1743 } else {
1744 this.modem.dial(optsf, function(err, data) {
1745 callback(err, data);
1746 });
1747 }
1748};
1749
1750Docker.Container = Container;
1751Docker.Image = Image;
1752Docker.Volume = Volume;
1753Docker.Network = Network;
1754Docker.Service = Service;
1755Docker.Plugin = Plugin;
1756Docker.Secret = Secret;
1757Docker.Task = Task;
1758Docker.Node = Node;
1759Docker.Exec = Exec;
1760
1761module.exports = Docker;