@sonde/packs 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (377) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/.turbo/turbo-test.log +53 -0
  3. package/.turbo/turbo-typecheck.log +4 -0
  4. package/CHANGELOG.md +19 -0
  5. package/dist/index.d.ts +16 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +40 -2
  8. package/dist/index.js.map +1 -1
  9. package/dist/integrations/citrix.d.ts +13 -0
  10. package/dist/integrations/citrix.d.ts.map +1 -0
  11. package/dist/integrations/citrix.js +415 -0
  12. package/dist/integrations/citrix.js.map +1 -0
  13. package/dist/integrations/citrix.test.d.ts +2 -0
  14. package/dist/integrations/citrix.test.d.ts.map +1 -0
  15. package/dist/integrations/citrix.test.js +464 -0
  16. package/dist/integrations/citrix.test.js.map +1 -0
  17. package/dist/integrations/graph.d.ts +9 -0
  18. package/dist/integrations/graph.d.ts.map +1 -0
  19. package/dist/integrations/graph.js +285 -0
  20. package/dist/integrations/graph.js.map +1 -0
  21. package/dist/integrations/graph.test.d.ts +2 -0
  22. package/dist/integrations/graph.test.d.ts.map +1 -0
  23. package/dist/integrations/graph.test.js +356 -0
  24. package/dist/integrations/graph.test.js.map +1 -0
  25. package/dist/integrations/httpbin.d.ts +3 -0
  26. package/dist/integrations/httpbin.d.ts.map +1 -0
  27. package/dist/integrations/httpbin.js +65 -0
  28. package/dist/integrations/httpbin.js.map +1 -0
  29. package/dist/integrations/nutanix.d.ts +18 -0
  30. package/dist/integrations/nutanix.d.ts.map +1 -0
  31. package/dist/integrations/nutanix.js +1116 -0
  32. package/dist/integrations/nutanix.js.map +1 -0
  33. package/dist/integrations/nutanix.test.d.ts +2 -0
  34. package/dist/integrations/nutanix.test.d.ts.map +1 -0
  35. package/dist/integrations/nutanix.test.js +978 -0
  36. package/dist/integrations/nutanix.test.js.map +1 -0
  37. package/dist/integrations/proxmox.d.ts +12 -0
  38. package/dist/integrations/proxmox.d.ts.map +1 -0
  39. package/dist/integrations/proxmox.js +728 -0
  40. package/dist/integrations/proxmox.js.map +1 -0
  41. package/dist/integrations/proxmox.test.d.ts +2 -0
  42. package/dist/integrations/proxmox.test.d.ts.map +1 -0
  43. package/dist/integrations/proxmox.test.js +697 -0
  44. package/dist/integrations/proxmox.test.js.map +1 -0
  45. package/dist/integrations/servicenow.d.ts +3 -0
  46. package/dist/integrations/servicenow.d.ts.map +1 -0
  47. package/dist/integrations/servicenow.js +251 -0
  48. package/dist/integrations/servicenow.js.map +1 -0
  49. package/dist/integrations/servicenow.test.d.ts +2 -0
  50. package/dist/integrations/servicenow.test.d.ts.map +1 -0
  51. package/dist/integrations/servicenow.test.js +217 -0
  52. package/dist/integrations/servicenow.test.js.map +1 -0
  53. package/dist/integrations/splunk.d.ts +9 -0
  54. package/dist/integrations/splunk.d.ts.map +1 -0
  55. package/dist/integrations/splunk.js +237 -0
  56. package/dist/integrations/splunk.js.map +1 -0
  57. package/dist/integrations/splunk.test.d.ts +2 -0
  58. package/dist/integrations/splunk.test.d.ts.map +1 -0
  59. package/dist/integrations/splunk.test.js +323 -0
  60. package/dist/integrations/splunk.test.js.map +1 -0
  61. package/dist/mysql/index.d.ts +3 -0
  62. package/dist/mysql/index.d.ts.map +1 -0
  63. package/dist/mysql/index.js +13 -0
  64. package/dist/mysql/index.js.map +1 -0
  65. package/dist/mysql/manifest.d.ts +3 -0
  66. package/dist/mysql/manifest.d.ts.map +1 -0
  67. package/dist/mysql/manifest.js +69 -0
  68. package/dist/mysql/manifest.js.map +1 -0
  69. package/dist/mysql/probes/databases-list.d.ts +13 -0
  70. package/dist/mysql/probes/databases-list.d.ts.map +1 -0
  71. package/dist/mysql/probes/databases-list.js +31 -0
  72. package/dist/mysql/probes/databases-list.js.map +1 -0
  73. package/dist/mysql/probes/databases-list.test.d.ts +2 -0
  74. package/dist/mysql/probes/databases-list.test.d.ts.map +1 -0
  75. package/dist/mysql/probes/databases-list.test.js +54 -0
  76. package/dist/mysql/probes/databases-list.test.js.map +1 -0
  77. package/dist/mysql/probes/processlist.d.ts +18 -0
  78. package/dist/mysql/probes/processlist.d.ts.map +1 -0
  79. package/dist/mysql/probes/processlist.js +36 -0
  80. package/dist/mysql/probes/processlist.js.map +1 -0
  81. package/dist/mysql/probes/processlist.test.d.ts +2 -0
  82. package/dist/mysql/probes/processlist.test.d.ts.map +1 -0
  83. package/dist/mysql/probes/processlist.test.js +41 -0
  84. package/dist/mysql/probes/processlist.test.js.map +1 -0
  85. package/dist/mysql/probes/status.d.ts +14 -0
  86. package/dist/mysql/probes/status.d.ts.map +1 -0
  87. package/dist/mysql/probes/status.js +40 -0
  88. package/dist/mysql/probes/status.js.map +1 -0
  89. package/dist/mysql/probes/status.test.d.ts +2 -0
  90. package/dist/mysql/probes/status.test.d.ts.map +1 -0
  91. package/dist/mysql/probes/status.test.js +43 -0
  92. package/dist/mysql/probes/status.test.js.map +1 -0
  93. package/dist/nginx/index.d.ts +3 -0
  94. package/dist/nginx/index.d.ts.map +1 -0
  95. package/dist/nginx/index.js +13 -0
  96. package/dist/nginx/index.js.map +1 -0
  97. package/dist/nginx/manifest.d.ts +3 -0
  98. package/dist/nginx/manifest.d.ts.map +1 -0
  99. package/dist/nginx/manifest.js +68 -0
  100. package/dist/nginx/manifest.js.map +1 -0
  101. package/dist/nginx/probes/access-log-tail.d.ts +9 -0
  102. package/dist/nginx/probes/access-log-tail.d.ts.map +1 -0
  103. package/dist/nginx/probes/access-log-tail.js +14 -0
  104. package/dist/nginx/probes/access-log-tail.js.map +1 -0
  105. package/dist/nginx/probes/access-log-tail.test.d.ts +2 -0
  106. package/dist/nginx/probes/access-log-tail.test.d.ts.map +1 -0
  107. package/dist/nginx/probes/access-log-tail.test.js +40 -0
  108. package/dist/nginx/probes/access-log-tail.test.js.map +1 -0
  109. package/dist/nginx/probes/config-test.d.ts +8 -0
  110. package/dist/nginx/probes/config-test.d.ts.map +1 -0
  111. package/dist/nginx/probes/config-test.js +18 -0
  112. package/dist/nginx/probes/config-test.js.map +1 -0
  113. package/dist/nginx/probes/config-test.test.d.ts +2 -0
  114. package/dist/nginx/probes/config-test.test.d.ts.map +1 -0
  115. package/dist/nginx/probes/config-test.test.js +35 -0
  116. package/dist/nginx/probes/config-test.test.js.map +1 -0
  117. package/dist/nginx/probes/error-log-tail.d.ts +9 -0
  118. package/dist/nginx/probes/error-log-tail.d.ts.map +1 -0
  119. package/dist/nginx/probes/error-log-tail.js +14 -0
  120. package/dist/nginx/probes/error-log-tail.js.map +1 -0
  121. package/dist/nginx/probes/error-log-tail.test.d.ts +2 -0
  122. package/dist/nginx/probes/error-log-tail.test.d.ts.map +1 -0
  123. package/dist/nginx/probes/error-log-tail.test.js +34 -0
  124. package/dist/nginx/probes/error-log-tail.test.js.map +1 -0
  125. package/dist/postgres/index.d.ts +3 -0
  126. package/dist/postgres/index.d.ts.map +1 -0
  127. package/dist/postgres/index.js +13 -0
  128. package/dist/postgres/index.js.map +1 -0
  129. package/dist/postgres/manifest.d.ts +3 -0
  130. package/dist/postgres/manifest.d.ts.map +1 -0
  131. package/dist/postgres/manifest.js +90 -0
  132. package/dist/postgres/manifest.js.map +1 -0
  133. package/dist/postgres/probes/connections-active.d.ts +17 -0
  134. package/dist/postgres/probes/connections-active.d.ts.map +1 -0
  135. package/dist/postgres/probes/connections-active.js +37 -0
  136. package/dist/postgres/probes/connections-active.js.map +1 -0
  137. package/dist/postgres/probes/connections-active.test.d.ts +2 -0
  138. package/dist/postgres/probes/connections-active.test.d.ts.map +1 -0
  139. package/dist/postgres/probes/connections-active.test.js +36 -0
  140. package/dist/postgres/probes/connections-active.test.js.map +1 -0
  141. package/dist/postgres/probes/databases-list.d.ts +14 -0
  142. package/dist/postgres/probes/databases-list.d.ts.map +1 -0
  143. package/dist/postgres/probes/databases-list.js +34 -0
  144. package/dist/postgres/probes/databases-list.js.map +1 -0
  145. package/dist/postgres/probes/databases-list.test.d.ts +2 -0
  146. package/dist/postgres/probes/databases-list.test.d.ts.map +1 -0
  147. package/dist/postgres/probes/databases-list.test.js +49 -0
  148. package/dist/postgres/probes/databases-list.test.js.map +1 -0
  149. package/dist/postgres/probes/query-slow.d.ts +17 -0
  150. package/dist/postgres/probes/query-slow.d.ts.map +1 -0
  151. package/dist/postgres/probes/query-slow.js +37 -0
  152. package/dist/postgres/probes/query-slow.js.map +1 -0
  153. package/dist/postgres/probes/query-slow.test.d.ts +2 -0
  154. package/dist/postgres/probes/query-slow.test.d.ts.map +1 -0
  155. package/dist/postgres/probes/query-slow.test.js +30 -0
  156. package/dist/postgres/probes/query-slow.test.js.map +1 -0
  157. package/dist/proxmox/index.d.ts +3 -0
  158. package/dist/proxmox/index.d.ts.map +1 -0
  159. package/dist/proxmox/index.js +23 -0
  160. package/dist/proxmox/index.js.map +1 -0
  161. package/dist/proxmox/manifest.d.ts +3 -0
  162. package/dist/proxmox/manifest.d.ts.map +1 -0
  163. package/dist/proxmox/manifest.js +75 -0
  164. package/dist/proxmox/manifest.js.map +1 -0
  165. package/dist/proxmox/probes/ceph-status.d.ts +36 -0
  166. package/dist/proxmox/probes/ceph-status.d.ts.map +1 -0
  167. package/dist/proxmox/probes/ceph-status.js +71 -0
  168. package/dist/proxmox/probes/ceph-status.js.map +1 -0
  169. package/dist/proxmox/probes/ceph-status.test.d.ts +2 -0
  170. package/dist/proxmox/probes/ceph-status.test.d.ts.map +1 -0
  171. package/dist/proxmox/probes/ceph-status.test.js +115 -0
  172. package/dist/proxmox/probes/ceph-status.test.js.map +1 -0
  173. package/dist/proxmox/probes/cluster-config.d.ts +31 -0
  174. package/dist/proxmox/probes/cluster-config.d.ts.map +1 -0
  175. package/dist/proxmox/probes/cluster-config.js +72 -0
  176. package/dist/proxmox/probes/cluster-config.js.map +1 -0
  177. package/dist/proxmox/probes/cluster-config.test.d.ts +2 -0
  178. package/dist/proxmox/probes/cluster-config.test.d.ts.map +1 -0
  179. package/dist/proxmox/probes/cluster-config.test.js +107 -0
  180. package/dist/proxmox/probes/cluster-config.test.js.map +1 -0
  181. package/dist/proxmox/probes/ha-status.d.ts +18 -0
  182. package/dist/proxmox/probes/ha-status.d.ts.map +1 -0
  183. package/dist/proxmox/probes/ha-status.js +38 -0
  184. package/dist/proxmox/probes/ha-status.js.map +1 -0
  185. package/dist/proxmox/probes/ha-status.test.d.ts +2 -0
  186. package/dist/proxmox/probes/ha-status.test.d.ts.map +1 -0
  187. package/dist/proxmox/probes/ha-status.test.js +66 -0
  188. package/dist/proxmox/probes/ha-status.test.js.map +1 -0
  189. package/dist/proxmox/probes/lvm.d.ts +35 -0
  190. package/dist/proxmox/probes/lvm.d.ts.map +1 -0
  191. package/dist/proxmox/probes/lvm.js +75 -0
  192. package/dist/proxmox/probes/lvm.js.map +1 -0
  193. package/dist/proxmox/probes/lvm.test.d.ts +2 -0
  194. package/dist/proxmox/probes/lvm.test.d.ts.map +1 -0
  195. package/dist/proxmox/probes/lvm.test.js +128 -0
  196. package/dist/proxmox/probes/lvm.test.js.map +1 -0
  197. package/dist/proxmox/probes/lxc-config.d.ts +29 -0
  198. package/dist/proxmox/probes/lxc-config.d.ts.map +1 -0
  199. package/dist/proxmox/probes/lxc-config.js +67 -0
  200. package/dist/proxmox/probes/lxc-config.js.map +1 -0
  201. package/dist/proxmox/probes/lxc-config.test.d.ts +2 -0
  202. package/dist/proxmox/probes/lxc-config.test.d.ts.map +1 -0
  203. package/dist/proxmox/probes/lxc-config.test.js +77 -0
  204. package/dist/proxmox/probes/lxc-config.test.js.map +1 -0
  205. package/dist/proxmox/probes/lxc-list.d.ts +20 -0
  206. package/dist/proxmox/probes/lxc-list.d.ts.map +1 -0
  207. package/dist/proxmox/probes/lxc-list.js +49 -0
  208. package/dist/proxmox/probes/lxc-list.js.map +1 -0
  209. package/dist/proxmox/probes/lxc-list.test.d.ts +2 -0
  210. package/dist/proxmox/probes/lxc-list.test.d.ts.map +1 -0
  211. package/dist/proxmox/probes/lxc-list.test.js +51 -0
  212. package/dist/proxmox/probes/lxc-list.test.js.map +1 -0
  213. package/dist/proxmox/probes/vm-config.d.ts +21 -0
  214. package/dist/proxmox/probes/vm-config.d.ts.map +1 -0
  215. package/dist/proxmox/probes/vm-config.js +58 -0
  216. package/dist/proxmox/probes/vm-config.js.map +1 -0
  217. package/dist/proxmox/probes/vm-config.test.d.ts +2 -0
  218. package/dist/proxmox/probes/vm-config.test.d.ts.map +1 -0
  219. package/dist/proxmox/probes/vm-config.test.js +80 -0
  220. package/dist/proxmox/probes/vm-config.test.js.map +1 -0
  221. package/dist/proxmox/probes/vm-locks.d.ts +16 -0
  222. package/dist/proxmox/probes/vm-locks.d.ts.map +1 -0
  223. package/dist/proxmox/probes/vm-locks.js +35 -0
  224. package/dist/proxmox/probes/vm-locks.js.map +1 -0
  225. package/dist/proxmox/probes/vm-locks.test.d.ts +2 -0
  226. package/dist/proxmox/probes/vm-locks.test.d.ts.map +1 -0
  227. package/dist/proxmox/probes/vm-locks.test.js +54 -0
  228. package/dist/proxmox/probes/vm-locks.test.js.map +1 -0
  229. package/dist/redis/index.d.ts +3 -0
  230. package/dist/redis/index.d.ts.map +1 -0
  231. package/dist/redis/index.js +13 -0
  232. package/dist/redis/index.js.map +1 -0
  233. package/dist/redis/manifest.d.ts +3 -0
  234. package/dist/redis/manifest.d.ts.map +1 -0
  235. package/dist/redis/manifest.js +51 -0
  236. package/dist/redis/manifest.js.map +1 -0
  237. package/dist/redis/probes/info.d.ts +15 -0
  238. package/dist/redis/probes/info.d.ts.map +1 -0
  239. package/dist/redis/probes/info.js +32 -0
  240. package/dist/redis/probes/info.js.map +1 -0
  241. package/dist/redis/probes/info.test.d.ts +2 -0
  242. package/dist/redis/probes/info.test.d.ts.map +1 -0
  243. package/dist/redis/probes/info.test.js +64 -0
  244. package/dist/redis/probes/info.test.js.map +1 -0
  245. package/dist/redis/probes/keys-count.d.ts +13 -0
  246. package/dist/redis/probes/keys-count.d.ts.map +1 -0
  247. package/dist/redis/probes/keys-count.js +24 -0
  248. package/dist/redis/probes/keys-count.js.map +1 -0
  249. package/dist/redis/probes/keys-count.test.d.ts +2 -0
  250. package/dist/redis/probes/keys-count.test.d.ts.map +1 -0
  251. package/dist/redis/probes/keys-count.test.js +37 -0
  252. package/dist/redis/probes/keys-count.test.js.map +1 -0
  253. package/dist/redis/probes/memory-usage.d.ts +16 -0
  254. package/dist/redis/probes/memory-usage.d.ts.map +1 -0
  255. package/dist/redis/probes/memory-usage.js +31 -0
  256. package/dist/redis/probes/memory-usage.js.map +1 -0
  257. package/dist/redis/probes/memory-usage.test.d.ts +2 -0
  258. package/dist/redis/probes/memory-usage.test.d.ts.map +1 -0
  259. package/dist/redis/probes/memory-usage.test.js +48 -0
  260. package/dist/redis/probes/memory-usage.test.js.map +1 -0
  261. package/dist/runbooks/nutanix.d.ts +3 -0
  262. package/dist/runbooks/nutanix.d.ts.map +1 -0
  263. package/dist/runbooks/nutanix.js +619 -0
  264. package/dist/runbooks/nutanix.js.map +1 -0
  265. package/dist/runbooks/nutanix.test.d.ts +2 -0
  266. package/dist/runbooks/nutanix.test.d.ts.map +1 -0
  267. package/dist/runbooks/nutanix.test.js +971 -0
  268. package/dist/runbooks/nutanix.test.js.map +1 -0
  269. package/dist/runbooks/proxmox.d.ts +3 -0
  270. package/dist/runbooks/proxmox.d.ts.map +1 -0
  271. package/dist/runbooks/proxmox.js +451 -0
  272. package/dist/runbooks/proxmox.js.map +1 -0
  273. package/dist/runbooks/proxmox.test.d.ts +2 -0
  274. package/dist/runbooks/proxmox.test.d.ts.map +1 -0
  275. package/dist/runbooks/proxmox.test.js +700 -0
  276. package/dist/runbooks/proxmox.test.js.map +1 -0
  277. package/dist/signatures.d.ts +2 -0
  278. package/dist/signatures.d.ts.map +1 -0
  279. package/dist/signatures.js +2 -0
  280. package/dist/signatures.js.map +1 -0
  281. package/dist/system/index.d.ts.map +1 -1
  282. package/dist/system/index.js +2 -0
  283. package/dist/system/index.js.map +1 -1
  284. package/dist/system/manifest.d.ts.map +1 -1
  285. package/dist/system/manifest.js +19 -1
  286. package/dist/system/manifest.js.map +1 -1
  287. package/dist/system/probes/ping.d.ts +20 -0
  288. package/dist/system/probes/ping.d.ts.map +1 -0
  289. package/dist/system/probes/ping.js +54 -0
  290. package/dist/system/probes/ping.js.map +1 -0
  291. package/dist/system/probes/ping.test.d.ts +2 -0
  292. package/dist/system/probes/ping.test.d.ts.map +1 -0
  293. package/dist/system/probes/ping.test.js +127 -0
  294. package/dist/system/probes/ping.test.js.map +1 -0
  295. package/dist/types.d.ts +53 -0
  296. package/dist/types.d.ts.map +1 -1
  297. package/dist/validation.d.ts +6 -1
  298. package/dist/validation.d.ts.map +1 -1
  299. package/dist/validation.js +10 -1
  300. package/dist/validation.js.map +1 -1
  301. package/package.json +1 -1
  302. package/src/index.ts +60 -6
  303. package/src/integrations/citrix.test.ts +592 -0
  304. package/src/integrations/citrix.ts +553 -0
  305. package/src/integrations/graph.test.ts +478 -0
  306. package/src/integrations/graph.ts +409 -0
  307. package/src/integrations/httpbin.ts +68 -0
  308. package/src/integrations/nutanix.test.ts +1508 -0
  309. package/src/integrations/nutanix.ts +1456 -0
  310. package/src/integrations/proxmox.test.ts +1020 -0
  311. package/src/integrations/proxmox.ts +985 -0
  312. package/src/integrations/servicenow.test.ts +314 -0
  313. package/src/integrations/servicenow.ts +280 -0
  314. package/src/integrations/splunk.test.ts +440 -0
  315. package/src/integrations/splunk.ts +352 -0
  316. package/src/mysql/index.ts +14 -0
  317. package/src/mysql/manifest.ts +70 -0
  318. package/src/mysql/probes/databases-list.test.ts +62 -0
  319. package/src/mysql/probes/databases-list.ts +45 -0
  320. package/src/mysql/probes/processlist.test.ts +47 -0
  321. package/src/mysql/probes/processlist.ts +55 -0
  322. package/src/mysql/probes/status.test.ts +50 -0
  323. package/src/mysql/probes/status.ts +56 -0
  324. package/src/nginx/index.ts +14 -0
  325. package/src/nginx/manifest.ts +69 -0
  326. package/src/nginx/probes/access-log-tail.test.ts +51 -0
  327. package/src/nginx/probes/access-log-tail.ts +23 -0
  328. package/src/nginx/probes/config-test.test.ts +47 -0
  329. package/src/nginx/probes/config-test.ts +24 -0
  330. package/src/nginx/probes/error-log-tail.test.ts +44 -0
  331. package/src/nginx/probes/error-log-tail.ts +23 -0
  332. package/src/postgres/index.ts +14 -0
  333. package/src/postgres/manifest.ts +91 -0
  334. package/src/postgres/probes/connections-active.test.ts +42 -0
  335. package/src/postgres/probes/connections-active.ts +55 -0
  336. package/src/postgres/probes/databases-list.test.ts +57 -0
  337. package/src/postgres/probes/databases-list.ts +49 -0
  338. package/src/postgres/probes/query-slow.test.ts +37 -0
  339. package/src/postgres/probes/query-slow.ts +55 -0
  340. package/src/proxmox/index.ts +24 -0
  341. package/src/proxmox/manifest.ts +76 -0
  342. package/src/proxmox/probes/ceph-status.test.ts +126 -0
  343. package/src/proxmox/probes/ceph-status.ts +116 -0
  344. package/src/proxmox/probes/cluster-config.test.ts +118 -0
  345. package/src/proxmox/probes/cluster-config.ts +97 -0
  346. package/src/proxmox/probes/ha-status.test.ts +76 -0
  347. package/src/proxmox/probes/ha-status.ts +56 -0
  348. package/src/proxmox/probes/lvm.test.ts +140 -0
  349. package/src/proxmox/probes/lvm.ts +121 -0
  350. package/src/proxmox/probes/lxc-config.test.ts +89 -0
  351. package/src/proxmox/probes/lxc-config.ts +90 -0
  352. package/src/proxmox/probes/lxc-list.test.ts +60 -0
  353. package/src/proxmox/probes/lxc-list.ts +67 -0
  354. package/src/proxmox/probes/vm-config.test.ts +93 -0
  355. package/src/proxmox/probes/vm-config.ts +77 -0
  356. package/src/proxmox/probes/vm-locks.test.ts +63 -0
  357. package/src/proxmox/probes/vm-locks.ts +49 -0
  358. package/src/redis/index.ts +14 -0
  359. package/src/redis/manifest.ts +52 -0
  360. package/src/redis/probes/info.test.ts +73 -0
  361. package/src/redis/probes/info.ts +46 -0
  362. package/src/redis/probes/keys-count.test.ts +44 -0
  363. package/src/redis/probes/keys-count.ts +38 -0
  364. package/src/redis/probes/memory-usage.test.ts +54 -0
  365. package/src/redis/probes/memory-usage.ts +46 -0
  366. package/src/runbooks/nutanix.test.ts +1138 -0
  367. package/src/runbooks/nutanix.ts +941 -0
  368. package/src/runbooks/proxmox.test.ts +838 -0
  369. package/src/runbooks/proxmox.ts +626 -0
  370. package/src/signatures.ts +1 -0
  371. package/src/system/index.ts +2 -0
  372. package/src/system/manifest.ts +21 -1
  373. package/src/system/probes/ping.test.ts +163 -0
  374. package/src/system/probes/ping.ts +89 -0
  375. package/src/types.ts +62 -0
  376. package/src/validation.ts +21 -1
  377. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,352 @@
1
+ import type {
2
+ FetchFn,
3
+ IntegrationConfig,
4
+ IntegrationCredentials,
5
+ IntegrationPack,
6
+ IntegrationProbeHandler,
7
+ } from '@sonde/shared';
8
+
9
+ // --- Auth helpers ---
10
+
11
+ /** Build auth headers: Bearer token or Basic username:password */
12
+ export function buildAuthHeaders(credentials: IntegrationCredentials): Record<string, string> {
13
+ if (credentials.authMethod === 'bearer_token') {
14
+ const token = credentials.credentials.splunkToken ?? '';
15
+ return { Authorization: `Bearer ${token}` };
16
+ }
17
+
18
+ // basic auth
19
+ const { username, password } = credentials.credentials;
20
+ if (username && password) {
21
+ return { Authorization: `Basic ${Buffer.from(`${username}:${password}`).toString('base64')}` };
22
+ }
23
+ return {};
24
+ }
25
+
26
+ // --- Splunk REST helper ---
27
+
28
+ /** Build a full Splunk REST URL with output_mode=json */
29
+ function splunkUrl(endpoint: string, path: string, params?: Record<string, string>): string {
30
+ const base = `${endpoint.replace(/\/$/, '')}${path}`;
31
+ const url = new URL(base);
32
+ url.searchParams.set('output_mode', 'json');
33
+ if (params) {
34
+ for (const [key, value] of Object.entries(params)) {
35
+ url.searchParams.set(key, value);
36
+ }
37
+ }
38
+ return url.toString();
39
+ }
40
+
41
+ /** GET a Splunk REST endpoint, returns parsed JSON */
42
+ export async function splunkGet(
43
+ path: string,
44
+ config: IntegrationConfig,
45
+ credentials: IntegrationCredentials,
46
+ fetchFn: FetchFn,
47
+ params?: Record<string, string>,
48
+ ): Promise<unknown> {
49
+ const url = splunkUrl(config.endpoint, path, params);
50
+ const headers: Record<string, string> = {
51
+ Accept: 'application/json',
52
+ ...buildAuthHeaders(credentials),
53
+ ...config.headers,
54
+ };
55
+
56
+ const res = await fetchFn(url, { headers });
57
+ if (!res.ok) throw new Error(`Splunk API returned ${res.status}: ${res.statusText}`);
58
+ return res.json();
59
+ }
60
+
61
+ /** POST URL-encoded form data to a Splunk REST endpoint, returns parsed JSON */
62
+ export async function splunkPost(
63
+ path: string,
64
+ formData: Record<string, string>,
65
+ config: IntegrationConfig,
66
+ credentials: IntegrationCredentials,
67
+ fetchFn: FetchFn,
68
+ ): Promise<unknown> {
69
+ const url = splunkUrl(config.endpoint, path);
70
+ const body = new URLSearchParams(formData);
71
+
72
+ const headers: Record<string, string> = {
73
+ 'Content-Type': 'application/x-www-form-urlencoded',
74
+ Accept: 'application/json',
75
+ ...buildAuthHeaders(credentials),
76
+ ...config.headers,
77
+ };
78
+
79
+ const res = await fetchFn(url, { method: 'POST', headers, body: body.toString() });
80
+ if (!res.ok) throw new Error(`Splunk API returned ${res.status}: ${res.statusText}`);
81
+ return res.json();
82
+ }
83
+
84
+ // --- Probe handlers ---
85
+
86
+ const POLL_INTERVAL_MS = 1000;
87
+ const MAX_POLL_ATTEMPTS = 60;
88
+
89
+ const splunkSearch: IntegrationProbeHandler = async (params, config, credentials, fetchFn) => {
90
+ const query = (params?.query as string) ?? '';
91
+ if (!query) throw new Error('query parameter is required (SPL search string)');
92
+
93
+ const earliest = (params?.earliest as string) || '-24h';
94
+ const latest = (params?.latest as string) || 'now';
95
+ const maxResults = (params?.max_results as number) || 100;
96
+
97
+ const startTime = Date.now();
98
+
99
+ // Create async search job via v2 API
100
+ const jobResponse = (await splunkPost(
101
+ '/services/search/v2/jobs',
102
+ {
103
+ search: query,
104
+ earliest_time: earliest,
105
+ latest_time: latest,
106
+ },
107
+ config,
108
+ credentials,
109
+ fetchFn,
110
+ )) as { sid?: string };
111
+
112
+ const sid = jobResponse.sid;
113
+ if (!sid) throw new Error('Splunk did not return a search job ID (sid)');
114
+
115
+ // Poll until done
116
+ let dispatchState = '';
117
+ let attempts = 0;
118
+
119
+ while (dispatchState !== 'DONE' && attempts < MAX_POLL_ATTEMPTS) {
120
+ const status = (await splunkGet(
121
+ `/services/search/v2/jobs/${sid}`,
122
+ config,
123
+ credentials,
124
+ fetchFn,
125
+ )) as { entry?: Array<{ content?: { dispatchState?: string } }> };
126
+
127
+ dispatchState = status.entry?.[0]?.content?.dispatchState ?? '';
128
+
129
+ if (dispatchState === 'FAILED') {
130
+ throw new Error('Splunk search job failed');
131
+ }
132
+
133
+ if (dispatchState !== 'DONE') {
134
+ await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
135
+ attempts++;
136
+ }
137
+ }
138
+
139
+ if (dispatchState !== 'DONE') {
140
+ throw new Error('Splunk search job timed out waiting for completion');
141
+ }
142
+
143
+ // Fetch results
144
+ const results = (await splunkGet(
145
+ `/services/search/v2/jobs/${sid}/results`,
146
+ config,
147
+ credentials,
148
+ fetchFn,
149
+ { count: String(maxResults) },
150
+ )) as { results?: unknown[]; init_offset?: number; post_process_count?: number };
151
+
152
+ const executionTimeMs = Date.now() - startTime;
153
+
154
+ return {
155
+ results: results.results ?? [],
156
+ resultCount: (results.results ?? []).length,
157
+ sid,
158
+ executionTimeMs,
159
+ };
160
+ };
161
+
162
+ const splunkIndexes: IntegrationProbeHandler = async (_params, config, credentials, fetchFn) => {
163
+ const data = (await splunkGet('/services/data/indexes', config, credentials, fetchFn, {
164
+ count: '0',
165
+ })) as {
166
+ entry?: Array<{
167
+ name?: string;
168
+ content?: {
169
+ currentDBSizeMB?: number;
170
+ totalEventCount?: string;
171
+ minTime?: string;
172
+ maxTime?: string;
173
+ disabled?: boolean;
174
+ };
175
+ }>;
176
+ };
177
+
178
+ const indexes = (data.entry ?? []).map((entry) => ({
179
+ name: entry.name ?? '',
180
+ currentSizeMB: entry.content?.currentDBSizeMB ?? 0,
181
+ totalEventCount: entry.content?.totalEventCount ?? '0',
182
+ earliestEventTime: entry.content?.minTime ?? null,
183
+ latestEventTime: entry.content?.maxTime ?? null,
184
+ disabled: entry.content?.disabled ?? false,
185
+ }));
186
+
187
+ return { indexes, count: indexes.length };
188
+ };
189
+
190
+ const splunkSavedSearches: IntegrationProbeHandler = async (
191
+ params,
192
+ config,
193
+ credentials,
194
+ fetchFn,
195
+ ) => {
196
+ const filterName = params?.name as string | undefined;
197
+
198
+ const data = (await splunkGet('/services/saved/searches', config, credentials, fetchFn, {
199
+ count: '0',
200
+ })) as {
201
+ entry?: Array<{
202
+ name?: string;
203
+ content?: {
204
+ search?: string;
205
+ cron_schedule?: string;
206
+ 'dispatch.latest_time'?: string;
207
+ disabled?: boolean;
208
+ triggered_alert_count?: number;
209
+ };
210
+ updated?: string;
211
+ }>;
212
+ };
213
+
214
+ let searches = (data.entry ?? []).map((entry) => ({
215
+ name: entry.name ?? '',
216
+ search: entry.content?.search ?? '',
217
+ cronSchedule: entry.content?.cron_schedule ?? null,
218
+ disabled: entry.content?.disabled ?? false,
219
+ triggeredAlertCount: entry.content?.triggered_alert_count ?? 0,
220
+ lastUpdated: entry.updated ?? null,
221
+ }));
222
+
223
+ if (filterName) {
224
+ const lower = filterName.toLowerCase();
225
+ searches = searches.filter((s) => s.name.toLowerCase().includes(lower));
226
+ }
227
+
228
+ return { savedSearches: searches, count: searches.length };
229
+ };
230
+
231
+ const splunkHealth: IntegrationProbeHandler = async (_params, config, credentials, fetchFn) => {
232
+ const data = (await splunkGet(
233
+ '/services/server/health/splunkd',
234
+ config,
235
+ credentials,
236
+ fetchFn,
237
+ )) as {
238
+ entry?: Array<{
239
+ content?: {
240
+ health?: string;
241
+ features?: Record<string, { health?: string; [key: string]: unknown }>;
242
+ };
243
+ }>;
244
+ };
245
+
246
+ const content = data.entry?.[0]?.content;
247
+ const features = content?.features ?? {};
248
+
249
+ const featureHealth = Object.entries(features).map(([name, info]) => ({
250
+ name,
251
+ health: info.health ?? 'unknown',
252
+ }));
253
+
254
+ return {
255
+ overallHealth: content?.health ?? 'unknown',
256
+ features: featureHealth,
257
+ };
258
+ };
259
+
260
+ // --- Pack definition ---
261
+
262
+ export const splunkPack: IntegrationPack = {
263
+ manifest: {
264
+ name: 'splunk',
265
+ type: 'integration',
266
+ version: '0.1.0',
267
+ description: 'Splunk Enterprise — search, indexes, saved searches, and health monitoring',
268
+ requires: { groups: [], files: [], commands: [] },
269
+ probes: [
270
+ {
271
+ name: 'search',
272
+ description:
273
+ 'Run an SPL search query and return results. Requires a role with "search" capability.',
274
+ capability: 'observe',
275
+ params: {
276
+ query: {
277
+ type: 'string',
278
+ description: 'SPL search query (e.g. "search index=main error | head 10")',
279
+ required: true,
280
+ },
281
+ earliest: {
282
+ type: 'string',
283
+ description: 'Earliest time (default: "-24h")',
284
+ required: false,
285
+ },
286
+ latest: {
287
+ type: 'string',
288
+ description: 'Latest time (default: "now")',
289
+ required: false,
290
+ },
291
+ max_results: {
292
+ type: 'number',
293
+ description: 'Maximum results to return (default: 100)',
294
+ required: false,
295
+ },
296
+ },
297
+ timeout: 60000,
298
+ },
299
+ {
300
+ name: 'indexes',
301
+ description: 'List all indexes with size, event count, and time range',
302
+ capability: 'observe',
303
+ params: {},
304
+ timeout: 15000,
305
+ },
306
+ {
307
+ name: 'saved_searches',
308
+ description: 'List saved searches with schedule and status',
309
+ capability: 'observe',
310
+ params: {
311
+ name: {
312
+ type: 'string',
313
+ description: 'Optional name filter (case-insensitive substring match)',
314
+ required: false,
315
+ },
316
+ },
317
+ timeout: 15000,
318
+ },
319
+ {
320
+ name: 'health',
321
+ description: 'Splunkd health status with per-feature breakdown',
322
+ capability: 'observe',
323
+ params: {},
324
+ timeout: 15000,
325
+ },
326
+ ],
327
+ runbook: {
328
+ category: 'observability',
329
+ probes: ['health', 'indexes'],
330
+ parallel: true,
331
+ },
332
+ },
333
+
334
+ handlers: {
335
+ search: splunkSearch,
336
+ indexes: splunkIndexes,
337
+ saved_searches: splunkSavedSearches,
338
+ health: splunkHealth,
339
+ },
340
+
341
+ testConnection: async (config, credentials, fetchFn) => {
342
+ const url = splunkUrl(config.endpoint, '/services/server/info');
343
+ const headers: Record<string, string> = {
344
+ Accept: 'application/json',
345
+ ...buildAuthHeaders(credentials),
346
+ ...config.headers,
347
+ };
348
+
349
+ const res = await fetchFn(url, { headers });
350
+ return res.ok;
351
+ },
352
+ };
@@ -0,0 +1,14 @@
1
+ import type { Pack } from '../types.js';
2
+ import { mysqlManifest } from './manifest.js';
3
+ import { databasesList } from './probes/databases-list.js';
4
+ import { processlist } from './probes/processlist.js';
5
+ import { status } from './probes/status.js';
6
+
7
+ export const mysqlPack: Pack = {
8
+ manifest: mysqlManifest,
9
+ handlers: {
10
+ 'mysql.databases.list': databasesList,
11
+ 'mysql.processlist': processlist,
12
+ 'mysql.status': status,
13
+ },
14
+ };
@@ -0,0 +1,70 @@
1
+ import type { PackManifest } from '@sonde/shared';
2
+
3
+ export const mysqlManifest: PackManifest = {
4
+ name: 'mysql',
5
+ version: '0.1.0',
6
+ description: 'MySQL probes: database listing, process list, server status',
7
+ requires: {
8
+ groups: [],
9
+ files: [],
10
+ commands: ['mysql'],
11
+ },
12
+ probes: [
13
+ {
14
+ name: 'databases.list',
15
+ description: 'List all MySQL databases with table counts and sizes',
16
+ capability: 'observe',
17
+ params: {
18
+ host: {
19
+ type: 'string',
20
+ description: 'Database host',
21
+ required: false,
22
+ default: 'localhost',
23
+ },
24
+ port: { type: 'number', description: 'Database port', required: false, default: 3306 },
25
+ user: { type: 'string', description: 'Database user', required: false, default: 'root' },
26
+ },
27
+ timeout: 15_000,
28
+ },
29
+ {
30
+ name: 'processlist',
31
+ description: 'Show active MySQL processes',
32
+ capability: 'observe',
33
+ params: {
34
+ host: {
35
+ type: 'string',
36
+ description: 'Database host',
37
+ required: false,
38
+ default: 'localhost',
39
+ },
40
+ port: { type: 'number', description: 'Database port', required: false, default: 3306 },
41
+ user: { type: 'string', description: 'Database user', required: false, default: 'root' },
42
+ },
43
+ timeout: 15_000,
44
+ },
45
+ {
46
+ name: 'status',
47
+ description: 'Get MySQL server status variables',
48
+ capability: 'observe',
49
+ params: {
50
+ host: {
51
+ type: 'string',
52
+ description: 'Database host',
53
+ required: false,
54
+ default: 'localhost',
55
+ },
56
+ port: { type: 'number', description: 'Database port', required: false, default: 3306 },
57
+ user: { type: 'string', description: 'Database user', required: false, default: 'root' },
58
+ },
59
+ timeout: 15_000,
60
+ },
61
+ ],
62
+ runbook: {
63
+ category: 'mysql',
64
+ probes: ['databases.list', 'processlist', 'status'],
65
+ parallel: true,
66
+ },
67
+ detect: {
68
+ commands: ['mysql'],
69
+ },
70
+ };
@@ -0,0 +1,62 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import type { ExecFn } from '../../types.js';
3
+ import type { MysqlDatabasesListResult } from './databases-list.js';
4
+ import { databasesList, parseDatabasesList } from './databases-list.js';
5
+
6
+ const SAMPLE_OUTPUT = `information_schema\t79\t0.00
7
+ myapp\t15\t256.50
8
+ mysql\t38\t2.44`;
9
+
10
+ describe('parseDatabasesList', () => {
11
+ it('parses mysql output into structured data', () => {
12
+ const result = parseDatabasesList(SAMPLE_OUTPUT);
13
+ expect(result.count).toBe(3);
14
+ expect(result.databases[0]).toEqual({
15
+ name: 'information_schema',
16
+ tables: 79,
17
+ sizeMb: 0,
18
+ });
19
+ expect(result.databases[1]).toEqual({
20
+ name: 'myapp',
21
+ tables: 15,
22
+ sizeMb: 256.5,
23
+ });
24
+ });
25
+
26
+ it('handles empty output', () => {
27
+ const result = parseDatabasesList('');
28
+ expect(result.count).toBe(0);
29
+ expect(result.databases).toEqual([]);
30
+ });
31
+ });
32
+
33
+ describe('databasesList handler', () => {
34
+ it('calls mysql with default params', async () => {
35
+ const mockExec: ExecFn = async (cmd, args) => {
36
+ expect(cmd).toBe('mysql');
37
+ expect(args).toContain('-h');
38
+ expect(args).toContain('localhost');
39
+ expect(args).toContain('-P');
40
+ expect(args).toContain('3306');
41
+ expect(args).toContain('-u');
42
+ expect(args).toContain('root');
43
+ expect(args).toContain('--batch');
44
+ expect(args).toContain('--skip-column-names');
45
+ return SAMPLE_OUTPUT;
46
+ };
47
+
48
+ const result = (await databasesList(undefined, mockExec)) as MysqlDatabasesListResult;
49
+ expect(result.count).toBe(3);
50
+ });
51
+
52
+ it('passes custom host/port/user', async () => {
53
+ const mockExec: ExecFn = async (cmd, args) => {
54
+ expect(args).toContain('db.example.com');
55
+ expect(args).toContain('3307');
56
+ expect(args).toContain('admin');
57
+ return SAMPLE_OUTPUT;
58
+ };
59
+
60
+ await databasesList({ host: 'db.example.com', port: 3307, user: 'admin' }, mockExec);
61
+ });
62
+ });
@@ -0,0 +1,45 @@
1
+ import type { ProbeHandler } from '../../types.js';
2
+
3
+ export interface MysqlDatabaseInfo {
4
+ name: string;
5
+ tables: number;
6
+ sizeMb: number;
7
+ }
8
+
9
+ export interface MysqlDatabasesListResult {
10
+ databases: MysqlDatabaseInfo[];
11
+ count: number;
12
+ }
13
+
14
+ export const databasesList: ProbeHandler = async (params, exec) => {
15
+ const host = (params?.host as string) ?? 'localhost';
16
+ const port = String((params?.port as number) ?? 3306);
17
+ const user = (params?.user as string) ?? 'root';
18
+
19
+ const stdout = await exec('mysql', [
20
+ '-h',
21
+ host,
22
+ '-P',
23
+ port,
24
+ '-u',
25
+ user,
26
+ '--batch',
27
+ '--skip-column-names',
28
+ '-e',
29
+ 'SELECT s.SCHEMA_NAME, COUNT(t.TABLE_NAME), ROUND(SUM(t.DATA_LENGTH + t.INDEX_LENGTH) / 1024 / 1024, 2) FROM information_schema.SCHEMATA s LEFT JOIN information_schema.TABLES t ON s.SCHEMA_NAME = t.TABLE_SCHEMA GROUP BY s.SCHEMA_NAME ORDER BY s.SCHEMA_NAME',
30
+ ]);
31
+ return parseDatabasesList(stdout);
32
+ };
33
+
34
+ export function parseDatabasesList(stdout: string): MysqlDatabasesListResult {
35
+ const lines = stdout.trim().split('\n').filter(Boolean);
36
+ const databases: MysqlDatabaseInfo[] = lines.map((line) => {
37
+ const parts = line.split('\t');
38
+ return {
39
+ name: parts[0] ?? '',
40
+ tables: Number(parts[1]) || 0,
41
+ sizeMb: Number(parts[2]) || 0,
42
+ };
43
+ });
44
+ return { databases, count: databases.length };
45
+ }
@@ -0,0 +1,47 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import type { ExecFn } from '../../types.js';
3
+ import type { MysqlProcesslistResult } from './processlist.js';
4
+ import { parseProcesslist, processlist } from './processlist.js';
5
+
6
+ const SAMPLE_OUTPUT = `42\troot\tlocalhost\tmyapp\tQuery\t120\texecuting\tSELECT * FROM large_table
7
+ 99\tappuser\t192.168.1.10\tmyapp\tSleep\t5\t\t`;
8
+
9
+ describe('parseProcesslist', () => {
10
+ it('parses process list output', () => {
11
+ const result = parseProcesslist(SAMPLE_OUTPUT);
12
+ expect(result.count).toBe(2);
13
+ expect(result.processes[0]).toEqual({
14
+ id: 42,
15
+ user: 'root',
16
+ host: 'localhost',
17
+ db: 'myapp',
18
+ command: 'Query',
19
+ time: 120,
20
+ state: 'executing',
21
+ info: 'SELECT * FROM large_table',
22
+ });
23
+ expect(result.processes[1]?.command).toBe('Sleep');
24
+ });
25
+
26
+ it('handles empty output', () => {
27
+ const result = parseProcesslist('');
28
+ expect(result.count).toBe(0);
29
+ expect(result.processes).toEqual([]);
30
+ });
31
+ });
32
+
33
+ describe('processlist handler', () => {
34
+ it('calls mysql with correct args', async () => {
35
+ const mockExec: ExecFn = async (cmd, args) => {
36
+ expect(cmd).toBe('mysql');
37
+ expect(args).toContain('--batch');
38
+ expect(args).toContain('--skip-column-names');
39
+ const query = args[args.length - 1];
40
+ expect(query).toContain('PROCESSLIST');
41
+ return SAMPLE_OUTPUT;
42
+ };
43
+
44
+ const result = (await processlist(undefined, mockExec)) as MysqlProcesslistResult;
45
+ expect(result.count).toBe(2);
46
+ });
47
+ });
@@ -0,0 +1,55 @@
1
+ import type { ProbeHandler } from '../../types.js';
2
+
3
+ export interface MysqlProcessInfo {
4
+ id: number;
5
+ user: string;
6
+ host: string;
7
+ db: string;
8
+ command: string;
9
+ time: number;
10
+ state: string;
11
+ info: string;
12
+ }
13
+
14
+ export interface MysqlProcesslistResult {
15
+ processes: MysqlProcessInfo[];
16
+ count: number;
17
+ }
18
+
19
+ export const processlist: ProbeHandler = async (params, exec) => {
20
+ const host = (params?.host as string) ?? 'localhost';
21
+ const port = String((params?.port as number) ?? 3306);
22
+ const user = (params?.user as string) ?? 'root';
23
+
24
+ const stdout = await exec('mysql', [
25
+ '-h',
26
+ host,
27
+ '-P',
28
+ port,
29
+ '-u',
30
+ user,
31
+ '--batch',
32
+ '--skip-column-names',
33
+ '-e',
34
+ 'SELECT ID, USER, HOST, IFNULL(DB, ""), COMMAND, TIME, IFNULL(STATE, ""), LEFT(IFNULL(INFO, ""), 200) FROM information_schema.PROCESSLIST ORDER BY TIME DESC',
35
+ ]);
36
+ return parseProcesslist(stdout);
37
+ };
38
+
39
+ export function parseProcesslist(stdout: string): MysqlProcesslistResult {
40
+ const lines = stdout.trim().split('\n').filter(Boolean);
41
+ const processes: MysqlProcessInfo[] = lines.map((line) => {
42
+ const parts = line.split('\t');
43
+ return {
44
+ id: Number(parts[0]) || 0,
45
+ user: parts[1] ?? '',
46
+ host: parts[2] ?? '',
47
+ db: parts[3] ?? '',
48
+ command: parts[4] ?? '',
49
+ time: Number(parts[5]) || 0,
50
+ state: parts[6] ?? '',
51
+ info: parts[7] ?? '',
52
+ };
53
+ });
54
+ return { processes, count: processes.length };
55
+ }
@@ -0,0 +1,50 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import type { ExecFn } from '../../types.js';
3
+ import type { MysqlStatusResult } from './status.js';
4
+ import { parseMysqlStatus, status } from './status.js';
5
+
6
+ const SAMPLE_OUTPUT = `Uptime\t86400
7
+ Threads_connected\t15
8
+ Questions\t1728000
9
+ Slow_queries\t42
10
+ Opened_tables\t500
11
+ Open_tables\t200`;
12
+
13
+ describe('parseMysqlStatus', () => {
14
+ it('parses status variables', () => {
15
+ const result = parseMysqlStatus(SAMPLE_OUTPUT);
16
+ expect(result.uptime).toBe(86400);
17
+ expect(result.threads).toBe(15);
18
+ expect(result.questions).toBe(1728000);
19
+ expect(result.slowQueries).toBe(42);
20
+ expect(result.opens).toBe(500);
21
+ expect(result.openTables).toBe(200);
22
+ expect(result.queriesPerSecondAvg).toBe(20);
23
+ });
24
+
25
+ it('stores all variables in map', () => {
26
+ const result = parseMysqlStatus(SAMPLE_OUTPUT);
27
+ expect(result.variables['Uptime']).toBe('86400');
28
+ expect(result.variables['Slow_queries']).toBe('42');
29
+ });
30
+
31
+ it('handles empty output', () => {
32
+ const result = parseMysqlStatus('');
33
+ expect(result.uptime).toBe(0);
34
+ expect(result.queriesPerSecondAvg).toBe(0);
35
+ });
36
+ });
37
+
38
+ describe('status handler', () => {
39
+ it('calls mysql SHOW GLOBAL STATUS', async () => {
40
+ const mockExec: ExecFn = async (cmd, args) => {
41
+ expect(cmd).toBe('mysql');
42
+ const query = args[args.length - 1];
43
+ expect(query).toContain('SHOW GLOBAL STATUS');
44
+ return SAMPLE_OUTPUT;
45
+ };
46
+
47
+ const result = (await status(undefined, mockExec)) as MysqlStatusResult;
48
+ expect(result.uptime).toBe(86400);
49
+ });
50
+ });