kubeview-mcp 1.0.0

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 (454) hide show
  1. package/.prettierrc.json +11 -0
  2. package/CHANGELOG.md +55 -0
  3. package/LICENSE +21 -0
  4. package/README.md +251 -0
  5. package/RELEASE.md +154 -0
  6. package/TODO.md +0 -0
  7. package/bin/kubeview-mcp.js +274 -0
  8. package/bin/setup.js +368 -0
  9. package/dist/src/cli/cli.d.ts +3 -0
  10. package/dist/src/cli/cli.d.ts.map +1 -0
  11. package/dist/src/cli/cli.js +23 -0
  12. package/dist/src/cli/cli.js.map +1 -0
  13. package/dist/src/index.d.ts +8 -0
  14. package/dist/src/index.d.ts.map +1 -0
  15. package/dist/src/index.js +45 -0
  16. package/dist/src/index.js.map +1 -0
  17. package/dist/src/kubernetes/BaseResourceOperations.d.ts +155 -0
  18. package/dist/src/kubernetes/BaseResourceOperations.d.ts.map +1 -0
  19. package/dist/src/kubernetes/BaseResourceOperations.js +136 -0
  20. package/dist/src/kubernetes/BaseResourceOperations.js.map +1 -0
  21. package/dist/src/kubernetes/CircuitBreaker.d.ts +182 -0
  22. package/dist/src/kubernetes/CircuitBreaker.d.ts.map +1 -0
  23. package/dist/src/kubernetes/CircuitBreaker.js +369 -0
  24. package/dist/src/kubernetes/CircuitBreaker.js.map +1 -0
  25. package/dist/src/kubernetes/ConnectionManager.d.ts +60 -0
  26. package/dist/src/kubernetes/ConnectionManager.d.ts.map +1 -0
  27. package/dist/src/kubernetes/ConnectionManager.js +77 -0
  28. package/dist/src/kubernetes/ConnectionManager.js.map +1 -0
  29. package/dist/src/kubernetes/ConnectionPool.d.ts +183 -0
  30. package/dist/src/kubernetes/ConnectionPool.d.ts.map +1 -0
  31. package/dist/src/kubernetes/ConnectionPool.js +437 -0
  32. package/dist/src/kubernetes/ConnectionPool.js.map +1 -0
  33. package/dist/src/kubernetes/ErrorHandler.d.ts +172 -0
  34. package/dist/src/kubernetes/ErrorHandler.d.ts.map +1 -0
  35. package/dist/src/kubernetes/ErrorHandler.js +328 -0
  36. package/dist/src/kubernetes/ErrorHandler.js.map +1 -0
  37. package/dist/src/kubernetes/ErrorHandling.d.ts +148 -0
  38. package/dist/src/kubernetes/ErrorHandling.d.ts.map +1 -0
  39. package/dist/src/kubernetes/ErrorHandling.js +304 -0
  40. package/dist/src/kubernetes/ErrorHandling.js.map +1 -0
  41. package/dist/src/kubernetes/KubernetesClient.d.ts +162 -0
  42. package/dist/src/kubernetes/KubernetesClient.d.ts.map +1 -0
  43. package/dist/src/kubernetes/KubernetesClient.js +382 -0
  44. package/dist/src/kubernetes/KubernetesClient.js.map +1 -0
  45. package/dist/src/kubernetes/ResourceOperations.d.ts +69 -0
  46. package/dist/src/kubernetes/ResourceOperations.d.ts.map +1 -0
  47. package/dist/src/kubernetes/ResourceOperations.js +99 -0
  48. package/dist/src/kubernetes/ResourceOperations.js.map +1 -0
  49. package/dist/src/kubernetes/RetryStrategy.d.ts +137 -0
  50. package/dist/src/kubernetes/RetryStrategy.d.ts.map +1 -0
  51. package/dist/src/kubernetes/RetryStrategy.js +277 -0
  52. package/dist/src/kubernetes/RetryStrategy.js.map +1 -0
  53. package/dist/src/kubernetes/RetryableOperation.d.ts +118 -0
  54. package/dist/src/kubernetes/RetryableOperation.d.ts.map +1 -0
  55. package/dist/src/kubernetes/RetryableOperation.js +233 -0
  56. package/dist/src/kubernetes/RetryableOperation.js.map +1 -0
  57. package/dist/src/kubernetes/index.d.ts +18 -0
  58. package/dist/src/kubernetes/index.d.ts.map +1 -0
  59. package/dist/src/kubernetes/index.js +28 -0
  60. package/dist/src/kubernetes/index.js.map +1 -0
  61. package/dist/src/kubernetes/resources/ConfigMapOperations.d.ts +60 -0
  62. package/dist/src/kubernetes/resources/ConfigMapOperations.d.ts.map +1 -0
  63. package/dist/src/kubernetes/resources/ConfigMapOperations.js +306 -0
  64. package/dist/src/kubernetes/resources/ConfigMapOperations.js.map +1 -0
  65. package/dist/src/kubernetes/resources/CustomResourceOperations.d.ts +55 -0
  66. package/dist/src/kubernetes/resources/CustomResourceOperations.d.ts.map +1 -0
  67. package/dist/src/kubernetes/resources/CustomResourceOperations.js +363 -0
  68. package/dist/src/kubernetes/resources/CustomResourceOperations.js.map +1 -0
  69. package/dist/src/kubernetes/resources/DeploymentOperations.d.ts +66 -0
  70. package/dist/src/kubernetes/resources/DeploymentOperations.d.ts.map +1 -0
  71. package/dist/src/kubernetes/resources/DeploymentOperations.js +234 -0
  72. package/dist/src/kubernetes/resources/DeploymentOperations.js.map +1 -0
  73. package/dist/src/kubernetes/resources/IngressOperations.d.ts +60 -0
  74. package/dist/src/kubernetes/resources/IngressOperations.d.ts.map +1 -0
  75. package/dist/src/kubernetes/resources/IngressOperations.js +224 -0
  76. package/dist/src/kubernetes/resources/IngressOperations.js.map +1 -0
  77. package/dist/src/kubernetes/resources/MetricOperations.d.ts +218 -0
  78. package/dist/src/kubernetes/resources/MetricOperations.d.ts.map +1 -0
  79. package/dist/src/kubernetes/resources/MetricOperations.js +893 -0
  80. package/dist/src/kubernetes/resources/MetricOperations.js.map +1 -0
  81. package/dist/src/kubernetes/resources/NamespaceOperations.d.ts +38 -0
  82. package/dist/src/kubernetes/resources/NamespaceOperations.d.ts.map +1 -0
  83. package/dist/src/kubernetes/resources/NamespaceOperations.js +101 -0
  84. package/dist/src/kubernetes/resources/NamespaceOperations.js.map +1 -0
  85. package/dist/src/kubernetes/resources/PersistentVolumeClaimOperations.d.ts +109 -0
  86. package/dist/src/kubernetes/resources/PersistentVolumeClaimOperations.d.ts.map +1 -0
  87. package/dist/src/kubernetes/resources/PersistentVolumeClaimOperations.js +383 -0
  88. package/dist/src/kubernetes/resources/PersistentVolumeClaimOperations.js.map +1 -0
  89. package/dist/src/kubernetes/resources/PersistentVolumeOperations.d.ts +97 -0
  90. package/dist/src/kubernetes/resources/PersistentVolumeOperations.d.ts.map +1 -0
  91. package/dist/src/kubernetes/resources/PersistentVolumeOperations.js +321 -0
  92. package/dist/src/kubernetes/resources/PersistentVolumeOperations.js.map +1 -0
  93. package/dist/src/kubernetes/resources/PodOperations.d.ts +99 -0
  94. package/dist/src/kubernetes/resources/PodOperations.d.ts.map +1 -0
  95. package/dist/src/kubernetes/resources/PodOperations.js +333 -0
  96. package/dist/src/kubernetes/resources/PodOperations.js.map +1 -0
  97. package/dist/src/kubernetes/resources/SecretOperations.d.ts +71 -0
  98. package/dist/src/kubernetes/resources/SecretOperations.d.ts.map +1 -0
  99. package/dist/src/kubernetes/resources/SecretOperations.js +254 -0
  100. package/dist/src/kubernetes/resources/SecretOperations.js.map +1 -0
  101. package/dist/src/kubernetes/resources/ServiceOperations.d.ts +64 -0
  102. package/dist/src/kubernetes/resources/ServiceOperations.d.ts.map +1 -0
  103. package/dist/src/kubernetes/resources/ServiceOperations.js +232 -0
  104. package/dist/src/kubernetes/resources/ServiceOperations.js.map +1 -0
  105. package/dist/src/kubernetes/utils/ResourceUtils.d.ts +238 -0
  106. package/dist/src/kubernetes/utils/ResourceUtils.d.ts.map +1 -0
  107. package/dist/src/kubernetes/utils/ResourceUtils.js +439 -0
  108. package/dist/src/kubernetes/utils/ResourceUtils.js.map +1 -0
  109. package/dist/src/plugins/ArgoCDToolsPlugin.d.ts +45 -0
  110. package/dist/src/plugins/ArgoCDToolsPlugin.d.ts.map +1 -0
  111. package/dist/src/plugins/ArgoCDToolsPlugin.js +155 -0
  112. package/dist/src/plugins/ArgoCDToolsPlugin.js.map +1 -0
  113. package/dist/src/plugins/ArgoToolsPlugin.d.ts +45 -0
  114. package/dist/src/plugins/ArgoToolsPlugin.d.ts.map +1 -0
  115. package/dist/src/plugins/ArgoToolsPlugin.js +149 -0
  116. package/dist/src/plugins/ArgoToolsPlugin.js.map +1 -0
  117. package/dist/src/plugins/HelmToolsPlugin.d.ts +41 -0
  118. package/dist/src/plugins/HelmToolsPlugin.d.ts.map +1 -0
  119. package/dist/src/plugins/HelmToolsPlugin.js +146 -0
  120. package/dist/src/plugins/HelmToolsPlugin.js.map +1 -0
  121. package/dist/src/plugins/KubernetesToolsPlugin.d.ts +44 -0
  122. package/dist/src/plugins/KubernetesToolsPlugin.d.ts.map +1 -0
  123. package/dist/src/plugins/KubernetesToolsPlugin.js +159 -0
  124. package/dist/src/plugins/KubernetesToolsPlugin.js.map +1 -0
  125. package/dist/src/plugins/SamplePlugin.d.ts +12 -0
  126. package/dist/src/plugins/SamplePlugin.d.ts.map +1 -0
  127. package/dist/src/plugins/SamplePlugin.js +51 -0
  128. package/dist/src/plugins/SamplePlugin.js.map +1 -0
  129. package/dist/src/plugins/index.d.ts +5 -0
  130. package/dist/src/plugins/index.d.ts.map +1 -0
  131. package/dist/src/plugins/index.js +5 -0
  132. package/dist/src/plugins/index.js.map +1 -0
  133. package/dist/src/server/MCPServer.d.ts +93 -0
  134. package/dist/src/server/MCPServer.d.ts.map +1 -0
  135. package/dist/src/server/MCPServer.js +398 -0
  136. package/dist/src/server/MCPServer.js.map +1 -0
  137. package/dist/src/tools/argo/ArgoCronListTool.d.ts +10 -0
  138. package/dist/src/tools/argo/ArgoCronListTool.d.ts.map +1 -0
  139. package/dist/src/tools/argo/ArgoCronListTool.js +70 -0
  140. package/dist/src/tools/argo/ArgoCronListTool.js.map +1 -0
  141. package/dist/src/tools/argo/ArgoGetTool.d.ts +10 -0
  142. package/dist/src/tools/argo/ArgoGetTool.d.ts.map +1 -0
  143. package/dist/src/tools/argo/ArgoGetTool.js +80 -0
  144. package/dist/src/tools/argo/ArgoGetTool.js.map +1 -0
  145. package/dist/src/tools/argo/ArgoListTool.d.ts +10 -0
  146. package/dist/src/tools/argo/ArgoListTool.d.ts.map +1 -0
  147. package/dist/src/tools/argo/ArgoListTool.js +133 -0
  148. package/dist/src/tools/argo/ArgoListTool.js.map +1 -0
  149. package/dist/src/tools/argo/ArgoLogsTool.d.ts +10 -0
  150. package/dist/src/tools/argo/ArgoLogsTool.d.ts.map +1 -0
  151. package/dist/src/tools/argo/ArgoLogsTool.js +117 -0
  152. package/dist/src/tools/argo/ArgoLogsTool.js.map +1 -0
  153. package/dist/src/tools/argo/BaseTool.d.ts +60 -0
  154. package/dist/src/tools/argo/BaseTool.d.ts.map +1 -0
  155. package/dist/src/tools/argo/BaseTool.js +51 -0
  156. package/dist/src/tools/argo/BaseTool.js.map +1 -0
  157. package/dist/src/tools/argo/index.d.ts +7 -0
  158. package/dist/src/tools/argo/index.d.ts.map +1 -0
  159. package/dist/src/tools/argo/index.js +6 -0
  160. package/dist/src/tools/argo/index.js.map +1 -0
  161. package/dist/src/tools/argocd/ArgoCDAppGetTool.d.ts +10 -0
  162. package/dist/src/tools/argocd/ArgoCDAppGetTool.d.ts.map +1 -0
  163. package/dist/src/tools/argocd/ArgoCDAppGetTool.js +97 -0
  164. package/dist/src/tools/argocd/ArgoCDAppGetTool.js.map +1 -0
  165. package/dist/src/tools/argocd/ArgoCDAppHistoryTool.d.ts +10 -0
  166. package/dist/src/tools/argocd/ArgoCDAppHistoryTool.d.ts.map +1 -0
  167. package/dist/src/tools/argocd/ArgoCDAppHistoryTool.js +80 -0
  168. package/dist/src/tools/argocd/ArgoCDAppHistoryTool.js.map +1 -0
  169. package/dist/src/tools/argocd/ArgoCDAppListTool.d.ts +10 -0
  170. package/dist/src/tools/argocd/ArgoCDAppListTool.d.ts.map +1 -0
  171. package/dist/src/tools/argocd/ArgoCDAppListTool.js +128 -0
  172. package/dist/src/tools/argocd/ArgoCDAppListTool.js.map +1 -0
  173. package/dist/src/tools/argocd/ArgoCDAppLogsTool.d.ts +10 -0
  174. package/dist/src/tools/argocd/ArgoCDAppLogsTool.d.ts.map +1 -0
  175. package/dist/src/tools/argocd/ArgoCDAppLogsTool.js +143 -0
  176. package/dist/src/tools/argocd/ArgoCDAppLogsTool.js.map +1 -0
  177. package/dist/src/tools/argocd/ArgoCDAppResourcesTool.d.ts +10 -0
  178. package/dist/src/tools/argocd/ArgoCDAppResourcesTool.d.ts.map +1 -0
  179. package/dist/src/tools/argocd/ArgoCDAppResourcesTool.js +123 -0
  180. package/dist/src/tools/argocd/ArgoCDAppResourcesTool.js.map +1 -0
  181. package/dist/src/tools/argocd/BaseTool.d.ts +71 -0
  182. package/dist/src/tools/argocd/BaseTool.d.ts.map +1 -0
  183. package/dist/src/tools/argocd/BaseTool.js +62 -0
  184. package/dist/src/tools/argocd/BaseTool.js.map +1 -0
  185. package/dist/src/tools/argocd/index.d.ts +8 -0
  186. package/dist/src/tools/argocd/index.d.ts.map +1 -0
  187. package/dist/src/tools/argocd/index.js +7 -0
  188. package/dist/src/tools/argocd/index.js.map +1 -0
  189. package/dist/src/tools/helm/BaseTool.d.ts +51 -0
  190. package/dist/src/tools/helm/BaseTool.d.ts.map +1 -0
  191. package/dist/src/tools/helm/BaseTool.js +42 -0
  192. package/dist/src/tools/helm/BaseTool.js.map +1 -0
  193. package/dist/src/tools/helm/HelmGetHooksTool.d.ts +10 -0
  194. package/dist/src/tools/helm/HelmGetHooksTool.d.ts.map +1 -0
  195. package/dist/src/tools/helm/HelmGetHooksTool.js +38 -0
  196. package/dist/src/tools/helm/HelmGetHooksTool.js.map +1 -0
  197. package/dist/src/tools/helm/HelmGetManifestTool.d.ts +10 -0
  198. package/dist/src/tools/helm/HelmGetManifestTool.d.ts.map +1 -0
  199. package/dist/src/tools/helm/HelmGetManifestTool.js +38 -0
  200. package/dist/src/tools/helm/HelmGetManifestTool.js.map +1 -0
  201. package/dist/src/tools/helm/HelmGetNotesTool.d.ts +10 -0
  202. package/dist/src/tools/helm/HelmGetNotesTool.d.ts.map +1 -0
  203. package/dist/src/tools/helm/HelmGetNotesTool.js +38 -0
  204. package/dist/src/tools/helm/HelmGetNotesTool.js.map +1 -0
  205. package/dist/src/tools/helm/HelmGetResourcesTool.d.ts +13 -0
  206. package/dist/src/tools/helm/HelmGetResourcesTool.d.ts.map +1 -0
  207. package/dist/src/tools/helm/HelmGetResourcesTool.js +124 -0
  208. package/dist/src/tools/helm/HelmGetResourcesTool.js.map +1 -0
  209. package/dist/src/tools/helm/HelmGetValuesTool.d.ts +10 -0
  210. package/dist/src/tools/helm/HelmGetValuesTool.d.ts.map +1 -0
  211. package/dist/src/tools/helm/HelmGetValuesTool.js +54 -0
  212. package/dist/src/tools/helm/HelmGetValuesTool.js.map +1 -0
  213. package/dist/src/tools/helm/HelmHistoryTool.d.ts +10 -0
  214. package/dist/src/tools/helm/HelmHistoryTool.d.ts.map +1 -0
  215. package/dist/src/tools/helm/HelmHistoryTool.js +49 -0
  216. package/dist/src/tools/helm/HelmHistoryTool.js.map +1 -0
  217. package/dist/src/tools/helm/HelmListTool.d.ts +10 -0
  218. package/dist/src/tools/helm/HelmListTool.d.ts.map +1 -0
  219. package/dist/src/tools/helm/HelmListTool.js +107 -0
  220. package/dist/src/tools/helm/HelmListTool.js.map +1 -0
  221. package/dist/src/tools/helm/HelmListWithResourcesTool.d.ts +14 -0
  222. package/dist/src/tools/helm/HelmListWithResourcesTool.d.ts.map +1 -0
  223. package/dist/src/tools/helm/HelmListWithResourcesTool.js +175 -0
  224. package/dist/src/tools/helm/HelmListWithResourcesTool.js.map +1 -0
  225. package/dist/src/tools/helm/HelmStatusTool.d.ts +10 -0
  226. package/dist/src/tools/helm/HelmStatusTool.d.ts.map +1 -0
  227. package/dist/src/tools/helm/HelmStatusTool.js +54 -0
  228. package/dist/src/tools/helm/HelmStatusTool.js.map +1 -0
  229. package/dist/src/tools/helm/index.d.ts +12 -0
  230. package/dist/src/tools/helm/index.d.ts.map +1 -0
  231. package/dist/src/tools/helm/index.js +11 -0
  232. package/dist/src/tools/helm/index.js.map +1 -0
  233. package/dist/src/tools/kubernetes/BaseTool.d.ts +48 -0
  234. package/dist/src/tools/kubernetes/BaseTool.d.ts.map +1 -0
  235. package/dist/src/tools/kubernetes/BaseTool.js +55 -0
  236. package/dist/src/tools/kubernetes/BaseTool.js.map +1 -0
  237. package/dist/src/tools/kubernetes/GetConfigMapTool.d.ts +11 -0
  238. package/dist/src/tools/kubernetes/GetConfigMapTool.d.ts.map +1 -0
  239. package/dist/src/tools/kubernetes/GetConfigMapTool.js +28 -0
  240. package/dist/src/tools/kubernetes/GetConfigMapTool.js.map +1 -0
  241. package/dist/src/tools/kubernetes/GetContainerLogsTool.d.ts +15 -0
  242. package/dist/src/tools/kubernetes/GetContainerLogsTool.d.ts.map +1 -0
  243. package/dist/src/tools/kubernetes/GetContainerLogsTool.js +119 -0
  244. package/dist/src/tools/kubernetes/GetContainerLogsTool.js.map +1 -0
  245. package/dist/src/tools/kubernetes/GetDeploymentsTool.d.ts +11 -0
  246. package/dist/src/tools/kubernetes/GetDeploymentsTool.d.ts.map +1 -0
  247. package/dist/src/tools/kubernetes/GetDeploymentsTool.js +30 -0
  248. package/dist/src/tools/kubernetes/GetDeploymentsTool.js.map +1 -0
  249. package/dist/src/tools/kubernetes/GetEventsTool.d.ts +11 -0
  250. package/dist/src/tools/kubernetes/GetEventsTool.d.ts.map +1 -0
  251. package/dist/src/tools/kubernetes/GetEventsTool.js +123 -0
  252. package/dist/src/tools/kubernetes/GetEventsTool.js.map +1 -0
  253. package/dist/src/tools/kubernetes/GetIngressTool.d.ts +11 -0
  254. package/dist/src/tools/kubernetes/GetIngressTool.d.ts.map +1 -0
  255. package/dist/src/tools/kubernetes/GetIngressTool.js +35 -0
  256. package/dist/src/tools/kubernetes/GetIngressTool.js.map +1 -0
  257. package/dist/src/tools/kubernetes/GetMetricsTool.d.ts +11 -0
  258. package/dist/src/tools/kubernetes/GetMetricsTool.d.ts.map +1 -0
  259. package/dist/src/tools/kubernetes/GetMetricsTool.js +40 -0
  260. package/dist/src/tools/kubernetes/GetMetricsTool.js.map +1 -0
  261. package/dist/src/tools/kubernetes/GetNamespacesTool.d.ts +11 -0
  262. package/dist/src/tools/kubernetes/GetNamespacesTool.d.ts.map +1 -0
  263. package/dist/src/tools/kubernetes/GetNamespacesTool.js +33 -0
  264. package/dist/src/tools/kubernetes/GetNamespacesTool.js.map +1 -0
  265. package/dist/src/tools/kubernetes/GetPersistentVolumeClaimsTool.d.ts +11 -0
  266. package/dist/src/tools/kubernetes/GetPersistentVolumeClaimsTool.d.ts.map +1 -0
  267. package/dist/src/tools/kubernetes/GetPersistentVolumeClaimsTool.js +92 -0
  268. package/dist/src/tools/kubernetes/GetPersistentVolumeClaimsTool.js.map +1 -0
  269. package/dist/src/tools/kubernetes/GetPersistentVolumesTool.d.ts +11 -0
  270. package/dist/src/tools/kubernetes/GetPersistentVolumesTool.d.ts.map +1 -0
  271. package/dist/src/tools/kubernetes/GetPersistentVolumesTool.js +88 -0
  272. package/dist/src/tools/kubernetes/GetPersistentVolumesTool.js.map +1 -0
  273. package/dist/src/tools/kubernetes/GetPodMetricsTool.d.ts +11 -0
  274. package/dist/src/tools/kubernetes/GetPodMetricsTool.d.ts.map +1 -0
  275. package/dist/src/tools/kubernetes/GetPodMetricsTool.js +100 -0
  276. package/dist/src/tools/kubernetes/GetPodMetricsTool.js.map +1 -0
  277. package/dist/src/tools/kubernetes/GetPodsTool.d.ts +11 -0
  278. package/dist/src/tools/kubernetes/GetPodsTool.d.ts.map +1 -0
  279. package/dist/src/tools/kubernetes/GetPodsTool.js +35 -0
  280. package/dist/src/tools/kubernetes/GetPodsTool.js.map +1 -0
  281. package/dist/src/tools/kubernetes/GetResourceTool.d.ts +12 -0
  282. package/dist/src/tools/kubernetes/GetResourceTool.d.ts.map +1 -0
  283. package/dist/src/tools/kubernetes/GetResourceTool.js +79 -0
  284. package/dist/src/tools/kubernetes/GetResourceTool.js.map +1 -0
  285. package/dist/src/tools/kubernetes/GetSecretsTool.d.ts +11 -0
  286. package/dist/src/tools/kubernetes/GetSecretsTool.d.ts.map +1 -0
  287. package/dist/src/tools/kubernetes/GetSecretsTool.js +49 -0
  288. package/dist/src/tools/kubernetes/GetSecretsTool.js.map +1 -0
  289. package/dist/src/tools/kubernetes/GetServicesTool.d.ts +11 -0
  290. package/dist/src/tools/kubernetes/GetServicesTool.d.ts.map +1 -0
  291. package/dist/src/tools/kubernetes/GetServicesTool.js +35 -0
  292. package/dist/src/tools/kubernetes/GetServicesTool.js.map +1 -0
  293. package/dist/src/tools/kubernetes/index.d.ts +17 -0
  294. package/dist/src/tools/kubernetes/index.d.ts.map +1 -0
  295. package/dist/src/tools/kubernetes/index.js +16 -0
  296. package/dist/src/tools/kubernetes/index.js.map +1 -0
  297. package/dist/src/utils/CliUtils.d.ts +24 -0
  298. package/dist/src/utils/CliUtils.d.ts.map +1 -0
  299. package/dist/src/utils/CliUtils.js +159 -0
  300. package/dist/src/utils/CliUtils.js.map +1 -0
  301. package/dist/tests/__mocks__/@kubernetes/client-node.d.ts +34 -0
  302. package/dist/tests/__mocks__/@kubernetes/client-node.d.ts.map +1 -0
  303. package/dist/tests/__mocks__/@kubernetes/client-node.js +20 -0
  304. package/dist/tests/__mocks__/@kubernetes/client-node.js.map +1 -0
  305. package/dist/tests/argo/ArgoGetTool.test.d.ts +2 -0
  306. package/dist/tests/argo/ArgoGetTool.test.d.ts.map +1 -0
  307. package/dist/tests/argo/ArgoGetTool.test.js +141 -0
  308. package/dist/tests/argo/ArgoGetTool.test.js.map +1 -0
  309. package/dist/tests/helm/BaseTool.test.d.ts +2 -0
  310. package/dist/tests/helm/BaseTool.test.d.ts.map +1 -0
  311. package/dist/tests/helm/BaseTool.test.js +241 -0
  312. package/dist/tests/helm/BaseTool.test.js.map +1 -0
  313. package/dist/tests/index.test.d.ts +2 -0
  314. package/dist/tests/index.test.d.ts.map +1 -0
  315. package/dist/tests/index.test.js +7 -0
  316. package/dist/tests/index.test.js.map +1 -0
  317. package/dist/tests/kubernetes/ConfigMapOperations.test.d.ts +2 -0
  318. package/dist/tests/kubernetes/ConfigMapOperations.test.d.ts.map +1 -0
  319. package/dist/tests/kubernetes/ConfigMapOperations.test.js +460 -0
  320. package/dist/tests/kubernetes/ConfigMapOperations.test.js.map +1 -0
  321. package/dist/tests/kubernetes/ConnectionManager.test.d.ts +2 -0
  322. package/dist/tests/kubernetes/ConnectionManager.test.d.ts.map +1 -0
  323. package/dist/tests/kubernetes/ConnectionManager.test.js +97 -0
  324. package/dist/tests/kubernetes/ConnectionManager.test.js.map +1 -0
  325. package/dist/tests/kubernetes/ConnectionPool.test.d.ts +2 -0
  326. package/dist/tests/kubernetes/ConnectionPool.test.d.ts.map +1 -0
  327. package/dist/tests/kubernetes/ConnectionPool.test.js +328 -0
  328. package/dist/tests/kubernetes/ConnectionPool.test.js.map +1 -0
  329. package/dist/tests/kubernetes/DeploymentOperations.test.d.ts +2 -0
  330. package/dist/tests/kubernetes/DeploymentOperations.test.d.ts.map +1 -0
  331. package/dist/tests/kubernetes/DeploymentOperations.test.js +196 -0
  332. package/dist/tests/kubernetes/DeploymentOperations.test.js.map +1 -0
  333. package/dist/tests/kubernetes/ErrorHandling.test.d.ts +2 -0
  334. package/dist/tests/kubernetes/ErrorHandling.test.d.ts.map +1 -0
  335. package/dist/tests/kubernetes/ErrorHandling.test.js +329 -0
  336. package/dist/tests/kubernetes/ErrorHandling.test.js.map +1 -0
  337. package/dist/tests/kubernetes/GetPodMetricsTool.test.d.ts +2 -0
  338. package/dist/tests/kubernetes/GetPodMetricsTool.test.d.ts.map +1 -0
  339. package/dist/tests/kubernetes/GetPodMetricsTool.test.js +150 -0
  340. package/dist/tests/kubernetes/GetPodMetricsTool.test.js.map +1 -0
  341. package/dist/tests/kubernetes/KubernetesClient.test.d.ts +2 -0
  342. package/dist/tests/kubernetes/KubernetesClient.test.d.ts.map +1 -0
  343. package/dist/tests/kubernetes/KubernetesClient.test.js +371 -0
  344. package/dist/tests/kubernetes/KubernetesClient.test.js.map +1 -0
  345. package/dist/tests/kubernetes/MetricOperations.parsing.test.d.ts +2 -0
  346. package/dist/tests/kubernetes/MetricOperations.parsing.test.d.ts.map +1 -0
  347. package/dist/tests/kubernetes/MetricOperations.parsing.test.js +49 -0
  348. package/dist/tests/kubernetes/MetricOperations.parsing.test.js.map +1 -0
  349. package/dist/tests/kubernetes/NamespaceOperations.test.d.ts +2 -0
  350. package/dist/tests/kubernetes/NamespaceOperations.test.d.ts.map +1 -0
  351. package/dist/tests/kubernetes/NamespaceOperations.test.js +115 -0
  352. package/dist/tests/kubernetes/NamespaceOperations.test.js.map +1 -0
  353. package/dist/tests/kubernetes/PodOperations.test.d.ts +2 -0
  354. package/dist/tests/kubernetes/PodOperations.test.d.ts.map +1 -0
  355. package/dist/tests/kubernetes/PodOperations.test.js +209 -0
  356. package/dist/tests/kubernetes/PodOperations.test.js.map +1 -0
  357. package/dist/tests/kubernetes/RetryStrategy.test.d.ts +2 -0
  358. package/dist/tests/kubernetes/RetryStrategy.test.d.ts.map +1 -0
  359. package/dist/tests/kubernetes/RetryStrategy.test.js +419 -0
  360. package/dist/tests/kubernetes/RetryStrategy.test.js.map +1 -0
  361. package/dist/tests/kubernetes/ServiceOperations.test.d.ts +2 -0
  362. package/dist/tests/kubernetes/ServiceOperations.test.d.ts.map +1 -0
  363. package/dist/tests/kubernetes/ServiceOperations.test.js +159 -0
  364. package/dist/tests/kubernetes/ServiceOperations.test.js.map +1 -0
  365. package/dist/tests/plugins/KubernetesToolsPlugin.test.d.ts +2 -0
  366. package/dist/tests/plugins/KubernetesToolsPlugin.test.d.ts.map +1 -0
  367. package/dist/tests/plugins/KubernetesToolsPlugin.test.js +153 -0
  368. package/dist/tests/plugins/KubernetesToolsPlugin.test.js.map +1 -0
  369. package/dist/tests/server/MCPServer.integration.test.d.ts +2 -0
  370. package/dist/tests/server/MCPServer.integration.test.d.ts.map +1 -0
  371. package/dist/tests/server/MCPServer.integration.test.js +244 -0
  372. package/dist/tests/server/MCPServer.integration.test.js.map +1 -0
  373. package/dist/tests/server/MCPServer.test.d.ts +2 -0
  374. package/dist/tests/server/MCPServer.test.d.ts.map +1 -0
  375. package/dist/tests/server/MCPServer.test.js +257 -0
  376. package/dist/tests/server/MCPServer.test.js.map +1 -0
  377. package/package.json +85 -0
  378. package/src/cli/cli.ts +25 -0
  379. package/src/cli/run-command.js +391 -0
  380. package/src/index.ts +46 -0
  381. package/src/kubernetes/BaseResourceOperations.ts +286 -0
  382. package/src/kubernetes/CircuitBreaker.ts +485 -0
  383. package/src/kubernetes/ConnectionManager.ts +114 -0
  384. package/src/kubernetes/ConnectionPool.ts +551 -0
  385. package/src/kubernetes/ErrorHandler.ts +436 -0
  386. package/src/kubernetes/ErrorHandling.ts +401 -0
  387. package/src/kubernetes/KubernetesClient.ts +500 -0
  388. package/src/kubernetes/README.md +349 -0
  389. package/src/kubernetes/ResourceOperations.ts +116 -0
  390. package/src/kubernetes/RetryStrategy.ts +365 -0
  391. package/src/kubernetes/RetryableOperation.ts +313 -0
  392. package/src/kubernetes/docs/ResourceOperations.md +606 -0
  393. package/src/kubernetes/index.ts +116 -0
  394. package/src/kubernetes/resources/ConfigMapOperations.ts +367 -0
  395. package/src/kubernetes/resources/CustomResourceOperations.ts +392 -0
  396. package/src/kubernetes/resources/DeploymentOperations.ts +294 -0
  397. package/src/kubernetes/resources/IngressOperations.ts +277 -0
  398. package/src/kubernetes/resources/MetricOperations.ts +1159 -0
  399. package/src/kubernetes/resources/NamespaceOperations.ts +129 -0
  400. package/src/kubernetes/resources/PersistentVolumeClaimOperations.ts +516 -0
  401. package/src/kubernetes/resources/PersistentVolumeOperations.ts +438 -0
  402. package/src/kubernetes/resources/PodOperations.ts +417 -0
  403. package/src/kubernetes/resources/SecretOperations.ts +304 -0
  404. package/src/kubernetes/resources/ServiceOperations.ts +283 -0
  405. package/src/kubernetes/utils/ResourceUtils.ts +553 -0
  406. package/src/plugins/ArgoCDToolsPlugin.ts +189 -0
  407. package/src/plugins/ArgoToolsPlugin.ts +180 -0
  408. package/src/plugins/HelmToolsPlugin.ts +180 -0
  409. package/src/plugins/KubernetesToolsPlugin.ts +198 -0
  410. package/src/plugins/SamplePlugin.ts +60 -0
  411. package/src/plugins/index.ts +4 -0
  412. package/src/server/MCPServer.ts +500 -0
  413. package/src/tools/argo/ArgoCronListTool.ts +78 -0
  414. package/src/tools/argo/ArgoGetTool.ts +91 -0
  415. package/src/tools/argo/ArgoListTool.ts +143 -0
  416. package/src/tools/argo/ArgoLogsTool.ts +131 -0
  417. package/src/tools/argo/BaseTool.ts +69 -0
  418. package/src/tools/argo/index.ts +6 -0
  419. package/src/tools/argocd/ArgoCDAppGetTool.ts +109 -0
  420. package/src/tools/argocd/ArgoCDAppHistoryTool.ts +91 -0
  421. package/src/tools/argocd/ArgoCDAppListTool.ts +144 -0
  422. package/src/tools/argocd/ArgoCDAppLogsTool.ts +162 -0
  423. package/src/tools/argocd/ArgoCDAppResourcesTool.ts +139 -0
  424. package/src/tools/argocd/BaseTool.ts +83 -0
  425. package/src/tools/argocd/index.ts +7 -0
  426. package/src/tools/helm/BaseTool.ts +60 -0
  427. package/src/tools/helm/HelmGetHooksTool.ts +44 -0
  428. package/src/tools/helm/HelmGetManifestTool.ts +44 -0
  429. package/src/tools/helm/HelmGetNotesTool.ts +44 -0
  430. package/src/tools/helm/HelmGetResourcesTool.ts +140 -0
  431. package/src/tools/helm/HelmGetValuesTool.ts +62 -0
  432. package/src/tools/helm/HelmHistoryTool.ts +56 -0
  433. package/src/tools/helm/HelmListTool.ts +107 -0
  434. package/src/tools/helm/HelmListWithResourcesTool.ts +194 -0
  435. package/src/tools/helm/HelmStatusTool.ts +62 -0
  436. package/src/tools/helm/index.ts +11 -0
  437. package/src/tools/kubernetes/BaseTool.ts +76 -0
  438. package/src/tools/kubernetes/GetConfigMapTool.ts +33 -0
  439. package/src/tools/kubernetes/GetContainerLogsTool.ts +140 -0
  440. package/src/tools/kubernetes/GetDeploymentsTool.ts +33 -0
  441. package/src/tools/kubernetes/GetEventsTool.ts +133 -0
  442. package/src/tools/kubernetes/GetIngressTool.ts +39 -0
  443. package/src/tools/kubernetes/GetMetricsTool.ts +53 -0
  444. package/src/tools/kubernetes/GetNamespacesTool.ts +36 -0
  445. package/src/tools/kubernetes/GetPersistentVolumeClaimsTool.ts +113 -0
  446. package/src/tools/kubernetes/GetPersistentVolumesTool.ts +107 -0
  447. package/src/tools/kubernetes/GetPodMetricsTool.ts +113 -0
  448. package/src/tools/kubernetes/GetPodsTool.ts +39 -0
  449. package/src/tools/kubernetes/GetResourceTool.ts +90 -0
  450. package/src/tools/kubernetes/GetSecretsTool.ts +55 -0
  451. package/src/tools/kubernetes/GetServicesTool.ts +39 -0
  452. package/src/tools/kubernetes/index.ts +16 -0
  453. package/src/utils/CliUtils.ts +207 -0
  454. package/tsconfig.json +36 -0
@@ -0,0 +1,893 @@
1
+ import * as http from 'http'; // Import http module
2
+ import * as https from 'https'; // Import https module
3
+ import { URL } from 'url'; // Import URL for parsing
4
+ // Prometheus-related constants
5
+ const PROMETHEUS_ANNOTATION_SCRAPE = 'prometheus.io/scrape';
6
+ const PROMETHEUS_ANNOTATION_PATH = 'prometheus.io/path';
7
+ const PROMETHEUS_ANNOTATION_PORT = 'prometheus.io/port';
8
+ export class MetricOperations {
9
+ k8sClient;
10
+ logger;
11
+ static METRICS_API_GROUP = 'metrics.k8s.io';
12
+ static METRICS_API_VERSION = 'v1beta1';
13
+ discoveredPrometheusTargets = [];
14
+ constructor(k8sClient, logger) {
15
+ this.k8sClient = k8sClient;
16
+ this.logger = logger;
17
+ this.logger?.debug?.('MetricOperations initialized');
18
+ }
19
+ /**
20
+ * Fetches metrics for all nodes.
21
+ * @returns A promise that resolves to a list of node metrics.
22
+ */
23
+ async getNodeMetrics() {
24
+ this.logger?.debug?.('Fetching node metrics using CustomObjectsApi');
25
+ try {
26
+ const response = await this.k8sClient.customObjects.listClusterCustomObject({
27
+ group: MetricOperations.METRICS_API_GROUP,
28
+ version: MetricOperations.METRICS_API_VERSION,
29
+ plural: 'nodes',
30
+ });
31
+ return response.body;
32
+ }
33
+ catch (error) {
34
+ this.logger?.error('Error fetching node metrics:', error.message);
35
+ if (error.body) {
36
+ this.logger?.error('Error body:', JSON.stringify(error.body, null, 2));
37
+ }
38
+ return null;
39
+ }
40
+ }
41
+ /**
42
+ * Fetches metrics for a specific node.
43
+ * @param nodeName The name of the node.
44
+ * @returns A promise that resolves to the node's metrics.
45
+ */
46
+ async getNodeMetricsByName(nodeName) {
47
+ this.logger?.debug?.(`Fetching metrics for node: ${nodeName} using CustomObjectsApi`);
48
+ try {
49
+ const response = await this.k8sClient.customObjects.getClusterCustomObject({
50
+ group: MetricOperations.METRICS_API_GROUP,
51
+ version: MetricOperations.METRICS_API_VERSION,
52
+ plural: 'nodes',
53
+ name: nodeName,
54
+ });
55
+ return response.body;
56
+ }
57
+ catch (error) {
58
+ this.logger?.error(`Error fetching metrics for node ${nodeName}:`, error.message);
59
+ if (error.body) {
60
+ this.logger?.error('Error body:', JSON.stringify(error.body, null, 2));
61
+ }
62
+ return null;
63
+ }
64
+ }
65
+ /**
66
+ * Helper: List all node names in the cluster
67
+ */
68
+ async listNodes() {
69
+ try {
70
+ const nodes = await this.k8sClient.core.listNode();
71
+ return nodes.items
72
+ .map((n) => n.metadata?.name)
73
+ .filter(Boolean);
74
+ }
75
+ catch (e) {
76
+ this.logger?.error('Failed to list nodes for kubelet summary fallback:', e);
77
+ return [];
78
+ }
79
+ }
80
+ /**
81
+ * Helper: Convert kubelet summary pod stats to PodMetrics format
82
+ */
83
+ convertSummaryPodToPodMetrics(pod) {
84
+ // Kubelet summary pod object: https://github.com/kubernetes/kubernetes/blob/master/pkg/kubelet/apis/stats/v1alpha1/types.go
85
+ // We'll map the fields as best as possible
86
+ const containers = (pod.containers || []).map((c) => ({
87
+ name: c.name,
88
+ usage: {
89
+ cpu: c.cpu?.usageNanoCores ? `${c.cpu.usageNanoCores}n` : '0',
90
+ memory: c.memory?.usageBytes ? `${c.memory.usageBytes}` : '0',
91
+ },
92
+ }));
93
+ return {
94
+ kind: 'PodMetrics',
95
+ apiVersion: 'metrics.k8s.io/v1beta1',
96
+ metadata: {
97
+ name: pod.podRef.name,
98
+ namespace: pod.podRef.namespace,
99
+ // selfLink and creationTimestamp not available
100
+ },
101
+ timestamp: pod.startTime || new Date().toISOString(),
102
+ window: '30s', // Not available in summary, use default
103
+ containers,
104
+ };
105
+ }
106
+ /**
107
+ * Helper: Fetch pod metrics from kubelet summary API for all nodes
108
+ */
109
+ async getPodMetricsFromKubeletSummary(namespace) {
110
+ const nodeNames = await this.listNodes();
111
+ const allPodMetrics = [];
112
+ for (const nodeName of nodeNames) {
113
+ try {
114
+ // Use the Kubernetes API proxy to access the kubelet summary endpoint
115
+ const summary = await this.k8sClient.getRaw(`/api/v1/nodes/${nodeName}/proxy/stats/summary`);
116
+ if (summary && summary.pods) {
117
+ for (const pod of summary.pods) {
118
+ if (!namespace || pod.podRef.namespace === namespace) {
119
+ allPodMetrics.push(this.convertSummaryPodToPodMetrics(pod));
120
+ }
121
+ }
122
+ }
123
+ }
124
+ catch (e) {
125
+ this.logger?.warn(`Failed to fetch kubelet summary for node ${nodeName}: ${e}`);
126
+ }
127
+ }
128
+ return allPodMetrics;
129
+ }
130
+ /**
131
+ * Helper: Fetch pod metrics from metrics.k8s.io API (original implementation)
132
+ */
133
+ async getPodMetricsFromMetricsApi(namespace) {
134
+ this.logger?.debug?.(`Fetching pod metrics for namespace: ${namespace || 'all'} using CustomObjectsApi`);
135
+ try {
136
+ let response;
137
+ if (namespace) {
138
+ response = await this.k8sClient.customObjects.listNamespacedCustomObject({
139
+ group: MetricOperations.METRICS_API_GROUP,
140
+ version: MetricOperations.METRICS_API_VERSION,
141
+ namespace: namespace,
142
+ plural: 'pods',
143
+ });
144
+ }
145
+ else {
146
+ this.logger?.debug?.('Fetching pod metrics for all namespaces using listClusterCustomObject.');
147
+ response = await this.k8sClient.customObjects.listClusterCustomObject({
148
+ group: MetricOperations.METRICS_API_GROUP,
149
+ version: MetricOperations.METRICS_API_VERSION,
150
+ plural: 'pods',
151
+ });
152
+ }
153
+ return response.body;
154
+ }
155
+ catch (error) {
156
+ this.logger?.error('Error fetching pod metrics from metrics.k8s.io:', error.message);
157
+ if (error.body) {
158
+ this.logger?.error('Error body:', JSON.stringify(error.body, null, 2));
159
+ }
160
+ return null;
161
+ }
162
+ }
163
+ /**
164
+ * Fetches metrics for all pods in a given namespace, or all namespaces if none is specified.
165
+ * Always tries both metrics.k8s.io and kubelet summary API, merging results.
166
+ * @param namespace Optional namespace to filter pods.
167
+ * @returns A promise that resolves to a list of pod metrics.
168
+ */
169
+ async getPodMetrics(namespace) {
170
+ // Attempt 1: metrics.k8s.io API
171
+ const metricsApi = await this.getPodMetricsFromMetricsApi(namespace);
172
+ if (metricsApi && metricsApi.items && metricsApi.items.length > 0) {
173
+ // Primary source succeeded – return as‑is, no merging with kubelet
174
+ return metricsApi;
175
+ }
176
+ // Attempt 2 (fallback): Kubelet summary API
177
+ const kubeletMetrics = await this.getPodMetricsFromKubeletSummary(namespace);
178
+ if (kubeletMetrics && kubeletMetrics.length > 0) {
179
+ return {
180
+ kind: 'PodMetricsList',
181
+ apiVersion: 'metrics.k8s.io/v1beta1',
182
+ metadata: {},
183
+ items: kubeletMetrics,
184
+ };
185
+ }
186
+ // No data from either source
187
+ return null;
188
+ }
189
+ /**
190
+ * Fetches metrics for a specific pod in a given namespace.
191
+ * Uses the namespace-wide getPodMetrics method and filters for the specific pod.
192
+ * This approach is more reliable than direct pod metric API calls.
193
+ * @param podName The name of the pod.
194
+ * @param namespace The namespace of the pod.
195
+ * @returns A promise that resolves to the pod's metrics.
196
+ */
197
+ async getPodMetricsByName(podName, namespace) {
198
+ this.logger?.debug?.(`Fetching metrics for pod: ${podName} in namespace ${namespace}`);
199
+ try {
200
+ // Use the robust getPodMetrics method which handles all fallbacks
201
+ const podMetricsList = await this.getPodMetrics(namespace);
202
+ if (podMetricsList && podMetricsList.items && podMetricsList.items.length > 0) {
203
+ // Find the specific pod in the list
204
+ const foundPod = podMetricsList.items.find((pod) => pod.metadata.name === podName &&
205
+ (pod.metadata.namespace === namespace || pod.metadata.namespace === undefined));
206
+ if (foundPod) {
207
+ this.logger?.debug?.(`Successfully found metrics for pod ${podName} in namespace ${namespace}`);
208
+ return foundPod;
209
+ }
210
+ else {
211
+ this.logger?.debug?.(`Pod ${podName} not found in metrics list for namespace ${namespace}`);
212
+ this.logger?.debug?.(`Available pods in namespace: ${podMetricsList.items.map((p) => p.metadata.name).join(', ')}`);
213
+ }
214
+ }
215
+ else {
216
+ this.logger?.debug?.(`No pod metrics available in namespace ${namespace}`);
217
+ }
218
+ }
219
+ catch (error) {
220
+ this.logger?.error(`Error fetching metrics for pod ${podName} in namespace ${namespace}: ${error.message}`);
221
+ }
222
+ return null;
223
+ }
224
+ /**
225
+ * Discovers Prometheus targets by scanning services for specific annotations.
226
+ * @param namespace Optional namespace to scan. If not provided, scans all namespaces.
227
+ */
228
+ async discoverPrometheusTargets(namespace) {
229
+ this.logger?.debug?.(`Starting Prometheus target discovery in namespace: ${namespace || 'all'}`);
230
+ const newTargets = [];
231
+ try {
232
+ let serviceList; // serviceList will directly be V1ServiceList
233
+ if (namespace) {
234
+ // Assuming the method directly returns V1ServiceList
235
+ serviceList = await this.k8sClient.core.listNamespacedService({ namespace });
236
+ }
237
+ else {
238
+ serviceList = await this.k8sClient.core.listServiceForAllNamespaces();
239
+ }
240
+ // Now serviceList is V1ServiceList, so access .items directly.
241
+ if (serviceList && serviceList.items) {
242
+ for (const service of serviceList.items) {
243
+ const metadata = service.metadata;
244
+ const annotations = metadata?.annotations;
245
+ if (annotations && annotations[PROMETHEUS_ANNOTATION_SCRAPE] === 'true') {
246
+ const serviceName = metadata?.name;
247
+ const serviceNamespace = metadata?.namespace;
248
+ const clusterIP = service.spec?.clusterIP;
249
+ if (!serviceName || !serviceNamespace || !clusterIP || clusterIP === 'None') {
250
+ this.logger?.debug?.(`Skipping Prometheus target for service ${serviceName || 'unknown'} in ${serviceNamespace || 'unknown'} due to missing name, namespace, or ClusterIP.`);
251
+ continue;
252
+ }
253
+ const path = annotations[PROMETHEUS_ANNOTATION_PATH] || '/metrics';
254
+ let portString = annotations[PROMETHEUS_ANNOTATION_PORT];
255
+ if (!portString && service.spec?.ports && service.spec.ports.length > 0) {
256
+ const httpPort = service.spec.ports.find((p) => p.name === 'http' || p.name === 'metrics');
257
+ portString = httpPort ? String(httpPort.port) : String(service.spec.ports[0].port);
258
+ }
259
+ if (!portString) {
260
+ this.logger?.warn(`Could not determine port for Prometheus target ${serviceName} in ${serviceNamespace}. Skipping.`);
261
+ continue;
262
+ }
263
+ const targetUrl = `http://${clusterIP}:${portString}${path.startsWith('/') ? path : '/' + path}`;
264
+ const newTarget = {
265
+ url: targetUrl,
266
+ serviceName: serviceName,
267
+ namespace: serviceNamespace,
268
+ };
269
+ newTargets.push(newTarget);
270
+ this.logger?.debug?.(`Discovered Prometheus target: ${newTarget.url} from service ${serviceNamespace}/${serviceName}`);
271
+ }
272
+ }
273
+ }
274
+ }
275
+ catch (error) {
276
+ this.logger?.error(`Error discovering Prometheus targets: ${error.message}`, error);
277
+ // Depending on desired behavior, might re-throw or return empty/partial list
278
+ }
279
+ this.discoveredPrometheusTargets = newTargets; // Replace or merge as needed
280
+ this.logger?.debug?.(`Prometheus target discovery finished. Found ${newTargets.length} targets.`);
281
+ return this.discoveredPrometheusTargets;
282
+ }
283
+ /**
284
+ * Queries a single Prometheus target.
285
+ * @param target The Prometheus target to query.
286
+ * @param promqlQuery The PromQL query string.
287
+ * @returns A promise that resolves to the parsed JSON response from Prometheus.
288
+ */
289
+ async queryPrometheusTarget(target, promqlQuery) {
290
+ const rawQueryUrl = `${target.url.replace(/\/$/, '')}/api/v1/query?query=${encodeURIComponent(promqlQuery)}`;
291
+ this.logger?.debug?.(`Querying Prometheus target: ${rawQueryUrl}`);
292
+ return new Promise((resolve, _reject) => {
293
+ const parsedUrl = new URL(rawQueryUrl);
294
+ const options = {
295
+ method: 'GET',
296
+ headers: {
297
+ Accept: 'application/json',
298
+ },
299
+ rejectUnauthorized: false,
300
+ };
301
+ const client = parsedUrl.protocol === 'https:' ? https : http;
302
+ const req = client.request(parsedUrl, options, (res) => {
303
+ let rawData = '';
304
+ res.setEncoding('utf8');
305
+ res.on('data', (chunk) => {
306
+ rawData += chunk;
307
+ });
308
+ res.on('end', () => {
309
+ if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
310
+ try {
311
+ const parsedData = JSON.parse(rawData);
312
+ this.logger?.debug?.(`Successfully queried Prometheus target ${target.url} for query: ${promqlQuery}`);
313
+ resolve(parsedData);
314
+ }
315
+ catch (parseError) {
316
+ this.logger?.error(`Error parsing JSON response from ${target.url}: ${parseError.message}`, parseError);
317
+ resolve(null); // Or reject, depending on desired error handling for parsing issues
318
+ }
319
+ }
320
+ else {
321
+ this.logger?.error(`Error querying Prometheus target ${target.url}: ${res.statusCode} ${res.statusMessage}`);
322
+ this.logger?.error(`Prometheus error response body: ${rawData}`);
323
+ resolve(null); // Or reject for HTTP errors
324
+ }
325
+ });
326
+ });
327
+ req.on('error', (error) => {
328
+ this.logger?.error(`Exception querying Prometheus target ${target.url}: ${error.message}`, error);
329
+ resolve(null); // Or reject for request errors
330
+ });
331
+ req.end();
332
+ });
333
+ }
334
+ /**
335
+ * Fetches metrics from all discovered Prometheus targets for a given query.
336
+ * This is a high-level method that would orchestrate discovery and querying.
337
+ * @param promqlQuery The PromQL query to execute on all targets.
338
+ * @returns A promise that resolves to an array of results from each target.
339
+ */
340
+ async getPrometheusMetrics(promqlQuery) {
341
+ if (this.discoveredPrometheusTargets.length === 0) {
342
+ this.logger?.debug?.('No Prometheus targets discovered. Attempting discovery now.');
343
+ await this.discoverPrometheusTargets(); // Discover if not already done
344
+ if (this.discoveredPrometheusTargets.length === 0) {
345
+ this.logger?.warn('Still no Prometheus targets found after discovery. Cannot query metrics.');
346
+ return [];
347
+ }
348
+ }
349
+ const allResults = [];
350
+ for (const target of this.discoveredPrometheusTargets) {
351
+ const result = await this.queryPrometheusTarget(target, promqlQuery);
352
+ if (result) {
353
+ allResults.push({ target: target.url, data: result });
354
+ }
355
+ }
356
+ return allResults;
357
+ }
358
+ // Helper function to parse K8s resource strings like "100m" or "128974848n" for CPU
359
+ // and "64Mi" or "128974848" for memory into numerical values (cores and bytes).
360
+ parseK8sCpuString(cpuString) {
361
+ if (!cpuString)
362
+ return undefined;
363
+ let value;
364
+ if (cpuString.endsWith('n')) {
365
+ // nanocores
366
+ value = parseFloat(cpuString) / 1e9;
367
+ }
368
+ else if (cpuString.endsWith('u')) {
369
+ // microcores
370
+ value = parseFloat(cpuString) / 1e6;
371
+ }
372
+ else if (cpuString.endsWith('m')) {
373
+ // millicores
374
+ value = parseFloat(cpuString) / 1e3;
375
+ }
376
+ else {
377
+ value = parseFloat(cpuString); // Assuming cores
378
+ }
379
+ return isNaN(value) ? undefined : value; // Return undefined if parsing failed
380
+ }
381
+ parseK8sMemoryString(memoryString) {
382
+ if (!memoryString)
383
+ return undefined;
384
+ const suffixes = {
385
+ Ki: 1024,
386
+ Mi: 1024 ** 2,
387
+ Gi: 1024 ** 3,
388
+ Ti: 1024 ** 4,
389
+ Pi: 1024 ** 5,
390
+ Ei: 1024 ** 6,
391
+ K: 1000,
392
+ M: 1000 ** 2,
393
+ G: 1000 ** 3,
394
+ T: 1000 ** 4,
395
+ P: 1000 ** 5,
396
+ E: 1000 ** 6,
397
+ };
398
+ const match = memoryString.match(/^(\d+\.?\d*|\.\d+)([KMGTPE]i?)?$/); // Allow decimals
399
+ if (!match) {
400
+ const numericValue = parseFloat(memoryString);
401
+ return isNaN(numericValue) ? undefined : numericValue; // Assuming bytes if no suffix and numeric
402
+ }
403
+ const value = parseFloat(match[1]);
404
+ if (isNaN(value))
405
+ return undefined; // Parsing of numeric part failed
406
+ const suffix = match[2];
407
+ if (suffix && suffixes[suffix]) {
408
+ return value * suffixes[suffix];
409
+ }
410
+ return value; // Bytes
411
+ }
412
+ /**
413
+ * Normalizes and merges metrics from different sources.
414
+ * This is a placeholder and will need actual implementation logic.
415
+ * @param nodeMetricsRaw Raw node metrics from Metrics Server.
416
+ * @param podMetricsRaw Raw pod metrics from Metrics Server.
417
+ * @param prometheusMetricsRaw Raw metrics from Prometheus (array of results from getPrometheusMetrics).
418
+ * @param allPodsRaw Optional: Full pod list for enrichment
419
+ * @returns An object containing lists of normalized node and pod metrics.
420
+ */
421
+ async normalizeAndMergeMetrics(nodeMetricsRaw, podMetricsRaw, prometheusMetricsRaw, // This will be an array of Prometheus query results
422
+ allPodsRaw) {
423
+ this.logger?.debug?.('Starting metrics normalization and merging...');
424
+ const normalizedNodes = [];
425
+ const normalizedPods = [];
426
+ try {
427
+ // Add a try-catch block for the whole normalization process
428
+ // Create a map for quick pod spec lookup if allPodsRaw is provided
429
+ const podSpecMap = new Map();
430
+ if (allPodsRaw && allPodsRaw.items) {
431
+ for (const pod of allPodsRaw.items) {
432
+ if (pod.metadata?.uid) {
433
+ podSpecMap.set(pod.metadata.uid, pod);
434
+ }
435
+ }
436
+ }
437
+ // Normalize NodeMetrics from Metrics Server
438
+ if (nodeMetricsRaw && Array.isArray(nodeMetricsRaw.items)) {
439
+ for (const rawNode of nodeMetricsRaw.items) {
440
+ normalizedNodes.push({
441
+ name: rawNode.metadata.name,
442
+ uid: rawNode.metadata.name, // Use name as fallback UID
443
+ timestamp: rawNode.timestamp,
444
+ window: rawNode.window,
445
+ usage: {
446
+ cpuCores: this.parseK8sCpuString(rawNode.usage.cpu),
447
+ memoryBytes: this.parseK8sMemoryString(rawNode.usage.memory),
448
+ },
449
+ customMetrics: [], // Initialize for Prometheus metrics
450
+ });
451
+ }
452
+ }
453
+ // Normalize PodMetrics from Metrics Server
454
+ if (podMetricsRaw && Array.isArray(podMetricsRaw.items)) {
455
+ for (const rawPod of podMetricsRaw.items) {
456
+ const containers = rawPod.containers.map((c) => ({
457
+ name: c.name,
458
+ usage: {
459
+ cpuCores: this.parseK8sCpuString(c.usage.cpu),
460
+ memoryBytes: this.parseK8sMemoryString(c.usage.memory),
461
+ },
462
+ }));
463
+ // Sum container usage for pod-level usage if not directly available or to ensure consistency
464
+ const podUsage = containers.reduce((acc, curr) => {
465
+ return {
466
+ cpuCores: (acc.cpuCores || 0) + (curr.usage.cpuCores || 0),
467
+ memoryBytes: (acc.memoryBytes || 0) + (curr.usage.memoryBytes || 0),
468
+ };
469
+ }, { cpuCores: 0, memoryBytes: 0 });
470
+ // Use name and namespace as fallback UID
471
+ const podUID = `${rawPod.metadata.namespace || 'default'}:${rawPod.metadata.name}`;
472
+ let nodeNameFromSpec = undefined;
473
+ if (podUID) {
474
+ // Try to find matching pod spec by UID if available
475
+ const podSpec = podSpecMap.get(podUID);
476
+ if (podSpec) {
477
+ nodeNameFromSpec = podSpec.spec?.nodeName;
478
+ }
479
+ else {
480
+ // Fallback: try to match by name and namespace if UID from metrics isn't reliable
481
+ if (allPodsRaw &&
482
+ allPodsRaw.items &&
483
+ rawPod.metadata.name &&
484
+ rawPod.metadata.namespace) {
485
+ const fallbackPodSpec = allPodsRaw.items.find((p) => p.metadata?.name === rawPod.metadata.name &&
486
+ p.metadata?.namespace === rawPod.metadata.namespace);
487
+ if (fallbackPodSpec) {
488
+ nodeNameFromSpec = fallbackPodSpec.spec?.nodeName;
489
+ }
490
+ }
491
+ }
492
+ }
493
+ normalizedPods.push({
494
+ name: rawPod.metadata.name,
495
+ namespace: rawPod.metadata.namespace || 'unknown',
496
+ uid: podUID,
497
+ nodeName: nodeNameFromSpec,
498
+ timestamp: rawPod.timestamp,
499
+ window: rawPod.window,
500
+ usage: podUsage,
501
+ containers: containers,
502
+ customMetrics: [], // Initialize for Prometheus metrics
503
+ });
504
+ }
505
+ }
506
+ // TODO: Implement merging of Prometheus metrics
507
+ // This will involve iterating prometheusMetricsRaw, parsing PromQL results,
508
+ // and matching them to the correct normalizedNodes or normalizedPods based on labels (e.g., node name, pod name, namespace).
509
+ this.logger?.debug?.(`Prometheus metrics to merge: ${prometheusMetricsRaw.length} results.`);
510
+ for (const promResult of prometheusMetricsRaw) {
511
+ if (promResult &&
512
+ promResult.status === 'success' &&
513
+ promResult.data &&
514
+ promResult.data.result) {
515
+ for (const metric of promResult.data.result) {
516
+ // --- Map Prometheus resultType to accepted metric kinds -----------------
517
+ const metricTypeMap = {
518
+ gauge: 'gauge',
519
+ counter: 'counter',
520
+ histogram: 'histogram',
521
+ summary: 'summary',
522
+ untyped: 'untyped',
523
+ vector: 'gauge',
524
+ matrix: 'gauge',
525
+ scalar: 'gauge',
526
+ string: 'untyped',
527
+ };
528
+ const mappedType = metricTypeMap[promResult.data.resultType ?? ''] ?? 'untyped';
529
+ const metricName = metric.metric.__name__ || 'unknown_metric';
530
+ const valueParsed = parseFloat(metric.value[1]); // [timestamp, value]
531
+ if (Number.isNaN(valueParsed)) {
532
+ // Skip this metric if the value isn't a finite number
533
+ continue;
534
+ }
535
+ const value = valueParsed;
536
+ const labels = { ...metric.metric };
537
+ delete labels.__name__;
538
+ const customMetric = {
539
+ name: metricName,
540
+ value: value,
541
+ labels: labels,
542
+ type: mappedType,
543
+ };
544
+ // Example: Attempt to match to a node
545
+ if (labels.node) {
546
+ const node = normalizedNodes.find((n) => n.name === labels.node);
547
+ if (node) {
548
+ node.customMetrics?.push(customMetric);
549
+ }
550
+ }
551
+ else if (labels.pod_name && labels.namespace) {
552
+ // Or a pod
553
+ const pod = normalizedPods.find((p) => p.name === labels.pod_name && p.namespace === labels.namespace);
554
+ if (pod) {
555
+ pod.customMetrics?.push(customMetric);
556
+ }
557
+ }
558
+ else if (labels.pod && labels.namespace) {
559
+ // k8s_pod_name from cAdvisor via Prometheus
560
+ const pod = normalizedPods.find((p) => p.name === labels.pod && p.namespace === labels.namespace);
561
+ if (pod) {
562
+ pod.customMetrics?.push(customMetric);
563
+ }
564
+ }
565
+ // Add more matching logic as needed based on common Prometheus label conventions for K8s
566
+ }
567
+ }
568
+ }
569
+ this.logger?.debug?.('Metrics normalization and merging finished.');
570
+ return { nodesMetrics: normalizedNodes, podsMetrics: normalizedPods };
571
+ }
572
+ catch (error) {
573
+ this.logger?.error(`Critical error during metrics normalization and merging: ${error.message}`, error);
574
+ // Depending on desired behavior, might re-throw or return empty/partial normalized lists
575
+ // For now, return empty lists to indicate failure but not crash the caller.
576
+ return { nodesMetrics: [], podsMetrics: [], error: error.message };
577
+ }
578
+ }
579
+ /**
580
+ * Fetches all relevant metrics (Metrics Server, Prometheus), optionally enriches with pod specs,
581
+ * and returns them in a normalized and merged format.
582
+ *
583
+ * This is a high-level convenience method.
584
+ *
585
+ * @param prometheusQueries An array of PromQL queries to execute against discovered Prometheus targets.
586
+ * @param fetchPodSpecs If true, fetches all pod specifications to enrich normalized pod metrics with nodeName. Defaults to true.
587
+ * @param discoveryNamespace Optional namespace to restrict Prometheus discovery and pod spec fetching.
588
+ * @returns A promise that resolves to an object containing lists of normalized node and pod metrics.
589
+ */
590
+ async getAllNormalizedMetrics(prometheusQueries, fetchPodSpecs = true, discoveryNamespace) {
591
+ this.logger?.debug?.('Starting high-level metric gathering using sequential sources (Metrics API ➔ Prometheus ➔ Kubelet)...');
592
+ /* -----------------------------------------------------------
593
+ * 0) Optionally fetch full Pod specs for later enrichment
594
+ * -------------------------------------------------------- */
595
+ let allPodsRaw = null;
596
+ if (fetchPodSpecs) {
597
+ try {
598
+ this.logger?.debug?.('Fetching all pod specs for enrichment...');
599
+ if (discoveryNamespace) {
600
+ if (typeof this.k8sClient.core.listNamespacedPod === 'function') {
601
+ allPodsRaw = await this.k8sClient.core.listNamespacedPod({
602
+ namespace: discoveryNamespace,
603
+ });
604
+ }
605
+ else {
606
+ this.logger?.warn('this.k8sClient.core.listNamespacedPod is not a function. Skipping pod spec fetch.');
607
+ }
608
+ }
609
+ else {
610
+ if (typeof this.k8sClient.core.listPodForAllNamespaces === 'function') {
611
+ allPodsRaw = await this.k8sClient.core.listPodForAllNamespaces();
612
+ }
613
+ else {
614
+ this.logger?.warn('this.k8sClient.core.listPodForAllNamespaces is not a function. Skipping pod spec fetch.');
615
+ }
616
+ }
617
+ this.logger?.debug?.(`Fetched ${allPodsRaw?.items?.length || 0} pod specs.`);
618
+ }
619
+ catch (error) {
620
+ this.logger?.error(`Error fetching pod specs: ${error.message}`, error);
621
+ }
622
+ }
623
+ /* -----------------------------------------------------------
624
+ * 1) Metrics Server (/apis/metrics.k8s.io/v1beta1)
625
+ * -------------------------------------------------------- */
626
+ let nodeMetricsRaw = null;
627
+ let podMetricsRaw = null;
628
+ // Try to get node metrics directly via customObjects API
629
+ try {
630
+ this.logger?.debug?.('Attempting to fetch node metrics from metrics.k8s.io API...');
631
+ nodeMetricsRaw = await this.getNodeMetrics();
632
+ if (nodeMetricsRaw) {
633
+ this.logger?.debug?.(`Successfully fetched metrics for ${nodeMetricsRaw?.items?.length || 0} nodes.`);
634
+ }
635
+ else {
636
+ this.logger?.warn('Node metrics API returned null or undefined response.');
637
+ }
638
+ }
639
+ catch (error) {
640
+ this.logger?.warn(`Error fetching node metrics from metrics.k8s.io API: ${error.message}`);
641
+ // Try direct API endpoint access for Rancher Desktop and similar environments
642
+ try {
643
+ this.logger?.debug?.('Attempting direct API endpoint access for node metrics...');
644
+ const directMetrics = await this.k8sClient.getRaw('/apis/metrics.k8s.io/v1beta1/nodes');
645
+ if (directMetrics && directMetrics.items) {
646
+ this.logger?.debug?.(`Successfully fetched metrics for ${directMetrics.items.length} nodes via direct API access.`);
647
+ nodeMetricsRaw = directMetrics;
648
+ }
649
+ }
650
+ catch (directError) {
651
+ this.logger?.warn(`Direct API access for node metrics failed: ${directError.message}`);
652
+ }
653
+ }
654
+ // Try to get pod metrics via customObjects API
655
+ try {
656
+ this.logger?.debug?.('Attempting to fetch pod metrics from metrics.k8s.io API...');
657
+ podMetricsRaw = await this.getPodMetricsFromMetricsApi(discoveryNamespace);
658
+ if (podMetricsRaw) {
659
+ this.logger?.debug?.(`Successfully fetched metrics for ${podMetricsRaw?.items?.length || 0} pods.`);
660
+ }
661
+ else {
662
+ this.logger?.warn('Pod metrics API returned null or undefined response.');
663
+ }
664
+ }
665
+ catch (error) {
666
+ this.logger?.warn(`Error fetching pod metrics from metrics.k8s.io API: ${error.message}`);
667
+ // Try direct API endpoint access for Rancher Desktop and similar environments
668
+ try {
669
+ this.logger?.debug?.('Attempting direct API endpoint access for pod metrics...');
670
+ const apiPath = discoveryNamespace
671
+ ? `/apis/metrics.k8s.io/v1beta1/namespaces/${discoveryNamespace}/pods`
672
+ : '/apis/metrics.k8s.io/v1beta1/pods';
673
+ const directMetrics = await this.k8sClient.getRaw(apiPath);
674
+ if (directMetrics && directMetrics.items) {
675
+ this.logger?.debug?.(`Successfully fetched metrics for ${directMetrics.items.length} pods via direct API access.`);
676
+ podMetricsRaw = directMetrics;
677
+ }
678
+ }
679
+ catch (directError) {
680
+ this.logger?.warn(`Direct API access for pod metrics failed: ${directError.message}`);
681
+ }
682
+ }
683
+ const metricsApiHasData = (nodeMetricsRaw?.items?.length ?? 0) > 0 || (podMetricsRaw?.items?.length ?? 0) > 0;
684
+ if (metricsApiHasData) {
685
+ this.logger?.debug?.('Returning metrics gathered from metrics.k8s.io API.');
686
+ return this.normalizeAndMergeMetrics(nodeMetricsRaw, podMetricsRaw, [], allPodsRaw);
687
+ }
688
+ /* -----------------------------------------------------------
689
+ * 2) Prometheus (if Metrics Server unavailable)
690
+ * -------------------------------------------------------- */
691
+ await this.discoverPrometheusTargets(discoveryNamespace);
692
+ const prometheusMetricsRaw = [];
693
+ for (const query of prometheusQueries) {
694
+ const results = await this.getPrometheusMetrics(query);
695
+ if (Array.isArray(results)) {
696
+ prometheusMetricsRaw.push(...results);
697
+ }
698
+ }
699
+ if (prometheusMetricsRaw.length > 0) {
700
+ this.logger?.debug?.('Returning metrics gathered from Prometheus targets.');
701
+ return this.normalizeAndMergeMetrics(null, null, prometheusMetricsRaw, allPodsRaw);
702
+ }
703
+ /* -----------------------------------------------------------
704
+ * 3) Kubelet /stats/summary (final fallback)
705
+ * -------------------------------------------------------- */
706
+ const kubeletPodMetrics = await this.getPodMetricsFromKubeletSummary(discoveryNamespace);
707
+ const podMetricsList = kubeletPodMetrics && kubeletPodMetrics.length > 0
708
+ ? {
709
+ kind: 'PodMetricsList',
710
+ apiVersion: 'metrics.k8s.io/v1beta1',
711
+ metadata: {},
712
+ items: kubeletPodMetrics,
713
+ }
714
+ : null;
715
+ if (podMetricsList) {
716
+ this.logger?.debug?.('Returning metrics gathered from kubelet summary fallback.');
717
+ }
718
+ else {
719
+ this.logger?.warn('Failed to gather metrics from any source; returning empty lists.');
720
+ }
721
+ return this.normalizeAndMergeMetrics(null, podMetricsList, [], allPodsRaw);
722
+ }
723
+ /**
724
+ * Get metrics with specific behavior for clean API calls.
725
+ * This method provides a more direct approach than getAllNormalizedMetrics for direct API access.
726
+ *
727
+ * @param prometheusQueries An array of PromQL queries to execute against discovered Prometheus targets.
728
+ * @param fetchPodSpecs If true, fetches all pod specifications to enrich normalized pod metrics with nodeName. Defaults to true.
729
+ * @param discoveryNamespace Optional namespace to restrict Prometheus discovery and pod spec fetching.
730
+ * @returns A promise that resolves to an object containing lists of normalized node and pod metrics.
731
+ */
732
+ async getMetricsWithOptions(prometheusQueries = [], fetchPodSpecs = true, discoveryNamespace, nodeApiPath = '/apis/metrics.k8s.io/v1beta1/nodes', podApiPath = '/apis/metrics.k8s.io/v1beta1/pods') {
733
+ // Try direct API calls first for better performance
734
+ try {
735
+ let nodeMetricsRaw = null;
736
+ let podMetricsRaw = null;
737
+ let allPodsRaw = null;
738
+ let errors = [];
739
+ // Get node metrics via direct API call
740
+ try {
741
+ nodeMetricsRaw = await this.k8sClient.getRaw(nodeApiPath);
742
+ this.logger?.debug?.(`Successfully fetched node metrics from ${nodeApiPath}`);
743
+ }
744
+ catch (error) {
745
+ const errorMsg = `Failed to get node metrics via API ${nodeApiPath}: ${error.message}`;
746
+ errors.push(errorMsg);
747
+ this.logger?.warn?.(errorMsg);
748
+ }
749
+ // Get pod metrics via direct API call
750
+ const podMetricsPath = discoveryNamespace
751
+ ? `/apis/metrics.k8s.io/v1beta1/namespaces/${discoveryNamespace}/pods`
752
+ : podApiPath;
753
+ try {
754
+ podMetricsRaw = await this.k8sClient.getRaw(podMetricsPath);
755
+ this.logger?.debug?.(`Successfully fetched pod metrics from ${podMetricsPath}`);
756
+ }
757
+ catch (error) {
758
+ const errorMsg = `Failed to get pod metrics via API ${podMetricsPath}: ${error.message}`;
759
+ errors.push(errorMsg);
760
+ this.logger?.warn?.(errorMsg);
761
+ }
762
+ // Get pod specs for enrichment if requested
763
+ if (fetchPodSpecs) {
764
+ try {
765
+ if (discoveryNamespace) {
766
+ allPodsRaw = await this.k8sClient.core.listNamespacedPod({
767
+ namespace: discoveryNamespace,
768
+ });
769
+ }
770
+ else {
771
+ allPodsRaw = await this.k8sClient.core.listPodForAllNamespaces();
772
+ }
773
+ this.logger?.debug?.(`Successfully fetched pod specs for enrichment`);
774
+ }
775
+ catch (error) {
776
+ const errorMsg = `Failed to get pod specs for enrichment: ${error.message}`;
777
+ errors.push(errorMsg);
778
+ this.logger?.warn?.(errorMsg);
779
+ }
780
+ }
781
+ // If we got metrics, normalize and return them
782
+ if ((nodeMetricsRaw && nodeMetricsRaw.items && nodeMetricsRaw.items.length > 0) ||
783
+ (podMetricsRaw && podMetricsRaw.items && podMetricsRaw.items.length > 0)) {
784
+ try {
785
+ const normalized = await this.normalizeAndMergeMetrics(nodeMetricsRaw, podMetricsRaw, [], allPodsRaw);
786
+ // Include partial errors if any occurred during API calls
787
+ const combinedError = errors.length > 0
788
+ ? normalized.error
789
+ ? `${normalized.error}; Additional errors: ${errors.join('; ')}`
790
+ : errors.join('; ')
791
+ : normalized.error;
792
+ return {
793
+ normalizedNodes: normalized.nodesMetrics,
794
+ normalizedPods: normalized.podsMetrics,
795
+ error: combinedError,
796
+ };
797
+ }
798
+ catch (normalizationError) {
799
+ this.logger?.error?.(`Error during metrics normalization: ${normalizationError.message}`);
800
+ return {
801
+ normalizedNodes: [],
802
+ normalizedPods: [],
803
+ error: `Normalization failed: ${normalizationError.message}${errors.length > 0 ? `; API errors: ${errors.join('; ')}` : ''}`,
804
+ };
805
+ }
806
+ }
807
+ // If no direct metrics available, log collected errors and try fallback
808
+ if (errors.length > 0) {
809
+ this.logger?.warn?.(`Direct API calls failed, attempting fallback. Errors: ${errors.join('; ')}`);
810
+ }
811
+ // Fallback: try the high-level getAllNormalizedMetrics method
812
+ try {
813
+ const safeDiscoveryNamespace = typeof discoveryNamespace === 'string' ? discoveryNamespace : undefined;
814
+ const metrics = await this.getAllNormalizedMetrics(prometheusQueries, fetchPodSpecs, safeDiscoveryNamespace);
815
+ // Include errors from direct API attempts if fallback succeeds
816
+ const combinedError = errors.length > 0
817
+ ? metrics.error
818
+ ? `${metrics.error}; Direct API errors: ${errors.join('; ')}`
819
+ : `Direct API errors (fallback used): ${errors.join('; ')}`
820
+ : metrics.error;
821
+ return {
822
+ normalizedNodes: metrics.nodesMetrics,
823
+ normalizedPods: metrics.podsMetrics,
824
+ error: combinedError,
825
+ };
826
+ }
827
+ catch (fallbackError) {
828
+ this.logger?.error?.(`Fallback method also failed: ${fallbackError.message}`);
829
+ return {
830
+ normalizedNodes: [],
831
+ normalizedPods: [],
832
+ error: `All methods failed. Direct API errors: ${errors.join('; ')}; Fallback error: ${fallbackError.message}`,
833
+ };
834
+ }
835
+ }
836
+ catch (error) {
837
+ this.logger?.error?.(`Critical error in getMetricsWithOptions: ${error.message}`);
838
+ return {
839
+ normalizedNodes: [],
840
+ normalizedPods: [],
841
+ error: `Critical error: ${error.message}`,
842
+ };
843
+ }
844
+ }
845
+ /**
846
+ * Parse CPU value to nanocores for consistent summing
847
+ * Public method for use by tools that need raw nanocores values
848
+ */
849
+ parseCpuValueToNanocores(cpuString) {
850
+ if (!cpuString)
851
+ return 0;
852
+ // Handle different CPU units
853
+ if (cpuString.endsWith('n')) {
854
+ return parseInt(cpuString.slice(0, -1), 10);
855
+ }
856
+ else if (cpuString.endsWith('u')) {
857
+ return parseInt(cpuString.slice(0, -1), 10) * 1000;
858
+ }
859
+ else if (cpuString.endsWith('m')) {
860
+ return parseInt(cpuString.slice(0, -1), 10) * 1000000;
861
+ }
862
+ else {
863
+ // Assume cores, convert to nanocores
864
+ return parseFloat(cpuString) * 1000000000;
865
+ }
866
+ }
867
+ /**
868
+ * Parse memory value to bytes for consistent summing
869
+ * Public method for use by tools that need raw bytes values
870
+ */
871
+ parseMemoryValueToBytes(memoryString) {
872
+ if (!memoryString)
873
+ return 0;
874
+ const value = parseInt(memoryString.replace(/[^\d]/g, ''), 10);
875
+ if (memoryString.includes('Ki')) {
876
+ return value * 1024;
877
+ }
878
+ else if (memoryString.includes('Mi')) {
879
+ return value * 1024 * 1024;
880
+ }
881
+ else if (memoryString.includes('Gi')) {
882
+ return value * 1024 * 1024 * 1024;
883
+ }
884
+ else if (memoryString.includes('Ti')) {
885
+ return value * 1024 * 1024 * 1024 * 1024;
886
+ }
887
+ else {
888
+ // Assume bytes
889
+ return value;
890
+ }
891
+ }
892
+ }
893
+ //# sourceMappingURL=MetricOperations.js.map