docker.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764
  1. 'use strict';
  2. // @ts-check
  3. // ==================================================================================
  4. // docker.js
  5. // ----------------------------------------------------------------------------------
  6. // Description: System Information - library
  7. // for Node.js
  8. // Copyright: (c) 2014 - 2022
  9. // Author: Sebastian Hildebrandt
  10. // ----------------------------------------------------------------------------------
  11. // License: MIT
  12. // ==================================================================================
  13. // 13. Docker
  14. // ----------------------------------------------------------------------------------
  15. const util = require('./util');
  16. const DockerSocket = require('./dockerSocket');
  17. let _platform = process.platform;
  18. const _windows = (_platform === 'win32');
  19. let _docker_container_stats = {};
  20. let _docker_socket;
  21. let _docker_last_read = 0;
  22. // --------------------------
  23. // get containers (parameter all: get also inactive/exited containers)
  24. function dockerInfo(callback) {
  25. return new Promise((resolve) => {
  26. process.nextTick(() => {
  27. if (!_docker_socket) {
  28. _docker_socket = new DockerSocket();
  29. }
  30. const result = {};
  31. _docker_socket.getInfo(data => {
  32. result.id = data.ID;
  33. result.containers = data.Containers;
  34. result.containersRunning = data.ContainersRunning;
  35. result.containersPaused = data.ContainersPaused;
  36. result.containersStopped = data.ContainersStopped;
  37. result.images = data.Images;
  38. result.driver = data.Driver;
  39. result.memoryLimit = data.MemoryLimit;
  40. result.swapLimit = data.SwapLimit;
  41. result.kernelMemory = data.KernelMemory;
  42. result.cpuCfsPeriod = data.CpuCfsPeriod;
  43. result.cpuCfsQuota = data.CpuCfsQuota;
  44. result.cpuShares = data.CPUShares;
  45. result.cpuSet = data.CPUSet;
  46. result.ipv4Forwarding = data.IPv4Forwarding;
  47. result.bridgeNfIptables = data.BridgeNfIptables;
  48. result.bridgeNfIp6tables = data.BridgeNfIp6tables;
  49. result.debug = data.Debug;
  50. result.nfd = data.NFd;
  51. result.oomKillDisable = data.OomKillDisable;
  52. result.ngoroutines = data.NGoroutines;
  53. result.systemTime = data.SystemTime;
  54. result.loggingDriver = data.LoggingDriver;
  55. result.cgroupDriver = data.CgroupDriver;
  56. result.nEventsListener = data.NEventsListener;
  57. result.kernelVersion = data.KernelVersion;
  58. result.operatingSystem = data.OperatingSystem;
  59. result.osType = data.OSType;
  60. result.architecture = data.Architecture;
  61. result.ncpu = data.NCPU;
  62. result.memTotal = data.MemTotal;
  63. result.dockerRootDir = data.DockerRootDir;
  64. result.httpProxy = data.HttpProxy;
  65. result.httpsProxy = data.HttpsProxy;
  66. result.noProxy = data.NoProxy;
  67. result.name = data.Name;
  68. result.labels = data.Labels;
  69. result.experimentalBuild = data.ExperimentalBuild;
  70. result.serverVersion = data.ServerVersion;
  71. result.clusterStore = data.ClusterStore;
  72. result.clusterAdvertise = data.ClusterAdvertise;
  73. result.defaultRuntime = data.DefaultRuntime;
  74. result.liveRestoreEnabled = data.LiveRestoreEnabled;
  75. result.isolation = data.Isolation;
  76. result.initBinary = data.InitBinary;
  77. result.productLicense = data.ProductLicense;
  78. if (callback) { callback(result); }
  79. resolve(result);
  80. });
  81. });
  82. });
  83. }
  84. exports.dockerInfo = dockerInfo;
  85. function dockerImages(all, callback) {
  86. // fallback - if only callback is given
  87. if (util.isFunction(all) && !callback) {
  88. callback = all;
  89. all = false;
  90. }
  91. if (typeof all === 'string' && all === 'true') {
  92. all = true;
  93. }
  94. if (typeof all !== 'boolean' && all !== undefined) {
  95. all = false;
  96. }
  97. all = all || false;
  98. let result = [];
  99. return new Promise((resolve) => {
  100. process.nextTick(() => {
  101. if (!_docker_socket) {
  102. _docker_socket = new DockerSocket();
  103. }
  104. const workload = [];
  105. _docker_socket.listImages(all, data => {
  106. let dockerImages = {};
  107. try {
  108. dockerImages = data;
  109. if (dockerImages && Object.prototype.toString.call(dockerImages) === '[object Array]' && dockerImages.length > 0) {
  110. dockerImages.forEach(function (element) {
  111. if (element.Names && Object.prototype.toString.call(element.Names) === '[object Array]' && element.Names.length > 0) {
  112. element.Name = element.Names[0].replace(/^\/|\/$/g, '');
  113. }
  114. workload.push(dockerImagesInspect(element.Id.trim(), element));
  115. });
  116. if (workload.length) {
  117. Promise.all(
  118. workload
  119. ).then(data => {
  120. if (callback) { callback(data); }
  121. resolve(data);
  122. });
  123. } else {
  124. if (callback) { callback(result); }
  125. resolve(result);
  126. }
  127. } else {
  128. if (callback) { callback(result); }
  129. resolve(result);
  130. }
  131. } catch (err) {
  132. if (callback) { callback(result); }
  133. resolve(result);
  134. }
  135. });
  136. });
  137. });
  138. }
  139. // --------------------------
  140. // container inspect (for one container)
  141. function dockerImagesInspect(imageID, payload) {
  142. return new Promise((resolve) => {
  143. process.nextTick(() => {
  144. imageID = imageID || '';
  145. if (typeof imageID !== 'string') {
  146. return resolve();
  147. }
  148. const imageIDSanitized = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(imageID, true)).trim();
  149. if (imageIDSanitized) {
  150. if (!_docker_socket) {
  151. _docker_socket = new DockerSocket();
  152. }
  153. _docker_socket.inspectImage(imageIDSanitized.trim(), data => {
  154. try {
  155. resolve({
  156. id: payload.Id,
  157. container: data.Container,
  158. comment: data.Comment,
  159. os: data.Os,
  160. architecture: data.Architecture,
  161. parent: data.Parent,
  162. dockerVersion: data.DockerVersion,
  163. size: data.Size,
  164. sharedSize: payload.SharedSize,
  165. virtualSize: data.VirtualSize,
  166. author: data.Author,
  167. created: data.Created ? Math.round(new Date(data.Created).getTime() / 1000) : 0,
  168. containerConfig: data.ContainerConfig ? data.ContainerConfig : {},
  169. graphDriver: data.GraphDriver ? data.GraphDriver : {},
  170. repoDigests: data.RepoDigests ? data.RepoDigests : {},
  171. repoTags: data.RepoTags ? data.RepoTags : {},
  172. config: data.Config ? data.Config : {},
  173. rootFS: data.RootFS ? data.RootFS : {},
  174. });
  175. } catch (err) {
  176. resolve();
  177. }
  178. });
  179. } else {
  180. resolve();
  181. }
  182. });
  183. });
  184. }
  185. exports.dockerImages = dockerImages;
  186. function dockerContainers(all, callback) {
  187. function inContainers(containers, id) {
  188. let filtered = containers.filter(obj => {
  189. /**
  190. * @namespace
  191. * @property {string} Id
  192. */
  193. return (obj.Id && (obj.Id === id));
  194. });
  195. return (filtered.length > 0);
  196. }
  197. // fallback - if only callback is given
  198. if (util.isFunction(all) && !callback) {
  199. callback = all;
  200. all = false;
  201. }
  202. if (typeof all === 'string' && all === 'true') {
  203. all = true;
  204. }
  205. if (typeof all !== 'boolean' && all !== undefined) {
  206. all = false;
  207. }
  208. all = all || false;
  209. let result = [];
  210. return new Promise((resolve) => {
  211. process.nextTick(() => {
  212. if (!_docker_socket) {
  213. _docker_socket = new DockerSocket();
  214. }
  215. const workload = [];
  216. _docker_socket.listContainers(all, data => {
  217. let docker_containers = {};
  218. try {
  219. docker_containers = data;
  220. if (docker_containers && Object.prototype.toString.call(docker_containers) === '[object Array]' && docker_containers.length > 0) {
  221. // GC in _docker_container_stats
  222. for (let key in _docker_container_stats) {
  223. if ({}.hasOwnProperty.call(_docker_container_stats, key)) {
  224. if (!inContainers(docker_containers, key)) { delete _docker_container_stats[key]; }
  225. }
  226. }
  227. docker_containers.forEach(function (element) {
  228. if (element.Names && Object.prototype.toString.call(element.Names) === '[object Array]' && element.Names.length > 0) {
  229. element.Name = element.Names[0].replace(/^\/|\/$/g, '');
  230. }
  231. workload.push(dockerContainerInspect(element.Id.trim(), element));
  232. // result.push({
  233. // id: element.Id,
  234. // name: element.Name,
  235. // image: element.Image,
  236. // imageID: element.ImageID,
  237. // command: element.Command,
  238. // created: element.Created,
  239. // state: element.State,
  240. // ports: element.Ports,
  241. // mounts: element.Mounts,
  242. // // hostconfig: element.HostConfig,
  243. // // network: element.NetworkSettings
  244. // });
  245. });
  246. if (workload.length) {
  247. Promise.all(
  248. workload
  249. ).then(data => {
  250. if (callback) { callback(data); }
  251. resolve(data);
  252. });
  253. } else {
  254. if (callback) { callback(result); }
  255. resolve(result);
  256. }
  257. } else {
  258. if (callback) { callback(result); }
  259. resolve(result);
  260. }
  261. } catch (err) {
  262. // GC in _docker_container_stats
  263. for (let key in _docker_container_stats) {
  264. if ({}.hasOwnProperty.call(_docker_container_stats, key)) {
  265. if (!inContainers(docker_containers, key)) { delete _docker_container_stats[key]; }
  266. }
  267. }
  268. if (callback) { callback(result); }
  269. resolve(result);
  270. }
  271. });
  272. });
  273. });
  274. }
  275. // --------------------------
  276. // container inspect (for one container)
  277. function dockerContainerInspect(containerID, payload) {
  278. return new Promise((resolve) => {
  279. process.nextTick(() => {
  280. containerID = containerID || '';
  281. if (typeof containerID !== 'string') {
  282. return resolve();
  283. }
  284. const containerIdSanitized = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(containerID, true)).trim();
  285. if (containerIdSanitized) {
  286. if (!_docker_socket) {
  287. _docker_socket = new DockerSocket();
  288. }
  289. _docker_socket.getInspect(containerIdSanitized.trim(), data => {
  290. try {
  291. resolve({
  292. id: payload.Id,
  293. name: payload.Name,
  294. image: payload.Image,
  295. imageID: payload.ImageID,
  296. command: payload.Command,
  297. created: payload.Created,
  298. started: data.State && data.State.StartedAt ? Math.round(new Date(data.State.StartedAt).getTime() / 1000) : 0,
  299. finished: data.State && data.State.FinishedAt && !data.State.FinishedAt.startsWith('0001-01-01') ? Math.round(new Date(data.State.FinishedAt).getTime() / 1000) : 0,
  300. createdAt: data.Created ? data.Created : '',
  301. startedAt: data.State && data.State.StartedAt ? data.State.StartedAt : '',
  302. finishedAt: data.State && data.State.FinishedAt && !data.State.FinishedAt.startsWith('0001-01-01') ? data.State.FinishedAt : '',
  303. state: payload.State,
  304. restartCount: data.RestartCount || 0,
  305. platform: data.Platform || '',
  306. driver: data.Driver || '',
  307. ports: payload.Ports,
  308. mounts: payload.Mounts,
  309. // hostconfig: payload.HostConfig,
  310. // network: payload.NetworkSettings
  311. });
  312. } catch (err) {
  313. resolve();
  314. }
  315. });
  316. } else {
  317. resolve();
  318. }
  319. });
  320. });
  321. }
  322. exports.dockerContainers = dockerContainers;
  323. // --------------------------
  324. // helper functions for calculation of docker stats
  325. function docker_calcCPUPercent(cpu_stats, precpu_stats) {
  326. /**
  327. * @namespace
  328. * @property {object} cpu_usage
  329. * @property {number} cpu_usage.total_usage
  330. * @property {number} system_cpu_usage
  331. * @property {object} cpu_usage
  332. * @property {Array} cpu_usage.percpu_usage
  333. */
  334. if (!_windows) {
  335. let cpuPercent = 0.0;
  336. // calculate the change for the cpu usage of the container in between readings
  337. let cpuDelta = cpu_stats.cpu_usage.total_usage - precpu_stats.cpu_usage.total_usage;
  338. // calculate the change for the entire system between readings
  339. let systemDelta = cpu_stats.system_cpu_usage - precpu_stats.system_cpu_usage;
  340. if (systemDelta > 0.0 && cpuDelta > 0.0) {
  341. // calculate the change for the cpu usage of the container in between readings
  342. cpuPercent = (cpuDelta / systemDelta) * cpu_stats.cpu_usage.percpu_usage.length * 100.0;
  343. }
  344. return cpuPercent;
  345. } else {
  346. let nanoSecNow = util.nanoSeconds();
  347. let cpuPercent = 0.0;
  348. if (_docker_last_read > 0) {
  349. let possIntervals = (nanoSecNow - _docker_last_read); // / 100 * os.cpus().length;
  350. let intervalsUsed = cpu_stats.cpu_usage.total_usage - precpu_stats.cpu_usage.total_usage;
  351. if (possIntervals > 0) {
  352. cpuPercent = 100.0 * intervalsUsed / possIntervals;
  353. }
  354. }
  355. _docker_last_read = nanoSecNow;
  356. return cpuPercent;
  357. }
  358. }
  359. function docker_calcNetworkIO(networks) {
  360. let rx;
  361. let wx;
  362. for (let key in networks) {
  363. // skip loop if the property is from prototype
  364. if (!{}.hasOwnProperty.call(networks, key)) { continue; }
  365. /**
  366. * @namespace
  367. * @property {number} rx_bytes
  368. * @property {number} tx_bytes
  369. */
  370. let obj = networks[key];
  371. rx = +obj.rx_bytes;
  372. wx = +obj.tx_bytes;
  373. }
  374. return {
  375. rx,
  376. wx
  377. };
  378. }
  379. function docker_calcBlockIO(blkio_stats) {
  380. let result = {
  381. r: 0,
  382. w: 0
  383. };
  384. /**
  385. * @namespace
  386. * @property {Array} io_service_bytes_recursive
  387. */
  388. if (blkio_stats && blkio_stats.io_service_bytes_recursive && Object.prototype.toString.call(blkio_stats.io_service_bytes_recursive) === '[object Array]' && blkio_stats.io_service_bytes_recursive.length > 0) {
  389. blkio_stats.io_service_bytes_recursive.forEach(function (element) {
  390. /**
  391. * @namespace
  392. * @property {string} op
  393. * @property {number} value
  394. */
  395. if (element.op && element.op.toLowerCase() === 'read' && element.value) {
  396. result.r += element.value;
  397. }
  398. if (element.op && element.op.toLowerCase() === 'write' && element.value) {
  399. result.w += element.value;
  400. }
  401. });
  402. }
  403. return result;
  404. }
  405. function dockerContainerStats(containerIDs, callback) {
  406. let containerArray = [];
  407. return new Promise((resolve) => {
  408. process.nextTick(() => {
  409. // fallback - if only callback is given
  410. if (util.isFunction(containerIDs) && !callback) {
  411. callback = containerIDs;
  412. containerArray = ['*'];
  413. } else {
  414. containerIDs = containerIDs || '*';
  415. if (typeof containerIDs !== 'string') {
  416. if (callback) { callback([]); }
  417. return resolve([]);
  418. }
  419. let containerIDsSanitized = '';
  420. containerIDsSanitized.__proto__.toLowerCase = util.stringToLower;
  421. containerIDsSanitized.__proto__.replace = util.stringReplace;
  422. containerIDsSanitized.__proto__.trim = util.stringTrim;
  423. containerIDsSanitized = containerIDs;
  424. containerIDsSanitized = containerIDsSanitized.trim();
  425. if (containerIDsSanitized !== '*') {
  426. containerIDsSanitized = '';
  427. const s = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(containerIDs, true)).trim();
  428. for (let i = 0; i <= util.mathMin(s.length, 2000); i++) {
  429. if (!(s[i] === undefined)) {
  430. s[i].__proto__.toLowerCase = util.stringToLower;
  431. const sl = s[i].toLowerCase();
  432. if (sl && sl[0] && !sl[1]) {
  433. containerIDsSanitized = containerIDsSanitized + sl[0];
  434. }
  435. }
  436. }
  437. }
  438. containerIDsSanitized = containerIDsSanitized.trim().toLowerCase().replace(/,+/g, '|');
  439. containerArray = containerIDsSanitized.split('|');
  440. }
  441. const result = [];
  442. const workload = [];
  443. if (containerArray.length && containerArray[0].trim() === '*') {
  444. containerArray = [];
  445. dockerContainers().then(allContainers => {
  446. for (let container of allContainers) {
  447. containerArray.push(container.id);
  448. }
  449. if (containerArray.length) {
  450. dockerContainerStats(containerArray.join(',')).then(result => {
  451. if (callback) { callback(result); }
  452. resolve(result);
  453. });
  454. } else {
  455. if (callback) { callback(result); }
  456. resolve(result);
  457. }
  458. });
  459. } else {
  460. for (let containerID of containerArray) {
  461. workload.push(dockerContainerStatsSingle(containerID.trim()));
  462. }
  463. if (workload.length) {
  464. Promise.all(
  465. workload
  466. ).then(data => {
  467. if (callback) { callback(data); }
  468. resolve(data);
  469. });
  470. } else {
  471. if (callback) { callback(result); }
  472. resolve(result);
  473. }
  474. }
  475. });
  476. });
  477. }
  478. // --------------------------
  479. // container stats (for one container)
  480. function dockerContainerStatsSingle(containerID) {
  481. containerID = containerID || '';
  482. let result = {
  483. id: containerID,
  484. memUsage: 0,
  485. memLimit: 0,
  486. memPercent: 0,
  487. cpuPercent: 0,
  488. pids: 0,
  489. netIO: {
  490. rx: 0,
  491. wx: 0
  492. },
  493. blockIO: {
  494. r: 0,
  495. w: 0
  496. },
  497. restartCount: 0,
  498. cpuStats: {},
  499. precpuStats: {},
  500. memoryStats: {},
  501. networks: {},
  502. };
  503. return new Promise((resolve) => {
  504. process.nextTick(() => {
  505. if (containerID) {
  506. if (!_docker_socket) {
  507. _docker_socket = new DockerSocket();
  508. }
  509. _docker_socket.getInspect(containerID, dataInspect => {
  510. try {
  511. _docker_socket.getStats(containerID, data => {
  512. try {
  513. let stats = data;
  514. if (!stats.message) {
  515. result.memUsage = (stats.memory_stats && stats.memory_stats.usage ? stats.memory_stats.usage : 0);
  516. result.memLimit = (stats.memory_stats && stats.memory_stats.limit ? stats.memory_stats.limit : 0);
  517. result.memPercent = (stats.memory_stats && stats.memory_stats.usage && stats.memory_stats.limit ? stats.memory_stats.usage / stats.memory_stats.limit * 100.0 : 0);
  518. result.cpuPercent = (stats.cpu_stats && stats.precpu_stats ? docker_calcCPUPercent(stats.cpu_stats, stats.precpu_stats) : 0);
  519. result.pids = (stats.pids_stats && stats.pids_stats.current ? stats.pids_stats.current : 0);
  520. result.restartCount = (dataInspect.RestartCount ? dataInspect.RestartCount : 0);
  521. if (stats.networks) { result.netIO = docker_calcNetworkIO(stats.networks); }
  522. if (stats.blkio_stats) { result.blockIO = docker_calcBlockIO(stats.blkio_stats); }
  523. result.cpuStats = (stats.cpu_stats ? stats.cpu_stats : {});
  524. result.precpuStats = (stats.precpu_stats ? stats.precpu_stats : {});
  525. result.memoryStats = (stats.memory_stats ? stats.memory_stats : {});
  526. result.networks = (stats.networks ? stats.networks : {});
  527. }
  528. } catch (err) {
  529. util.noop();
  530. }
  531. // }
  532. resolve(result);
  533. });
  534. } catch (err) {
  535. util.noop();
  536. }
  537. });
  538. } else {
  539. resolve(result);
  540. }
  541. });
  542. });
  543. }
  544. exports.dockerContainerStats = dockerContainerStats;
  545. // --------------------------
  546. // container processes (for one container)
  547. function dockerContainerProcesses(containerID, callback) {
  548. let result = [];
  549. return new Promise((resolve) => {
  550. process.nextTick(() => {
  551. containerID = containerID || '';
  552. if (typeof containerID !== 'string') {
  553. return resolve(result);
  554. }
  555. const containerIdSanitized = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(containerID, true)).trim();
  556. if (containerIdSanitized) {
  557. if (!_docker_socket) {
  558. _docker_socket = new DockerSocket();
  559. }
  560. _docker_socket.getProcesses(containerIdSanitized, data => {
  561. /**
  562. * @namespace
  563. * @property {Array} Titles
  564. * @property {Array} Processes
  565. **/
  566. try {
  567. if (data && data.Titles && data.Processes) {
  568. let titles = data.Titles.map(function (value) {
  569. return value.toUpperCase();
  570. });
  571. let pos_pid = titles.indexOf('PID');
  572. let pos_ppid = titles.indexOf('PPID');
  573. let pos_pgid = titles.indexOf('PGID');
  574. let pos_vsz = titles.indexOf('VSZ');
  575. let pos_time = titles.indexOf('TIME');
  576. let pos_elapsed = titles.indexOf('ELAPSED');
  577. let pos_ni = titles.indexOf('NI');
  578. let pos_ruser = titles.indexOf('RUSER');
  579. let pos_user = titles.indexOf('USER');
  580. let pos_rgroup = titles.indexOf('RGROUP');
  581. let pos_group = titles.indexOf('GROUP');
  582. let pos_stat = titles.indexOf('STAT');
  583. let pos_rss = titles.indexOf('RSS');
  584. let pos_command = titles.indexOf('COMMAND');
  585. data.Processes.forEach(process => {
  586. result.push({
  587. pidHost: (pos_pid >= 0 ? process[pos_pid] : ''),
  588. ppid: (pos_ppid >= 0 ? process[pos_ppid] : ''),
  589. pgid: (pos_pgid >= 0 ? process[pos_pgid] : ''),
  590. user: (pos_user >= 0 ? process[pos_user] : ''),
  591. ruser: (pos_ruser >= 0 ? process[pos_ruser] : ''),
  592. group: (pos_group >= 0 ? process[pos_group] : ''),
  593. rgroup: (pos_rgroup >= 0 ? process[pos_rgroup] : ''),
  594. stat: (pos_stat >= 0 ? process[pos_stat] : ''),
  595. time: (pos_time >= 0 ? process[pos_time] : ''),
  596. elapsed: (pos_elapsed >= 0 ? process[pos_elapsed] : ''),
  597. nice: (pos_ni >= 0 ? process[pos_ni] : ''),
  598. rss: (pos_rss >= 0 ? process[pos_rss] : ''),
  599. vsz: (pos_vsz >= 0 ? process[pos_vsz] : ''),
  600. command: (pos_command >= 0 ? process[pos_command] : '')
  601. });
  602. });
  603. }
  604. } catch (err) {
  605. util.noop();
  606. }
  607. if (callback) { callback(result); }
  608. resolve(result);
  609. });
  610. } else {
  611. if (callback) { callback(result); }
  612. resolve(result);
  613. }
  614. });
  615. });
  616. }
  617. exports.dockerContainerProcesses = dockerContainerProcesses;
  618. function dockerVolumes(callback) {
  619. let result = [];
  620. return new Promise((resolve) => {
  621. process.nextTick(() => {
  622. if (!_docker_socket) {
  623. _docker_socket = new DockerSocket();
  624. }
  625. _docker_socket.listVolumes(data => {
  626. let dockerVolumes = {};
  627. try {
  628. dockerVolumes = data;
  629. if (dockerVolumes && dockerVolumes.Volumes && Object.prototype.toString.call(dockerVolumes.Volumes) === '[object Array]' && dockerVolumes.Volumes.length > 0) {
  630. dockerVolumes.Volumes.forEach(function (element) {
  631. result.push({
  632. name: element.Name,
  633. driver: element.Driver,
  634. labels: element.Labels,
  635. mountpoint: element.Mountpoint,
  636. options: element.Options,
  637. scope: element.Scope,
  638. created: element.CreatedAt ? Math.round(new Date(element.CreatedAt).getTime() / 1000) : 0,
  639. });
  640. });
  641. if (callback) { callback(result); }
  642. resolve(result);
  643. } else {
  644. if (callback) { callback(result); }
  645. resolve(result);
  646. }
  647. } catch (err) {
  648. if (callback) { callback(result); }
  649. resolve(result);
  650. }
  651. });
  652. });
  653. });
  654. }
  655. exports.dockerVolumes = dockerVolumes;
  656. function dockerAll(callback) {
  657. return new Promise((resolve) => {
  658. process.nextTick(() => {
  659. dockerContainers(true).then(result => {
  660. if (result && Object.prototype.toString.call(result) === '[object Array]' && result.length > 0) {
  661. let l = result.length;
  662. result.forEach(function (element) {
  663. dockerContainerStats(element.id).then(res => {
  664. // include stats in array
  665. element.memUsage = res[0].memUsage;
  666. element.memLimit = res[0].memLimit;
  667. element.memPercent = res[0].memPercent;
  668. element.cpuPercent = res[0].cpuPercent;
  669. element.pids = res[0].pids;
  670. element.netIO = res[0].netIO;
  671. element.blockIO = res[0].blockIO;
  672. element.cpuStats = res[0].cpuStats;
  673. element.precpuStats = res[0].precpuStats;
  674. element.memoryStats = res[0].memoryStats;
  675. element.networks = res[0].networks;
  676. dockerContainerProcesses(element.id).then(processes => {
  677. element.processes = processes;
  678. l -= 1;
  679. if (l === 0) {
  680. if (callback) { callback(result); }
  681. resolve(result);
  682. }
  683. });
  684. // all done??
  685. });
  686. });
  687. } else {
  688. if (callback) { callback(result); }
  689. resolve(result);
  690. }
  691. });
  692. });
  693. });
  694. }
  695. exports.dockerAll = dockerAll;