typekro 0.1.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 (620) hide show
  1. package/LICENSE +185 -0
  2. package/README.md +1137 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/alchemy/deployers.d.ts +39 -0
  5. package/dist/alchemy/deployers.d.ts.map +1 -0
  6. package/dist/alchemy/deployers.js +194 -0
  7. package/dist/alchemy/deployers.js.map +1 -0
  8. package/dist/alchemy/deployment.d.ts +12 -0
  9. package/dist/alchemy/deployment.d.ts.map +1 -0
  10. package/dist/alchemy/deployment.js +12 -0
  11. package/dist/alchemy/deployment.js.map +1 -0
  12. package/dist/alchemy/index.d.ts +17 -0
  13. package/dist/alchemy/index.d.ts.map +1 -0
  14. package/dist/alchemy/index.js +20 -0
  15. package/dist/alchemy/index.js.map +1 -0
  16. package/dist/alchemy/resolver.d.ts +127 -0
  17. package/dist/alchemy/resolver.d.ts.map +1 -0
  18. package/dist/alchemy/resolver.js +341 -0
  19. package/dist/alchemy/resolver.js.map +1 -0
  20. package/dist/alchemy/resource-registration.d.ts +22 -0
  21. package/dist/alchemy/resource-registration.d.ts.map +1 -0
  22. package/dist/alchemy/resource-registration.js +218 -0
  23. package/dist/alchemy/resource-registration.js.map +1 -0
  24. package/dist/alchemy/type-inference.d.ts +13 -0
  25. package/dist/alchemy/type-inference.d.ts.map +1 -0
  26. package/dist/alchemy/type-inference.js +67 -0
  27. package/dist/alchemy/type-inference.js.map +1 -0
  28. package/dist/alchemy/types.d.ts +92 -0
  29. package/dist/alchemy/types.d.ts.map +1 -0
  30. package/dist/alchemy/types.js +8 -0
  31. package/dist/alchemy/types.js.map +1 -0
  32. package/dist/alchemy/utilities.d.ts +12 -0
  33. package/dist/alchemy/utilities.d.ts.map +1 -0
  34. package/dist/alchemy/utilities.js +16 -0
  35. package/dist/alchemy/utilities.js.map +1 -0
  36. package/dist/alchemy/wrapper.d.ts +16 -0
  37. package/dist/alchemy/wrapper.d.ts.map +1 -0
  38. package/dist/alchemy/wrapper.js +23 -0
  39. package/dist/alchemy/wrapper.js.map +1 -0
  40. package/dist/core/composition/composition.d.ts +94 -0
  41. package/dist/core/composition/composition.d.ts.map +1 -0
  42. package/dist/core/composition/composition.js +230 -0
  43. package/dist/core/composition/composition.js.map +1 -0
  44. package/dist/core/composition/index.d.ts +12 -0
  45. package/dist/core/composition/index.d.ts.map +1 -0
  46. package/dist/core/composition/index.js +12 -0
  47. package/dist/core/composition/index.js.map +1 -0
  48. package/dist/core/composition/typekro-runtime/index.d.ts +3 -0
  49. package/dist/core/composition/typekro-runtime/index.d.ts.map +1 -0
  50. package/dist/core/composition/typekro-runtime/index.js +2 -0
  51. package/dist/core/composition/typekro-runtime/index.js.map +1 -0
  52. package/dist/core/composition/typekro-runtime/typekro-runtime.d.ts +39 -0
  53. package/dist/core/composition/typekro-runtime/typekro-runtime.d.ts.map +1 -0
  54. package/dist/core/composition/typekro-runtime/typekro-runtime.js +100 -0
  55. package/dist/core/composition/typekro-runtime/typekro-runtime.js.map +1 -0
  56. package/dist/core/composition/typekro-runtime/types.d.ts +16 -0
  57. package/dist/core/composition/typekro-runtime/types.d.ts.map +1 -0
  58. package/dist/core/composition/typekro-runtime/types.js +12 -0
  59. package/dist/core/composition/typekro-runtime/types.js.map +1 -0
  60. package/dist/core/composition/types.d.ts +264 -0
  61. package/dist/core/composition/types.d.ts.map +1 -0
  62. package/dist/core/composition/types.js +2 -0
  63. package/dist/core/composition/types.js.map +1 -0
  64. package/dist/core/constants/brands.d.ts +42 -0
  65. package/dist/core/constants/brands.d.ts.map +1 -0
  66. package/dist/core/constants/brands.js +51 -0
  67. package/dist/core/constants/brands.js.map +1 -0
  68. package/dist/core/dependencies/graph.d.ts +67 -0
  69. package/dist/core/dependencies/graph.d.ts.map +1 -0
  70. package/dist/core/dependencies/graph.js +220 -0
  71. package/dist/core/dependencies/graph.js.map +1 -0
  72. package/dist/core/dependencies/index.d.ts +7 -0
  73. package/dist/core/dependencies/index.d.ts.map +1 -0
  74. package/dist/core/dependencies/index.js +8 -0
  75. package/dist/core/dependencies/index.js.map +1 -0
  76. package/dist/core/dependencies/resolver.d.ts +53 -0
  77. package/dist/core/dependencies/resolver.d.ts.map +1 -0
  78. package/dist/core/dependencies/resolver.js +167 -0
  79. package/dist/core/dependencies/resolver.js.map +1 -0
  80. package/dist/core/dependencies/type-guards.d.ts +17 -0
  81. package/dist/core/dependencies/type-guards.d.ts.map +1 -0
  82. package/dist/core/dependencies/type-guards.js +35 -0
  83. package/dist/core/dependencies/type-guards.js.map +1 -0
  84. package/dist/core/deployment/deployment-strategies.d.ts +12 -0
  85. package/dist/core/deployment/deployment-strategies.d.ts.map +1 -0
  86. package/dist/core/deployment/deployment-strategies.js +11 -0
  87. package/dist/core/deployment/deployment-strategies.js.map +1 -0
  88. package/dist/core/deployment/direct-factory.d.ts +111 -0
  89. package/dist/core/deployment/direct-factory.d.ts.map +1 -0
  90. package/dist/core/deployment/direct-factory.js +627 -0
  91. package/dist/core/deployment/direct-factory.js.map +1 -0
  92. package/dist/core/deployment/engine.d.ts +128 -0
  93. package/dist/core/deployment/engine.d.ts.map +1 -0
  94. package/dist/core/deployment/engine.js +1408 -0
  95. package/dist/core/deployment/engine.js.map +1 -0
  96. package/dist/core/deployment/index.d.ts +14 -0
  97. package/dist/core/deployment/index.d.ts.map +1 -0
  98. package/dist/core/deployment/index.js +14 -0
  99. package/dist/core/deployment/index.js.map +1 -0
  100. package/dist/core/deployment/kro-factory.d.ts +143 -0
  101. package/dist/core/deployment/kro-factory.d.ts.map +1 -0
  102. package/dist/core/deployment/kro-factory.js +837 -0
  103. package/dist/core/deployment/kro-factory.js.map +1 -0
  104. package/dist/core/deployment/readiness.d.ts +54 -0
  105. package/dist/core/deployment/readiness.d.ts.map +1 -0
  106. package/dist/core/deployment/readiness.js +175 -0
  107. package/dist/core/deployment/readiness.js.map +1 -0
  108. package/dist/core/deployment/rollback-manager.d.ts +63 -0
  109. package/dist/core/deployment/rollback-manager.d.ts.map +1 -0
  110. package/dist/core/deployment/rollback-manager.js +225 -0
  111. package/dist/core/deployment/rollback-manager.js.map +1 -0
  112. package/dist/core/deployment/shared-utilities.d.ts +41 -0
  113. package/dist/core/deployment/shared-utilities.d.ts.map +1 -0
  114. package/dist/core/deployment/shared-utilities.js +100 -0
  115. package/dist/core/deployment/shared-utilities.js.map +1 -0
  116. package/dist/core/deployment/status-hydrator.d.ts +86 -0
  117. package/dist/core/deployment/status-hydrator.d.ts.map +1 -0
  118. package/dist/core/deployment/status-hydrator.js +262 -0
  119. package/dist/core/deployment/status-hydrator.js.map +1 -0
  120. package/dist/core/deployment/strategies/alchemy-strategy.d.ts +107 -0
  121. package/dist/core/deployment/strategies/alchemy-strategy.d.ts.map +1 -0
  122. package/dist/core/deployment/strategies/alchemy-strategy.js +446 -0
  123. package/dist/core/deployment/strategies/alchemy-strategy.js.map +1 -0
  124. package/dist/core/deployment/strategies/base-strategy.d.ts +50 -0
  125. package/dist/core/deployment/strategies/base-strategy.d.ts.map +1 -0
  126. package/dist/core/deployment/strategies/base-strategy.js +82 -0
  127. package/dist/core/deployment/strategies/base-strategy.js.map +1 -0
  128. package/dist/core/deployment/strategies/direct-strategy.d.ts +29 -0
  129. package/dist/core/deployment/strategies/direct-strategy.d.ts.map +1 -0
  130. package/dist/core/deployment/strategies/direct-strategy.js +80 -0
  131. package/dist/core/deployment/strategies/direct-strategy.js.map +1 -0
  132. package/dist/core/deployment/strategies/index.d.ts +12 -0
  133. package/dist/core/deployment/strategies/index.d.ts.map +1 -0
  134. package/dist/core/deployment/strategies/index.js +12 -0
  135. package/dist/core/deployment/strategies/index.js.map +1 -0
  136. package/dist/core/deployment/strategies/kro-strategy.d.ts +41 -0
  137. package/dist/core/deployment/strategies/kro-strategy.d.ts.map +1 -0
  138. package/dist/core/deployment/strategies/kro-strategy.js +270 -0
  139. package/dist/core/deployment/strategies/kro-strategy.js.map +1 -0
  140. package/dist/core/direct-deployment.d.ts +8 -0
  141. package/dist/core/direct-deployment.d.ts.map +1 -0
  142. package/dist/core/direct-deployment.js +9 -0
  143. package/dist/core/direct-deployment.js.map +1 -0
  144. package/dist/core/errors.d.ts +73 -0
  145. package/dist/core/errors.d.ts.map +1 -0
  146. package/dist/core/errors.js +250 -0
  147. package/dist/core/errors.js.map +1 -0
  148. package/dist/core/evaluation/cel-optimizer.d.ts +48 -0
  149. package/dist/core/evaluation/cel-optimizer.d.ts.map +1 -0
  150. package/dist/core/evaluation/cel-optimizer.js +176 -0
  151. package/dist/core/evaluation/cel-optimizer.js.map +1 -0
  152. package/dist/core/factory.d.ts +12 -0
  153. package/dist/core/factory.d.ts.map +1 -0
  154. package/dist/core/factory.js +13 -0
  155. package/dist/core/factory.js.map +1 -0
  156. package/dist/core/kubernetes/api.d.ts +43 -0
  157. package/dist/core/kubernetes/api.d.ts.map +1 -0
  158. package/dist/core/kubernetes/api.js +209 -0
  159. package/dist/core/kubernetes/api.js.map +1 -0
  160. package/dist/core/kubernetes/client-provider.d.ts +204 -0
  161. package/dist/core/kubernetes/client-provider.d.ts.map +1 -0
  162. package/dist/core/kubernetes/client-provider.js +421 -0
  163. package/dist/core/kubernetes/client-provider.js.map +1 -0
  164. package/dist/core/logging/config.d.ts +14 -0
  165. package/dist/core/logging/config.d.ts.map +1 -0
  166. package/dist/core/logging/config.js +57 -0
  167. package/dist/core/logging/config.js.map +1 -0
  168. package/dist/core/logging/index.d.ts +4 -0
  169. package/dist/core/logging/index.d.ts.map +1 -0
  170. package/dist/core/logging/index.js +4 -0
  171. package/dist/core/logging/index.js.map +1 -0
  172. package/dist/core/logging/logger.d.ts +26 -0
  173. package/dist/core/logging/logger.d.ts.map +1 -0
  174. package/dist/core/logging/logger.js +114 -0
  175. package/dist/core/logging/logger.js.map +1 -0
  176. package/dist/core/logging/types.d.ts +93 -0
  177. package/dist/core/logging/types.d.ts.map +1 -0
  178. package/dist/core/logging/types.js +2 -0
  179. package/dist/core/logging/types.js.map +1 -0
  180. package/dist/core/readiness/cluster-state.d.ts +229 -0
  181. package/dist/core/readiness/cluster-state.d.ts.map +1 -0
  182. package/dist/core/readiness/cluster-state.js +360 -0
  183. package/dist/core/readiness/cluster-state.js.map +1 -0
  184. package/dist/core/readiness/index.d.ts +5 -0
  185. package/dist/core/readiness/index.d.ts.map +1 -0
  186. package/dist/core/readiness/index.js +5 -0
  187. package/dist/core/readiness/index.js.map +1 -0
  188. package/dist/core/readiness/registry.d.ts +45 -0
  189. package/dist/core/readiness/registry.d.ts.map +1 -0
  190. package/dist/core/readiness/registry.js +62 -0
  191. package/dist/core/readiness/registry.js.map +1 -0
  192. package/dist/core/references/cel-evaluator.d.ts +102 -0
  193. package/dist/core/references/cel-evaluator.d.ts.map +1 -0
  194. package/dist/core/references/cel-evaluator.js +288 -0
  195. package/dist/core/references/cel-evaluator.js.map +1 -0
  196. package/dist/core/references/cel.d.ts +75 -0
  197. package/dist/core/references/cel.d.ts.map +1 -0
  198. package/dist/core/references/cel.js +213 -0
  199. package/dist/core/references/cel.js.map +1 -0
  200. package/dist/core/references/external-refs.d.ts +37 -0
  201. package/dist/core/references/external-refs.d.ts.map +1 -0
  202. package/dist/core/references/external-refs.js +53 -0
  203. package/dist/core/references/external-refs.js.map +1 -0
  204. package/dist/core/references/index.d.ts +15 -0
  205. package/dist/core/references/index.d.ts.map +1 -0
  206. package/dist/core/references/index.js +19 -0
  207. package/dist/core/references/index.js.map +1 -0
  208. package/dist/core/references/resolver.d.ts +117 -0
  209. package/dist/core/references/resolver.d.ts.map +1 -0
  210. package/dist/core/references/resolver.js +554 -0
  211. package/dist/core/references/resolver.js.map +1 -0
  212. package/dist/core/references/schema-proxy.d.ts +38 -0
  213. package/dist/core/references/schema-proxy.d.ts.map +1 -0
  214. package/dist/core/references/schema-proxy.js +163 -0
  215. package/dist/core/references/schema-proxy.js.map +1 -0
  216. package/dist/core/serialization/core.d.ts +15 -0
  217. package/dist/core/serialization/core.d.ts.map +1 -0
  218. package/dist/core/serialization/core.js +169 -0
  219. package/dist/core/serialization/core.js.map +1 -0
  220. package/dist/core/serialization/index.d.ts +9 -0
  221. package/dist/core/serialization/index.d.ts.map +1 -0
  222. package/dist/core/serialization/index.js +12 -0
  223. package/dist/core/serialization/index.js.map +1 -0
  224. package/dist/core/serialization/schema.d.ts +14 -0
  225. package/dist/core/serialization/schema.d.ts.map +1 -0
  226. package/dist/core/serialization/schema.js +33 -0
  227. package/dist/core/serialization/schema.js.map +1 -0
  228. package/dist/core/serialization/validation.d.ts +18 -0
  229. package/dist/core/serialization/validation.d.ts.map +1 -0
  230. package/dist/core/serialization/validation.js +165 -0
  231. package/dist/core/serialization/validation.js.map +1 -0
  232. package/dist/core/serialization/yaml.d.ts +10 -0
  233. package/dist/core/serialization/yaml.d.ts.map +1 -0
  234. package/dist/core/serialization/yaml.js +63 -0
  235. package/dist/core/serialization/yaml.js.map +1 -0
  236. package/dist/core/types/common.d.ts +41 -0
  237. package/dist/core/types/common.d.ts.map +1 -0
  238. package/dist/core/types/common.js +9 -0
  239. package/dist/core/types/common.js.map +1 -0
  240. package/dist/core/types/dependencies.d.ts +14 -0
  241. package/dist/core/types/dependencies.d.ts.map +1 -0
  242. package/dist/core/types/dependencies.js +5 -0
  243. package/dist/core/types/dependencies.js.map +1 -0
  244. package/dist/core/types/deployment.d.ts +265 -0
  245. package/dist/core/types/deployment.d.ts.map +1 -0
  246. package/dist/core/types/deployment.js +20 -0
  247. package/dist/core/types/deployment.js.map +1 -0
  248. package/dist/core/types/index.d.ts +19 -0
  249. package/dist/core/types/index.d.ts.map +1 -0
  250. package/dist/core/types/index.js +15 -0
  251. package/dist/core/types/index.js.map +1 -0
  252. package/dist/core/types/kubernetes.d.ts +352 -0
  253. package/dist/core/types/kubernetes.d.ts.map +1 -0
  254. package/dist/core/types/kubernetes.js +5 -0
  255. package/dist/core/types/kubernetes.js.map +1 -0
  256. package/dist/core/types/references.d.ts +54 -0
  257. package/dist/core/types/references.d.ts.map +1 -0
  258. package/dist/core/types/references.js +14 -0
  259. package/dist/core/types/references.js.map +1 -0
  260. package/dist/core/types/resource-graph.d.ts +93 -0
  261. package/dist/core/types/resource-graph.d.ts.map +1 -0
  262. package/dist/core/types/resource-graph.js +8 -0
  263. package/dist/core/types/resource-graph.js.map +1 -0
  264. package/dist/core/types/serialization.d.ts +210 -0
  265. package/dist/core/types/serialization.d.ts.map +1 -0
  266. package/dist/core/types/serialization.js +5 -0
  267. package/dist/core/types/serialization.js.map +1 -0
  268. package/dist/core/types/yaml.d.ts +92 -0
  269. package/dist/core/types/yaml.d.ts.map +1 -0
  270. package/dist/core/types/yaml.js +2 -0
  271. package/dist/core/types/yaml.js.map +1 -0
  272. package/dist/core/types.d.ts +8 -0
  273. package/dist/core/types.d.ts.map +1 -0
  274. package/dist/core/types.js +9 -0
  275. package/dist/core/types.js.map +1 -0
  276. package/dist/core/validation/cel-validator.d.ts +47 -0
  277. package/dist/core/validation/cel-validator.d.ts.map +1 -0
  278. package/dist/core/validation/cel-validator.js +200 -0
  279. package/dist/core/validation/cel-validator.js.map +1 -0
  280. package/dist/core/yaml/index.d.ts +5 -0
  281. package/dist/core/yaml/index.d.ts.map +1 -0
  282. package/dist/core/yaml/index.js +5 -0
  283. package/dist/core/yaml/index.js.map +1 -0
  284. package/dist/core/yaml/path-resolver.d.ts +122 -0
  285. package/dist/core/yaml/path-resolver.d.ts.map +1 -0
  286. package/dist/core/yaml/path-resolver.js +556 -0
  287. package/dist/core/yaml/path-resolver.js.map +1 -0
  288. package/dist/core.d.ts +30 -0
  289. package/dist/core.d.ts.map +1 -0
  290. package/dist/core.js +59 -0
  291. package/dist/core.js.map +1 -0
  292. package/dist/factories/flux/git-repository.d.ts +62 -0
  293. package/dist/factories/flux/git-repository.d.ts.map +1 -0
  294. package/dist/factories/flux/git-repository.js +34 -0
  295. package/dist/factories/flux/git-repository.js.map +1 -0
  296. package/dist/factories/flux/index.d.ts +10 -0
  297. package/dist/factories/flux/index.d.ts.map +1 -0
  298. package/dist/factories/flux/index.js +11 -0
  299. package/dist/factories/flux/index.js.map +1 -0
  300. package/dist/factories/flux/kustomize/index.d.ts +4 -0
  301. package/dist/factories/flux/kustomize/index.d.ts.map +1 -0
  302. package/dist/factories/flux/kustomize/index.js +3 -0
  303. package/dist/factories/flux/kustomize/index.js.map +1 -0
  304. package/dist/factories/flux/kustomize/kustomization.d.ts +178 -0
  305. package/dist/factories/flux/kustomize/kustomization.d.ts.map +1 -0
  306. package/dist/factories/flux/kustomize/kustomization.js +108 -0
  307. package/dist/factories/flux/kustomize/kustomization.js.map +1 -0
  308. package/dist/factories/flux/kustomize/readiness-evaluators.d.ts +9 -0
  309. package/dist/factories/flux/kustomize/readiness-evaluators.d.ts.map +1 -0
  310. package/dist/factories/flux/kustomize/readiness-evaluators.js +71 -0
  311. package/dist/factories/flux/kustomize/readiness-evaluators.js.map +1 -0
  312. package/dist/factories/flux/kustomize/types.d.ts +2 -0
  313. package/dist/factories/flux/kustomize/types.d.ts.map +1 -0
  314. package/dist/factories/flux/kustomize/types.js +2 -0
  315. package/dist/factories/flux/kustomize/types.js.map +1 -0
  316. package/dist/factories/helm/helm-release.d.ts +139 -0
  317. package/dist/factories/helm/helm-release.d.ts.map +1 -0
  318. package/dist/factories/helm/helm-release.js +180 -0
  319. package/dist/factories/helm/helm-release.js.map +1 -0
  320. package/dist/factories/helm/helm-repository.d.ts +24 -0
  321. package/dist/factories/helm/helm-repository.d.ts.map +1 -0
  322. package/dist/factories/helm/helm-repository.js +57 -0
  323. package/dist/factories/helm/helm-repository.js.map +1 -0
  324. package/dist/factories/helm/index.d.ts +8 -0
  325. package/dist/factories/helm/index.d.ts.map +1 -0
  326. package/dist/factories/helm/index.js +8 -0
  327. package/dist/factories/helm/index.js.map +1 -0
  328. package/dist/factories/helm/readiness-evaluators.d.ts +55 -0
  329. package/dist/factories/helm/readiness-evaluators.d.ts.map +1 -0
  330. package/dist/factories/helm/readiness-evaluators.js +295 -0
  331. package/dist/factories/helm/readiness-evaluators.js.map +1 -0
  332. package/dist/factories/helm/types.d.ts +21 -0
  333. package/dist/factories/helm/types.d.ts.map +1 -0
  334. package/dist/factories/helm/types.js +2 -0
  335. package/dist/factories/helm/types.js.map +1 -0
  336. package/dist/factories/index.d.ts +12 -0
  337. package/dist/factories/index.d.ts.map +1 -0
  338. package/dist/factories/index.js +31 -0
  339. package/dist/factories/index.js.map +1 -0
  340. package/dist/factories/kro/index.d.ts +11 -0
  341. package/dist/factories/kro/index.d.ts.map +1 -0
  342. package/dist/factories/kro/index.js +10 -0
  343. package/dist/factories/kro/index.js.map +1 -0
  344. package/dist/factories/kro/kro-crd.d.ts +14 -0
  345. package/dist/factories/kro/kro-crd.d.ts.map +1 -0
  346. package/dist/factories/kro/kro-crd.js +51 -0
  347. package/dist/factories/kro/kro-crd.js.map +1 -0
  348. package/dist/factories/kro/kro-custom-resource.d.ts +23 -0
  349. package/dist/factories/kro/kro-custom-resource.d.ts.map +1 -0
  350. package/dist/factories/kro/kro-custom-resource.js +153 -0
  351. package/dist/factories/kro/kro-custom-resource.js.map +1 -0
  352. package/dist/factories/kro/resource-graph-definition.d.ts +12 -0
  353. package/dist/factories/kro/resource-graph-definition.d.ts.map +1 -0
  354. package/dist/factories/kro/resource-graph-definition.js +94 -0
  355. package/dist/factories/kro/resource-graph-definition.js.map +1 -0
  356. package/dist/factories/kubernetes/admission/index.d.ts +9 -0
  357. package/dist/factories/kubernetes/admission/index.d.ts.map +1 -0
  358. package/dist/factories/kubernetes/admission/index.js +9 -0
  359. package/dist/factories/kubernetes/admission/index.js.map +1 -0
  360. package/dist/factories/kubernetes/admission/mutating-webhook-configuration.d.ts +5 -0
  361. package/dist/factories/kubernetes/admission/mutating-webhook-configuration.d.ts.map +1 -0
  362. package/dist/factories/kubernetes/admission/mutating-webhook-configuration.js +10 -0
  363. package/dist/factories/kubernetes/admission/mutating-webhook-configuration.js.map +1 -0
  364. package/dist/factories/kubernetes/admission/validating-webhook-configuration.d.ts +5 -0
  365. package/dist/factories/kubernetes/admission/validating-webhook-configuration.d.ts.map +1 -0
  366. package/dist/factories/kubernetes/admission/validating-webhook-configuration.js +10 -0
  367. package/dist/factories/kubernetes/admission/validating-webhook-configuration.js.map +1 -0
  368. package/dist/factories/kubernetes/autoscaling/horizontal-pod-autoscaler-v1.d.ts +6 -0
  369. package/dist/factories/kubernetes/autoscaling/horizontal-pod-autoscaler-v1.d.ts.map +1 -0
  370. package/dist/factories/kubernetes/autoscaling/horizontal-pod-autoscaler-v1.js +35 -0
  371. package/dist/factories/kubernetes/autoscaling/horizontal-pod-autoscaler-v1.js.map +1 -0
  372. package/dist/factories/kubernetes/autoscaling/horizontal-pod-autoscaler.d.ts +6 -0
  373. package/dist/factories/kubernetes/autoscaling/horizontal-pod-autoscaler.d.ts.map +1 -0
  374. package/dist/factories/kubernetes/autoscaling/horizontal-pod-autoscaler.js +31 -0
  375. package/dist/factories/kubernetes/autoscaling/horizontal-pod-autoscaler.js.map +1 -0
  376. package/dist/factories/kubernetes/autoscaling/index.d.ts +9 -0
  377. package/dist/factories/kubernetes/autoscaling/index.d.ts.map +1 -0
  378. package/dist/factories/kubernetes/autoscaling/index.js +9 -0
  379. package/dist/factories/kubernetes/autoscaling/index.js.map +1 -0
  380. package/dist/factories/kubernetes/certificates/certificate-signing-request.d.ts +6 -0
  381. package/dist/factories/kubernetes/certificates/certificate-signing-request.d.ts.map +1 -0
  382. package/dist/factories/kubernetes/certificates/certificate-signing-request.js +48 -0
  383. package/dist/factories/kubernetes/certificates/certificate-signing-request.js.map +1 -0
  384. package/dist/factories/kubernetes/certificates/index.d.ts +8 -0
  385. package/dist/factories/kubernetes/certificates/index.d.ts.map +1 -0
  386. package/dist/factories/kubernetes/certificates/index.js +8 -0
  387. package/dist/factories/kubernetes/certificates/index.js.map +1 -0
  388. package/dist/factories/kubernetes/config/config-map.d.ts +5 -0
  389. package/dist/factories/kubernetes/config/config-map.d.ts.map +1 -0
  390. package/dist/factories/kubernetes/config/config-map.js +16 -0
  391. package/dist/factories/kubernetes/config/config-map.js.map +1 -0
  392. package/dist/factories/kubernetes/config/index.d.ts +9 -0
  393. package/dist/factories/kubernetes/config/index.d.ts.map +1 -0
  394. package/dist/factories/kubernetes/config/index.js +9 -0
  395. package/dist/factories/kubernetes/config/index.js.map +1 -0
  396. package/dist/factories/kubernetes/config/secret.d.ts +5 -0
  397. package/dist/factories/kubernetes/config/secret.d.ts.map +1 -0
  398. package/dist/factories/kubernetes/config/secret.js +16 -0
  399. package/dist/factories/kubernetes/config/secret.js.map +1 -0
  400. package/dist/factories/kubernetes/coordination/index.d.ts +8 -0
  401. package/dist/factories/kubernetes/coordination/index.d.ts.map +1 -0
  402. package/dist/factories/kubernetes/coordination/index.js +8 -0
  403. package/dist/factories/kubernetes/coordination/index.js.map +1 -0
  404. package/dist/factories/kubernetes/coordination/lease.d.ts +5 -0
  405. package/dist/factories/kubernetes/coordination/lease.d.ts.map +1 -0
  406. package/dist/factories/kubernetes/coordination/lease.js +10 -0
  407. package/dist/factories/kubernetes/coordination/lease.js.map +1 -0
  408. package/dist/factories/kubernetes/core/component-status.d.ts +4 -0
  409. package/dist/factories/kubernetes/core/component-status.d.ts.map +1 -0
  410. package/dist/factories/kubernetes/core/component-status.js +25 -0
  411. package/dist/factories/kubernetes/core/component-status.js.map +1 -0
  412. package/dist/factories/kubernetes/core/index.d.ts +11 -0
  413. package/dist/factories/kubernetes/core/index.d.ts.map +1 -0
  414. package/dist/factories/kubernetes/core/index.js +11 -0
  415. package/dist/factories/kubernetes/core/index.js.map +1 -0
  416. package/dist/factories/kubernetes/core/namespace.d.ts +9 -0
  417. package/dist/factories/kubernetes/core/namespace.d.ts.map +1 -0
  418. package/dist/factories/kubernetes/core/namespace.js +48 -0
  419. package/dist/factories/kubernetes/core/namespace.js.map +1 -0
  420. package/dist/factories/kubernetes/core/node.d.ts +6 -0
  421. package/dist/factories/kubernetes/core/node.d.ts.map +1 -0
  422. package/dist/factories/kubernetes/core/node.js +34 -0
  423. package/dist/factories/kubernetes/core/node.js.map +1 -0
  424. package/dist/factories/kubernetes/core/pod.d.ts +6 -0
  425. package/dist/factories/kubernetes/core/pod.d.ts.map +1 -0
  426. package/dist/factories/kubernetes/core/pod.js +44 -0
  427. package/dist/factories/kubernetes/core/pod.js.map +1 -0
  428. package/dist/factories/kubernetes/extensions/custom-resource-definition.d.ts +6 -0
  429. package/dist/factories/kubernetes/extensions/custom-resource-definition.d.ts.map +1 -0
  430. package/dist/factories/kubernetes/extensions/custom-resource-definition.js +45 -0
  431. package/dist/factories/kubernetes/extensions/custom-resource-definition.js.map +1 -0
  432. package/dist/factories/kubernetes/extensions/custom-resource.d.ts +12 -0
  433. package/dist/factories/kubernetes/extensions/custom-resource.d.ts.map +1 -0
  434. package/dist/factories/kubernetes/extensions/custom-resource.js +17 -0
  435. package/dist/factories/kubernetes/extensions/custom-resource.js.map +1 -0
  436. package/dist/factories/kubernetes/extensions/index.d.ts +9 -0
  437. package/dist/factories/kubernetes/extensions/index.d.ts.map +1 -0
  438. package/dist/factories/kubernetes/extensions/index.js +9 -0
  439. package/dist/factories/kubernetes/extensions/index.js.map +1 -0
  440. package/dist/factories/kubernetes/index.d.ts +24 -0
  441. package/dist/factories/kubernetes/index.d.ts.map +1 -0
  442. package/dist/factories/kubernetes/index.js +75 -0
  443. package/dist/factories/kubernetes/index.js.map +1 -0
  444. package/dist/factories/kubernetes/networking/endpoint-slice.d.ts +4 -0
  445. package/dist/factories/kubernetes/networking/endpoint-slice.d.ts.map +1 -0
  446. package/dist/factories/kubernetes/networking/endpoint-slice.js +10 -0
  447. package/dist/factories/kubernetes/networking/endpoint-slice.js.map +1 -0
  448. package/dist/factories/kubernetes/networking/endpoints.d.ts +4 -0
  449. package/dist/factories/kubernetes/networking/endpoints.d.ts.map +1 -0
  450. package/dist/factories/kubernetes/networking/endpoints.js +39 -0
  451. package/dist/factories/kubernetes/networking/endpoints.js.map +1 -0
  452. package/dist/factories/kubernetes/networking/index.d.ts +13 -0
  453. package/dist/factories/kubernetes/networking/index.d.ts.map +1 -0
  454. package/dist/factories/kubernetes/networking/index.js +13 -0
  455. package/dist/factories/kubernetes/networking/index.js.map +1 -0
  456. package/dist/factories/kubernetes/networking/ingress-class.d.ts +5 -0
  457. package/dist/factories/kubernetes/networking/ingress-class.d.ts.map +1 -0
  458. package/dist/factories/kubernetes/networking/ingress-class.js +16 -0
  459. package/dist/factories/kubernetes/networking/ingress-class.js.map +1 -0
  460. package/dist/factories/kubernetes/networking/ingress.d.ts +5 -0
  461. package/dist/factories/kubernetes/networking/ingress.d.ts.map +1 -0
  462. package/dist/factories/kubernetes/networking/ingress.js +33 -0
  463. package/dist/factories/kubernetes/networking/ingress.js.map +1 -0
  464. package/dist/factories/kubernetes/networking/network-policy.d.ts +5 -0
  465. package/dist/factories/kubernetes/networking/network-policy.d.ts.map +1 -0
  466. package/dist/factories/kubernetes/networking/network-policy.js +17 -0
  467. package/dist/factories/kubernetes/networking/network-policy.js.map +1 -0
  468. package/dist/factories/kubernetes/networking/service.d.ts +5 -0
  469. package/dist/factories/kubernetes/networking/service.d.ts.map +1 -0
  470. package/dist/factories/kubernetes/networking/service.js +64 -0
  471. package/dist/factories/kubernetes/networking/service.js.map +1 -0
  472. package/dist/factories/kubernetes/policy/index.d.ts +10 -0
  473. package/dist/factories/kubernetes/policy/index.d.ts.map +1 -0
  474. package/dist/factories/kubernetes/policy/index.js +10 -0
  475. package/dist/factories/kubernetes/policy/index.js.map +1 -0
  476. package/dist/factories/kubernetes/policy/limit-range.d.ts +5 -0
  477. package/dist/factories/kubernetes/policy/limit-range.d.ts.map +1 -0
  478. package/dist/factories/kubernetes/policy/limit-range.js +17 -0
  479. package/dist/factories/kubernetes/policy/limit-range.js.map +1 -0
  480. package/dist/factories/kubernetes/policy/pod-disruption-budget.d.ts +6 -0
  481. package/dist/factories/kubernetes/policy/pod-disruption-budget.d.ts.map +1 -0
  482. package/dist/factories/kubernetes/policy/pod-disruption-budget.js +55 -0
  483. package/dist/factories/kubernetes/policy/pod-disruption-budget.js.map +1 -0
  484. package/dist/factories/kubernetes/policy/resource-quota.d.ts +6 -0
  485. package/dist/factories/kubernetes/policy/resource-quota.d.ts.map +1 -0
  486. package/dist/factories/kubernetes/policy/resource-quota.js +43 -0
  487. package/dist/factories/kubernetes/policy/resource-quota.js.map +1 -0
  488. package/dist/factories/kubernetes/rbac/cluster-role-binding.d.ts +4 -0
  489. package/dist/factories/kubernetes/rbac/cluster-role-binding.d.ts.map +1 -0
  490. package/dist/factories/kubernetes/rbac/cluster-role-binding.js +17 -0
  491. package/dist/factories/kubernetes/rbac/cluster-role-binding.js.map +1 -0
  492. package/dist/factories/kubernetes/rbac/cluster-role.d.ts +4 -0
  493. package/dist/factories/kubernetes/rbac/cluster-role.d.ts.map +1 -0
  494. package/dist/factories/kubernetes/rbac/cluster-role.js +17 -0
  495. package/dist/factories/kubernetes/rbac/cluster-role.js.map +1 -0
  496. package/dist/factories/kubernetes/rbac/index.d.ts +12 -0
  497. package/dist/factories/kubernetes/rbac/index.d.ts.map +1 -0
  498. package/dist/factories/kubernetes/rbac/index.js +12 -0
  499. package/dist/factories/kubernetes/rbac/index.js.map +1 -0
  500. package/dist/factories/kubernetes/rbac/role-binding.d.ts +4 -0
  501. package/dist/factories/kubernetes/rbac/role-binding.d.ts.map +1 -0
  502. package/dist/factories/kubernetes/rbac/role-binding.js +17 -0
  503. package/dist/factories/kubernetes/rbac/role-binding.js.map +1 -0
  504. package/dist/factories/kubernetes/rbac/role.d.ts +4 -0
  505. package/dist/factories/kubernetes/rbac/role.d.ts.map +1 -0
  506. package/dist/factories/kubernetes/rbac/role.js +17 -0
  507. package/dist/factories/kubernetes/rbac/role.js.map +1 -0
  508. package/dist/factories/kubernetes/rbac/service-account.d.ts +4 -0
  509. package/dist/factories/kubernetes/rbac/service-account.d.ts.map +1 -0
  510. package/dist/factories/kubernetes/rbac/service-account.js +17 -0
  511. package/dist/factories/kubernetes/rbac/service-account.js.map +1 -0
  512. package/dist/factories/kubernetes/scheduling/index.d.ts +9 -0
  513. package/dist/factories/kubernetes/scheduling/index.d.ts.map +1 -0
  514. package/dist/factories/kubernetes/scheduling/index.js +9 -0
  515. package/dist/factories/kubernetes/scheduling/index.js.map +1 -0
  516. package/dist/factories/kubernetes/scheduling/priority-class.d.ts +4 -0
  517. package/dist/factories/kubernetes/scheduling/priority-class.d.ts.map +1 -0
  518. package/dist/factories/kubernetes/scheduling/priority-class.js +16 -0
  519. package/dist/factories/kubernetes/scheduling/priority-class.js.map +1 -0
  520. package/dist/factories/kubernetes/scheduling/runtime-class.d.ts +5 -0
  521. package/dist/factories/kubernetes/scheduling/runtime-class.d.ts.map +1 -0
  522. package/dist/factories/kubernetes/scheduling/runtime-class.js +10 -0
  523. package/dist/factories/kubernetes/scheduling/runtime-class.js.map +1 -0
  524. package/dist/factories/kubernetes/storage/csi-driver.d.ts +5 -0
  525. package/dist/factories/kubernetes/storage/csi-driver.d.ts.map +1 -0
  526. package/dist/factories/kubernetes/storage/csi-driver.js +16 -0
  527. package/dist/factories/kubernetes/storage/csi-driver.js.map +1 -0
  528. package/dist/factories/kubernetes/storage/csi-node.d.ts +5 -0
  529. package/dist/factories/kubernetes/storage/csi-node.d.ts.map +1 -0
  530. package/dist/factories/kubernetes/storage/csi-node.js +10 -0
  531. package/dist/factories/kubernetes/storage/csi-node.js.map +1 -0
  532. package/dist/factories/kubernetes/storage/index.d.ts +13 -0
  533. package/dist/factories/kubernetes/storage/index.d.ts.map +1 -0
  534. package/dist/factories/kubernetes/storage/index.js +13 -0
  535. package/dist/factories/kubernetes/storage/index.js.map +1 -0
  536. package/dist/factories/kubernetes/storage/persistent-volume-claim.d.ts +6 -0
  537. package/dist/factories/kubernetes/storage/persistent-volume-claim.d.ts.map +1 -0
  538. package/dist/factories/kubernetes/storage/persistent-volume-claim.js +30 -0
  539. package/dist/factories/kubernetes/storage/persistent-volume-claim.js.map +1 -0
  540. package/dist/factories/kubernetes/storage/persistent-volume.d.ts +6 -0
  541. package/dist/factories/kubernetes/storage/persistent-volume.d.ts.map +1 -0
  542. package/dist/factories/kubernetes/storage/persistent-volume.js +47 -0
  543. package/dist/factories/kubernetes/storage/persistent-volume.js.map +1 -0
  544. package/dist/factories/kubernetes/storage/storage-class.d.ts +4 -0
  545. package/dist/factories/kubernetes/storage/storage-class.d.ts.map +1 -0
  546. package/dist/factories/kubernetes/storage/storage-class.js +17 -0
  547. package/dist/factories/kubernetes/storage/storage-class.js.map +1 -0
  548. package/dist/factories/kubernetes/storage/volume-attachment.d.ts +6 -0
  549. package/dist/factories/kubernetes/storage/volume-attachment.d.ts.map +1 -0
  550. package/dist/factories/kubernetes/storage/volume-attachment.js +10 -0
  551. package/dist/factories/kubernetes/storage/volume-attachment.js.map +1 -0
  552. package/dist/factories/kubernetes/types.d.ts +8 -0
  553. package/dist/factories/kubernetes/types.d.ts.map +1 -0
  554. package/dist/factories/kubernetes/types.js +8 -0
  555. package/dist/factories/kubernetes/types.js.map +1 -0
  556. package/dist/factories/kubernetes/workloads/cron-job.d.ts +6 -0
  557. package/dist/factories/kubernetes/workloads/cron-job.d.ts.map +1 -0
  558. package/dist/factories/kubernetes/workloads/cron-job.js +53 -0
  559. package/dist/factories/kubernetes/workloads/cron-job.js.map +1 -0
  560. package/dist/factories/kubernetes/workloads/daemon-set.d.ts +6 -0
  561. package/dist/factories/kubernetes/workloads/daemon-set.d.ts.map +1 -0
  562. package/dist/factories/kubernetes/workloads/daemon-set.js +32 -0
  563. package/dist/factories/kubernetes/workloads/daemon-set.js.map +1 -0
  564. package/dist/factories/kubernetes/workloads/deployment.d.ts +5 -0
  565. package/dist/factories/kubernetes/workloads/deployment.d.ts.map +1 -0
  566. package/dist/factories/kubernetes/workloads/deployment.js +59 -0
  567. package/dist/factories/kubernetes/workloads/deployment.js.map +1 -0
  568. package/dist/factories/kubernetes/workloads/index.d.ts +14 -0
  569. package/dist/factories/kubernetes/workloads/index.d.ts.map +1 -0
  570. package/dist/factories/kubernetes/workloads/index.js +14 -0
  571. package/dist/factories/kubernetes/workloads/index.js.map +1 -0
  572. package/dist/factories/kubernetes/workloads/job.d.ts +6 -0
  573. package/dist/factories/kubernetes/workloads/job.d.ts.map +1 -0
  574. package/dist/factories/kubernetes/workloads/job.js +105 -0
  575. package/dist/factories/kubernetes/workloads/job.js.map +1 -0
  576. package/dist/factories/kubernetes/workloads/replica-set.d.ts +6 -0
  577. package/dist/factories/kubernetes/workloads/replica-set.d.ts.map +1 -0
  578. package/dist/factories/kubernetes/workloads/replica-set.js +33 -0
  579. package/dist/factories/kubernetes/workloads/replica-set.js.map +1 -0
  580. package/dist/factories/kubernetes/workloads/replication-controller.d.ts +6 -0
  581. package/dist/factories/kubernetes/workloads/replication-controller.d.ts.map +1 -0
  582. package/dist/factories/kubernetes/workloads/replication-controller.js +56 -0
  583. package/dist/factories/kubernetes/workloads/replication-controller.js.map +1 -0
  584. package/dist/factories/kubernetes/workloads/stateful-set.d.ts +6 -0
  585. package/dist/factories/kubernetes/workloads/stateful-set.d.ts.map +1 -0
  586. package/dist/factories/kubernetes/workloads/stateful-set.js +81 -0
  587. package/dist/factories/kubernetes/workloads/stateful-set.js.map +1 -0
  588. package/dist/factories/kubernetes/yaml/index.d.ts +6 -0
  589. package/dist/factories/kubernetes/yaml/index.d.ts.map +1 -0
  590. package/dist/factories/kubernetes/yaml/index.js +6 -0
  591. package/dist/factories/kubernetes/yaml/index.js.map +1 -0
  592. package/dist/factories/kubernetes/yaml/yaml-directory.d.ts +54 -0
  593. package/dist/factories/kubernetes/yaml/yaml-directory.d.ts.map +1 -0
  594. package/dist/factories/kubernetes/yaml/yaml-directory.js +178 -0
  595. package/dist/factories/kubernetes/yaml/yaml-directory.js.map +1 -0
  596. package/dist/factories/kubernetes/yaml/yaml-file.d.ts +54 -0
  597. package/dist/factories/kubernetes/yaml/yaml-file.d.ts.map +1 -0
  598. package/dist/factories/kubernetes/yaml/yaml-file.js +181 -0
  599. package/dist/factories/kubernetes/yaml/yaml-file.js.map +1 -0
  600. package/dist/factories/shared.d.ts +11 -0
  601. package/dist/factories/shared.d.ts.map +1 -0
  602. package/dist/factories/shared.js +364 -0
  603. package/dist/factories/shared.js.map +1 -0
  604. package/dist/index.d.ts +9 -0
  605. package/dist/index.d.ts.map +1 -0
  606. package/dist/index.js +49 -0
  607. package/dist/index.js.map +1 -0
  608. package/dist/utils/helpers.d.ts +69 -0
  609. package/dist/utils/helpers.d.ts.map +1 -0
  610. package/dist/utils/helpers.js +405 -0
  611. package/dist/utils/helpers.js.map +1 -0
  612. package/dist/utils/index.d.ts +9 -0
  613. package/dist/utils/index.d.ts.map +1 -0
  614. package/dist/utils/index.js +11 -0
  615. package/dist/utils/index.js.map +1 -0
  616. package/dist/utils/type-guards.d.ts +34 -0
  617. package/dist/utils/type-guards.d.ts.map +1 -0
  618. package/dist/utils/type-guards.js +66 -0
  619. package/dist/utils/type-guards.js.map +1 -0
  620. package/package.json +109 -0
@@ -0,0 +1,1408 @@
1
+ /**
2
+ * Direct Deployment Engine
3
+ *
4
+ * Orchestrates the deployment of Kubernetes resources directly to a cluster
5
+ * without requiring the Kro controller, using in-process dependency resolution.
6
+ */
7
+ import * as k8s from '@kubernetes/client-node';
8
+ import { DependencyResolver } from '../dependencies/index.js';
9
+ import { CircularDependencyError } from '../errors.js';
10
+ import { getComponentLogger } from '../logging/index.js';
11
+ import { ReferenceResolver, DeploymentMode } from '../references/index.js';
12
+ import { ResourceDeploymentError } from '../types/deployment.js';
13
+ import { ResourceReadinessChecker } from './readiness.js';
14
+ import { StatusHydrator } from './status-hydrator.js';
15
+ import { ensureReadinessEvaluator } from '../../utils/helpers.js';
16
+ export class DirectDeploymentEngine {
17
+ kubeClient;
18
+ deploymentMode;
19
+ dependencyResolver;
20
+ referenceResolver;
21
+ k8sApi;
22
+ readinessChecker;
23
+ statusHydrator;
24
+ deploymentState = new Map();
25
+ readyResources = new Set(); // Track resources that are already ready
26
+ logger = getComponentLogger('deployment-engine');
27
+ constructor(kubeClient, k8sApi, referenceResolver, deploymentMode = DeploymentMode.DIRECT) {
28
+ this.kubeClient = kubeClient;
29
+ this.deploymentMode = deploymentMode;
30
+ this.dependencyResolver = new DependencyResolver();
31
+ this.referenceResolver = referenceResolver || new ReferenceResolver(kubeClient, this.deploymentMode, k8sApi);
32
+ this.k8sApi = k8sApi || kubeClient.makeApiClient(k8s.KubernetesObjectApi);
33
+ this.readinessChecker = new ResourceReadinessChecker(this.k8sApi);
34
+ this.statusHydrator = new StatusHydrator(this.k8sApi);
35
+ // Set up callback to track ready resources
36
+ this.readinessChecker.setOnResourceReady((resource) => {
37
+ const resourceKey = `${resource.kind}/${resource.name}/${resource.namespace}`;
38
+ this.readyResources.add(resourceKey);
39
+ this.logger.debug('Resource marked as ready via generic readiness checker', {
40
+ resourceKey,
41
+ totalReady: this.readyResources.size
42
+ });
43
+ });
44
+ }
45
+ /**
46
+ * Get the Kubernetes API client for external integrations
47
+ * @returns The configured KubernetesObjectApi instance
48
+ */
49
+ getKubernetesApi() {
50
+ return this.k8sApi;
51
+ }
52
+ /**
53
+ * Check if a deployed resource is ready using the factory-provided readiness evaluator
54
+ */
55
+ async isDeployedResourceReady(deployedResource) {
56
+ try {
57
+ // Check if the deployed resource has a factory-provided readiness evaluator
58
+ const readinessEvaluator = deployedResource.manifest.readinessEvaluator;
59
+ if (readinessEvaluator) {
60
+ // Use the factory-provided readiness evaluator
61
+ // Create a resource reference for the API call
62
+ const resourceRef = {
63
+ apiVersion: deployedResource.manifest.apiVersion || '',
64
+ kind: deployedResource.kind,
65
+ metadata: {
66
+ name: deployedResource.name,
67
+ namespace: deployedResource.namespace,
68
+ },
69
+ };
70
+ // Get the live resource from the cluster
71
+ const liveResource = await this.k8sApi.read(resourceRef);
72
+ // Use the factory-provided readiness evaluator
73
+ const result = readinessEvaluator(liveResource.body);
74
+ if (typeof result === 'boolean') {
75
+ return result;
76
+ }
77
+ else if (result && typeof result === 'object' && 'ready' in result) {
78
+ return result.ready;
79
+ }
80
+ else {
81
+ this.logger.warn('Readiness evaluator returned unexpected result', {
82
+ resourceId: deployedResource.id,
83
+ result
84
+ });
85
+ return false;
86
+ }
87
+ }
88
+ else {
89
+ // Fallback to generic readiness checker
90
+ const resourceRef = {
91
+ apiVersion: deployedResource.manifest.apiVersion || '',
92
+ kind: deployedResource.kind,
93
+ metadata: {
94
+ name: deployedResource.name,
95
+ namespace: deployedResource.namespace,
96
+ },
97
+ };
98
+ const liveResource = await this.k8sApi.read(resourceRef);
99
+ return this.readinessChecker.isResourceReady(liveResource.body);
100
+ }
101
+ }
102
+ catch (error) {
103
+ this.logger.debug('Failed to check resource readiness', {
104
+ error: error,
105
+ resourceId: deployedResource.id,
106
+ kind: deployedResource.kind,
107
+ name: deployedResource.name,
108
+ namespace: deployedResource.namespace
109
+ });
110
+ return false;
111
+ }
112
+ }
113
+ /**
114
+ * Get all deployment states for health checking
115
+ */
116
+ getAllDeploymentStates() {
117
+ return Array.from(this.deploymentState.values());
118
+ }
119
+ /**
120
+ * Deploy a resource graph to the Kubernetes cluster
121
+ */
122
+ async deploy(graph, options) {
123
+ const deploymentId = this.generateDeploymentId();
124
+ const startTime = Date.now();
125
+ const deployedResources = [];
126
+ const errors = [];
127
+ const deploymentLogger = this.logger.child({ deploymentId, resourceCount: graph.resources.length });
128
+ deploymentLogger.info('Starting deployment', { options });
129
+ try {
130
+ this.emitEvent(options, {
131
+ type: 'started',
132
+ message: `Starting deployment of ${graph.resources.length} resources`,
133
+ timestamp: new Date(),
134
+ });
135
+ // 1. Validate no cycles in dependency graph
136
+ deploymentLogger.debug('Validating dependency graph', { dependencyGraph: graph.dependencyGraph });
137
+ this.dependencyResolver.validateNoCycles(graph.dependencyGraph);
138
+ // 2. Analyze deployment order and identify parallel stages
139
+ deploymentLogger.debug('Analyzing deployment order for parallel execution');
140
+ const deploymentPlan = this.dependencyResolver.analyzeDeploymentOrder(graph.dependencyGraph);
141
+ deploymentLogger.debug('Deployment plan determined', {
142
+ levels: deploymentPlan.levels.length,
143
+ totalResources: deploymentPlan.totalResources,
144
+ maxParallelism: deploymentPlan.maxParallelism
145
+ });
146
+ // 3. Create resolution context
147
+ const context = {
148
+ deployedResources,
149
+ kubeClient: this.kubeClient,
150
+ ...(options.namespace && { namespace: options.namespace }),
151
+ timeout: options.timeout || 30000,
152
+ };
153
+ // 4. Deploy resources in parallel stages
154
+ for (let levelIndex = 0; levelIndex < deploymentPlan.levels.length; levelIndex++) {
155
+ const currentLevel = deploymentPlan.levels[levelIndex];
156
+ if (!currentLevel) {
157
+ continue;
158
+ }
159
+ const levelLogger = deploymentLogger.child({
160
+ level: levelIndex + 1,
161
+ resourceCount: currentLevel.length
162
+ });
163
+ levelLogger.debug(`Deploying level ${levelIndex + 1} with ${currentLevel.length} resources in parallel`);
164
+ // Track performance metrics for this level
165
+ const levelStartTime = Date.now();
166
+ // Deploy all resources in this level in parallel
167
+ const levelPromises = currentLevel.map(async (resourceId) => {
168
+ const resourceLogger = deploymentLogger.child({ resourceId });
169
+ resourceLogger.debug('Starting resource deployment');
170
+ const resource = graph.resources.find((r) => r.id === resourceId);
171
+ if (!resource) {
172
+ resourceLogger.error('Resource not found in graph');
173
+ const error = new Error(`Resource with id '${resourceId}' not found in graph`);
174
+ return {
175
+ success: false,
176
+ resourceId,
177
+ error: {
178
+ resourceId,
179
+ phase: 'validation',
180
+ error,
181
+ timestamp: new Date(),
182
+ }
183
+ };
184
+ }
185
+ resourceLogger.debug('Found resource in graph', {
186
+ resourceId: resource.id,
187
+ kind: resource.manifest?.kind,
188
+ name: resource.manifest?.metadata?.name
189
+ });
190
+ try {
191
+ resourceLogger.debug('Calling deploySingleResource');
192
+ // Wait for CRD establishment if this is a custom resource
193
+ await this.waitForCRDIfCustomResource(resource.manifest, options, resourceLogger);
194
+ // FIX: Unconditionally ensure the readiness evaluator is attached just before deployment.
195
+ const resourceWithEvaluator = ensureReadinessEvaluator(resource.manifest);
196
+ const deployedResource = await this.deploySingleResource(resourceWithEvaluator, context, options);
197
+ resourceLogger.debug('Resource deployed successfully');
198
+ return {
199
+ success: true,
200
+ resourceId,
201
+ deployedResource
202
+ };
203
+ }
204
+ catch (error) {
205
+ resourceLogger.error('Resource deployment failed', error);
206
+ const failedResource = {
207
+ id: resourceId,
208
+ kind: resource.manifest.kind,
209
+ name: resource.manifest.metadata?.name || 'unknown',
210
+ namespace: resource.manifest.metadata?.namespace || 'default',
211
+ manifest: resource.manifest,
212
+ status: 'failed',
213
+ deployedAt: new Date(),
214
+ error: error,
215
+ };
216
+ return {
217
+ success: false,
218
+ resourceId,
219
+ deployedResource: failedResource,
220
+ error: {
221
+ resourceId,
222
+ phase: 'deployment',
223
+ error: error,
224
+ timestamp: new Date(),
225
+ }
226
+ };
227
+ }
228
+ });
229
+ // Wait for all resources in this level to complete
230
+ const levelResults = await Promise.allSettled(levelPromises);
231
+ // Process results and handle errors
232
+ let levelHasFailures = false;
233
+ for (const result of levelResults) {
234
+ if (result.status === 'fulfilled') {
235
+ const deploymentResult = result.value;
236
+ if (deploymentResult.success && deploymentResult.deployedResource) {
237
+ deployedResources.push(deploymentResult.deployedResource);
238
+ }
239
+ else {
240
+ levelHasFailures = true;
241
+ if (deploymentResult.error) {
242
+ errors.push(deploymentResult.error);
243
+ }
244
+ if (deploymentResult.deployedResource) {
245
+ deployedResources.push(deploymentResult.deployedResource);
246
+ }
247
+ }
248
+ }
249
+ else {
250
+ // Promise was rejected
251
+ levelHasFailures = true;
252
+ levelLogger.error('Unexpected promise rejection in parallel deployment', result.reason);
253
+ }
254
+ }
255
+ // Handle rollback if there are failures and rollback is enabled
256
+ if (levelHasFailures && options.rollbackOnFailure) {
257
+ levelLogger.warn('Level deployment failed, initiating rollback');
258
+ await this.rollbackDeployedResources(deployedResources, options);
259
+ const duration = Date.now() - startTime;
260
+ this.emitEvent(options, {
261
+ type: 'rollback',
262
+ message: `Deployment failed and rolled back in ${duration}ms`,
263
+ timestamp: new Date(),
264
+ });
265
+ return {
266
+ deploymentId,
267
+ resources: deployedResources,
268
+ dependencyGraph: graph.dependencyGraph,
269
+ duration,
270
+ status: 'failed',
271
+ errors,
272
+ };
273
+ }
274
+ // Calculate level performance metrics
275
+ const levelDuration = Date.now() - levelStartTime;
276
+ const successfulCount = levelResults.filter(r => r.status === 'fulfilled' && r.value.success).length;
277
+ const failedCount = levelResults.filter(r => r.status === 'rejected' || (r.status === 'fulfilled' && !r.value.success)).length;
278
+ const isTestEnvironment = process.env.NODE_ENV === 'test' || process.env.VITEST === 'true';
279
+ // Use debug level in test environments to reduce noise, info level in production
280
+ const logLevel = isTestEnvironment ? 'debug' : 'info';
281
+ levelLogger[logLevel](`Level ${levelIndex + 1} deployment completed`, {
282
+ successful: successfulCount,
283
+ failed: failedCount,
284
+ duration: levelDuration,
285
+ parallelism: currentLevel.length,
286
+ averageTimePerResource: Math.round(levelDuration / currentLevel.length)
287
+ });
288
+ }
289
+ const duration = Date.now() - startTime;
290
+ const successfulResources = deployedResources.filter((r) => r.status !== 'failed');
291
+ const status = errors.length === 0 ? 'success' : successfulResources.length > 0 ? 'partial' : 'failed';
292
+ // Log comprehensive performance metrics
293
+ const isTestEnvironment = process.env.NODE_ENV === 'test' || process.env.VITEST === 'true';
294
+ // Use debug level in test environments to reduce noise, info level in production
295
+ const logLevel = isTestEnvironment ? 'debug' : 'info';
296
+ deploymentLogger[logLevel]('Parallel deployment performance metrics', {
297
+ totalDuration: duration,
298
+ totalResources: deploymentPlan.totalResources,
299
+ parallelLevels: deploymentPlan.levels.length,
300
+ maxParallelism: deploymentPlan.maxParallelism,
301
+ averageTimePerResource: Math.round(duration / deploymentPlan.totalResources),
302
+ successfulResources: successfulResources.length,
303
+ failedResources: errors.length,
304
+ parallelismEfficiency: Math.round((deploymentPlan.totalResources / deploymentPlan.levels.length) / deploymentPlan.maxParallelism * 100),
305
+ status
306
+ });
307
+ this.emitEvent(options, {
308
+ type: status === 'success' ? 'completed' : 'failed',
309
+ message: `Deployment ${status} in ${duration}ms (${deploymentPlan.levels.length} parallel levels, max ${deploymentPlan.maxParallelism} concurrent)`,
310
+ timestamp: new Date(),
311
+ });
312
+ // Store deployment state for rollback
313
+ this.deploymentState.set(deploymentId, {
314
+ deploymentId,
315
+ resources: deployedResources,
316
+ dependencyGraph: graph.dependencyGraph,
317
+ startTime: new Date(startTime),
318
+ endTime: new Date(),
319
+ status: status === 'success' ? 'completed' : status === 'partial' ? 'completed' : 'failed',
320
+ options,
321
+ });
322
+ return {
323
+ deploymentId,
324
+ resources: deployedResources,
325
+ dependencyGraph: graph.dependencyGraph,
326
+ duration,
327
+ status,
328
+ errors,
329
+ };
330
+ }
331
+ catch (error) {
332
+ // Re-throw circular dependency errors immediately - these are configuration errors
333
+ if (error instanceof CircularDependencyError) {
334
+ throw error;
335
+ }
336
+ const duration = Date.now() - startTime;
337
+ this.emitEvent(options, {
338
+ type: 'failed',
339
+ message: `Deployment failed: ${error}`,
340
+ timestamp: new Date(),
341
+ error: error,
342
+ });
343
+ // Store deployment state even for failed deployments (for rollback)
344
+ this.deploymentState.set(deploymentId, {
345
+ deploymentId,
346
+ resources: deployedResources,
347
+ dependencyGraph: graph.dependencyGraph,
348
+ startTime: new Date(startTime),
349
+ endTime: new Date(),
350
+ status: 'failed',
351
+ options,
352
+ });
353
+ return {
354
+ deploymentId,
355
+ resources: deployedResources,
356
+ dependencyGraph: graph.dependencyGraph,
357
+ duration,
358
+ status: 'failed',
359
+ errors: [
360
+ {
361
+ resourceId: 'deployment',
362
+ phase: 'deployment',
363
+ error: error,
364
+ timestamp: new Date(),
365
+ },
366
+ ],
367
+ };
368
+ }
369
+ }
370
+ /**
371
+ * Analyze closure dependencies to determine execution levels
372
+ */
373
+ analyzeClosureDependencies(closures, spec, dependencyGraph) {
374
+ const closureDependencies = [];
375
+ for (const [name, closure] of Object.entries(closures)) {
376
+ // For now, analyze dependencies by examining the closure's configuration
377
+ // This is a simplified implementation - in practice, we would need to analyze
378
+ // the closure's arguments to detect resource references
379
+ const dependencies = this.extractClosureDependencies(closure, spec);
380
+ // Determine execution level based on dependencies
381
+ // For now, assign all closures to level -1 to ensure they run before all resources
382
+ // This is especially important for closures that install CRDs (like fluxSystem)
383
+ let level = -1;
384
+ if (dependencies.length > 0) {
385
+ // Find the maximum level of any dependency + 1
386
+ for (const depId of dependencies) {
387
+ const depLevel = this.getResourceLevel(depId, dependencyGraph);
388
+ level = Math.max(level, depLevel + 1);
389
+ }
390
+ }
391
+ closureDependencies.push({
392
+ name,
393
+ closure,
394
+ dependencies,
395
+ level,
396
+ });
397
+ }
398
+ return closureDependencies;
399
+ }
400
+ /**
401
+ * Extract dependencies from a closure by analyzing its configuration
402
+ * This is a simplified implementation - in practice, we would need more sophisticated analysis
403
+ */
404
+ extractClosureDependencies(closure, spec) {
405
+ // For now, return empty dependencies since closures typically don't depend on Enhanced<> resources
406
+ // In the future, this could analyze closure arguments for resource references
407
+ return [];
408
+ }
409
+ /**
410
+ * Get the execution level of a resource in the dependency graph
411
+ */
412
+ getResourceLevel(resourceId, dependencyGraph) {
413
+ // Find the level where this resource appears in the deployment plan
414
+ const deploymentPlan = this.dependencyResolver.analyzeDeploymentOrder(dependencyGraph);
415
+ for (let levelIndex = 0; levelIndex < deploymentPlan.levels.length; levelIndex++) {
416
+ const level = deploymentPlan.levels[levelIndex];
417
+ if (level && level.includes(resourceId)) {
418
+ return levelIndex;
419
+ }
420
+ }
421
+ return 0; // Default to level 0 if not found
422
+ }
423
+ /**
424
+ * Integrate closures into the deployment plan based on their dependencies
425
+ */
426
+ integrateClosuresIntoPlan(deploymentPlan, closureDependencies) {
427
+ // Create enhanced levels with both resources and closures
428
+ const enhancedLevels = [];
429
+ // Check if we have any closures at level -1 (pre-resource level)
430
+ const preResourceClosures = closureDependencies.filter(c => c.level === -1);
431
+ // If we have pre-resource closures, add them as level 0 and shift everything else
432
+ if (preResourceClosures.length > 0) {
433
+ enhancedLevels.push({
434
+ resources: [],
435
+ closures: preResourceClosures,
436
+ });
437
+ }
438
+ // Initialize levels with existing resources (shifted if we added a pre-resource level)
439
+ for (let i = 0; i < deploymentPlan.levels.length; i++) {
440
+ enhancedLevels.push({
441
+ resources: deploymentPlan.levels[i] || [],
442
+ closures: [],
443
+ });
444
+ }
445
+ // Add closures to their appropriate levels (excluding level -1 which we already handled)
446
+ for (const closureInfo of closureDependencies) {
447
+ if (closureInfo.level === -1) {
448
+ continue; // Already handled above
449
+ }
450
+ // Adjust level index if we added a pre-resource level
451
+ const adjustedLevel = preResourceClosures.length > 0 ? closureInfo.level + 1 : closureInfo.level;
452
+ // Ensure we have enough levels
453
+ while (enhancedLevels.length <= adjustedLevel) {
454
+ enhancedLevels.push({ resources: [], closures: [] });
455
+ }
456
+ const targetLevel = enhancedLevels[adjustedLevel];
457
+ if (targetLevel) {
458
+ targetLevel.closures.push(closureInfo);
459
+ }
460
+ }
461
+ return {
462
+ levels: enhancedLevels,
463
+ totalResources: deploymentPlan.totalResources,
464
+ totalClosures: closureDependencies.length,
465
+ maxParallelism: Math.max(deploymentPlan.maxParallelism, Math.max(...enhancedLevels.map(level => level.closures.length))),
466
+ };
467
+ }
468
+ /**
469
+ * Deploy a resource graph with deployment closures integrated into level-based execution
470
+ */
471
+ async deployWithClosures(graph, closures, options, spec, alchemyScope) {
472
+ const deploymentId = this.generateDeploymentId();
473
+ const startTime = Date.now();
474
+ const deployedResources = [];
475
+ const errors = [];
476
+ const deploymentLogger = this.logger.child({
477
+ deploymentId,
478
+ resourceCount: graph.resources.length,
479
+ closureCount: Object.keys(closures).length
480
+ });
481
+ deploymentLogger.info('Starting deployment with closures', {
482
+ options,
483
+ closures: Object.keys(closures)
484
+ });
485
+ try {
486
+ this.emitEvent(options, {
487
+ type: 'started',
488
+ message: `Starting deployment of ${graph.resources.length} resources and ${Object.keys(closures).length} closures`,
489
+ timestamp: new Date(),
490
+ });
491
+ // 1. Validate no cycles in dependency graph
492
+ deploymentLogger.debug('Validating dependency graph', { dependencyGraph: graph.dependencyGraph });
493
+ this.dependencyResolver.validateNoCycles(graph.dependencyGraph);
494
+ // 2. Analyze deployment order and identify parallel stages
495
+ deploymentLogger.debug('Analyzing deployment order for parallel execution');
496
+ const deploymentPlan = this.dependencyResolver.analyzeDeploymentOrder(graph.dependencyGraph);
497
+ deploymentLogger.debug('Deployment plan determined', {
498
+ levels: deploymentPlan.levels.length,
499
+ totalResources: deploymentPlan.totalResources,
500
+ maxParallelism: deploymentPlan.maxParallelism
501
+ });
502
+ // 3. Analyze closure dependencies and integrate into deployment plan
503
+ const closureDependencies = this.analyzeClosureDependencies(closures, spec, graph.dependencyGraph);
504
+ const enhancedPlan = this.integrateClosuresIntoPlan(deploymentPlan, closureDependencies);
505
+ deploymentLogger.debug('Enhanced deployment plan with closures', {
506
+ levels: enhancedPlan.levels.length,
507
+ totalResources: enhancedPlan.totalResources,
508
+ totalClosures: enhancedPlan.totalClosures,
509
+ maxParallelism: enhancedPlan.maxParallelism
510
+ });
511
+ // 4. Create resolution context
512
+ const context = {
513
+ deployedResources,
514
+ kubeClient: this.kubeClient,
515
+ ...(options.namespace && { namespace: options.namespace }),
516
+ timeout: options.timeout || 30000,
517
+ };
518
+ // 5. Deploy resources and closures level by level with proper dependency handling
519
+ for (let levelIndex = 0; levelIndex < enhancedPlan.levels.length; levelIndex++) {
520
+ const currentLevel = enhancedPlan.levels[levelIndex];
521
+ if (!currentLevel) {
522
+ continue;
523
+ }
524
+ const levelLogger = deploymentLogger.child({
525
+ level: levelIndex + 1,
526
+ resourceCount: currentLevel.resources.length,
527
+ closureCount: currentLevel.closures.length
528
+ });
529
+ levelLogger.debug(`Deploying level ${levelIndex + 1} with ${currentLevel.resources.length} resources and ${currentLevel.closures.length} closures in parallel`);
530
+ const levelStartTime = Date.now();
531
+ // Create deployment context for closures at this level
532
+ const deployedResourcesMap = new Map();
533
+ // Populate with resources from previous levels
534
+ for (const resource of deployedResources) {
535
+ deployedResourcesMap.set(resource.id, resource);
536
+ }
537
+ const deploymentContext = {
538
+ kubernetesApi: this.k8sApi,
539
+ ...(alchemyScope && { alchemyScope }),
540
+ ...(options.namespace && { namespace: options.namespace }),
541
+ deployedResources: deployedResourcesMap,
542
+ resolveReference: async (ref) => {
543
+ // Enhanced reference resolution - will be improved in future tasks
544
+ return ref;
545
+ },
546
+ };
547
+ // Prepare promises for both resources and closures
548
+ const levelPromises = [];
549
+ // Add resource deployment promises
550
+ const resourcePromises = currentLevel.resources.map(async (resourceId) => {
551
+ const resourceLogger = deploymentLogger.child({ resourceId });
552
+ resourceLogger.debug('Starting resource deployment');
553
+ const resource = graph.resources.find((r) => r.id === resourceId);
554
+ if (!resource) {
555
+ resourceLogger.error('Resource not found in graph');
556
+ const error = new Error(`Resource with id '${resourceId}' not found in graph`);
557
+ return {
558
+ success: false,
559
+ resourceId,
560
+ error: {
561
+ resourceId,
562
+ phase: 'validation',
563
+ error,
564
+ timestamp: new Date(),
565
+ }
566
+ };
567
+ }
568
+ resourceLogger.debug('Found resource in graph', {
569
+ resourceId: resource.id,
570
+ kind: resource.manifest?.kind,
571
+ name: resource.manifest?.metadata?.name
572
+ });
573
+ try {
574
+ resourceLogger.debug('Calling deploySingleResource');
575
+ const resourceWithEvaluator = ensureReadinessEvaluator(resource.manifest);
576
+ const deployedResource = await this.deploySingleResource(resourceWithEvaluator, context, options);
577
+ resourceLogger.debug('Resource deployed successfully');
578
+ return {
579
+ success: true,
580
+ resourceId,
581
+ deployedResource
582
+ };
583
+ }
584
+ catch (error) {
585
+ resourceLogger.error('Resource deployment failed', error);
586
+ const failedResource = {
587
+ id: resourceId,
588
+ kind: resource.manifest.kind,
589
+ name: resource.manifest.metadata?.name || 'unknown',
590
+ namespace: resource.manifest.metadata?.namespace || 'default',
591
+ manifest: resource.manifest,
592
+ status: 'failed',
593
+ deployedAt: new Date(),
594
+ error: error,
595
+ };
596
+ return {
597
+ success: false,
598
+ resourceId,
599
+ deployedResource: failedResource,
600
+ error: {
601
+ resourceId,
602
+ phase: 'deployment',
603
+ error: error,
604
+ timestamp: new Date(),
605
+ }
606
+ };
607
+ }
608
+ });
609
+ // Add closure execution promises
610
+ const closurePromises = currentLevel.closures.map(async (closureInfo) => {
611
+ const closureLogger = levelLogger.child({ closureName: closureInfo.name });
612
+ closureLogger.debug('Executing closure at level', { level: levelIndex + 1 });
613
+ try {
614
+ const result = await closureInfo.closure(deploymentContext);
615
+ closureLogger.debug('Closure executed successfully', { resultCount: result?.length || 0 });
616
+ return {
617
+ success: true,
618
+ type: 'closure',
619
+ name: closureInfo.name,
620
+ result
621
+ };
622
+ }
623
+ catch (error) {
624
+ closureLogger.error('Closure execution failed', error);
625
+ return {
626
+ success: false,
627
+ type: 'closure',
628
+ name: closureInfo.name,
629
+ error: {
630
+ resourceId: `closure-${closureInfo.name}`,
631
+ phase: 'deployment',
632
+ error: error,
633
+ timestamp: new Date(),
634
+ }
635
+ };
636
+ }
637
+ });
638
+ // Combine all promises for this level
639
+ levelPromises.push(...resourcePromises, ...closurePromises);
640
+ // Wait for all resources and closures in this level to complete
641
+ const levelResults = await Promise.allSettled(levelPromises);
642
+ // Process results and handle errors
643
+ let levelHasFailures = false;
644
+ let successfulResources = 0;
645
+ let successfulClosures = 0;
646
+ let failedResources = 0;
647
+ let failedClosures = 0;
648
+ for (const result of levelResults) {
649
+ if (result.status === 'fulfilled') {
650
+ const deploymentResult = result.value;
651
+ if (deploymentResult.type === 'closure') {
652
+ // Handle closure result
653
+ if (deploymentResult.success) {
654
+ successfulClosures++;
655
+ }
656
+ else {
657
+ levelHasFailures = true;
658
+ failedClosures++;
659
+ if (deploymentResult.error) {
660
+ errors.push(deploymentResult.error);
661
+ }
662
+ }
663
+ }
664
+ else {
665
+ // Handle resource result
666
+ if (deploymentResult.success && deploymentResult.deployedResource) {
667
+ deployedResources.push(deploymentResult.deployedResource);
668
+ successfulResources++;
669
+ }
670
+ else {
671
+ levelHasFailures = true;
672
+ failedResources++;
673
+ if (deploymentResult.error) {
674
+ errors.push(deploymentResult.error);
675
+ }
676
+ if (deploymentResult.deployedResource) {
677
+ deployedResources.push(deploymentResult.deployedResource);
678
+ }
679
+ }
680
+ }
681
+ }
682
+ else {
683
+ levelHasFailures = true;
684
+ levelLogger.error('Unexpected promise rejection in parallel deployment', result.reason);
685
+ }
686
+ }
687
+ // Handle rollback if there are failures and rollback is enabled
688
+ if (levelHasFailures && options.rollbackOnFailure) {
689
+ levelLogger.warn('Level deployment failed, initiating rollback');
690
+ await this.rollbackDeployedResources(deployedResources, options);
691
+ const duration = Date.now() - startTime;
692
+ this.emitEvent(options, {
693
+ type: 'rollback',
694
+ message: `Deployment failed and rolled back in ${duration}ms`,
695
+ timestamp: new Date(),
696
+ });
697
+ return {
698
+ deploymentId,
699
+ resources: deployedResources,
700
+ dependencyGraph: graph.dependencyGraph,
701
+ duration,
702
+ status: 'failed',
703
+ errors,
704
+ };
705
+ }
706
+ // Calculate level performance metrics
707
+ const levelDuration = Date.now() - levelStartTime;
708
+ const totalOperations = currentLevel.resources.length + currentLevel.closures.length;
709
+ const isTestEnvironment = process.env.NODE_ENV === 'test' || process.env.VITEST === 'true';
710
+ const logLevel = isTestEnvironment ? 'debug' : 'info';
711
+ levelLogger[logLevel](`Level ${levelIndex + 1} deployment completed`, {
712
+ resources: { successful: successfulResources, failed: failedResources },
713
+ closures: { successful: successfulClosures, failed: failedClosures },
714
+ duration: levelDuration,
715
+ parallelism: totalOperations,
716
+ averageTimePerOperation: totalOperations > 0 ? Math.round(levelDuration / totalOperations) : 0
717
+ });
718
+ }
719
+ const duration = Date.now() - startTime;
720
+ const successfulResources = deployedResources.filter((r) => r.status !== 'failed');
721
+ const status = errors.length === 0 ? 'success' : successfulResources.length > 0 ? 'partial' : 'failed';
722
+ // Log comprehensive performance metrics
723
+ const isTestEnvironment = process.env.NODE_ENV === 'test' || process.env.VITEST === 'true';
724
+ const logLevel = isTestEnvironment ? 'debug' : 'info';
725
+ deploymentLogger[logLevel]('Parallel deployment with closures performance metrics', {
726
+ totalDuration: duration,
727
+ totalResources: enhancedPlan.totalResources,
728
+ totalClosures: enhancedPlan.totalClosures,
729
+ parallelLevels: enhancedPlan.levels.length,
730
+ maxParallelism: enhancedPlan.maxParallelism,
731
+ averageTimePerResource: enhancedPlan.totalResources > 0 ? Math.round(duration / enhancedPlan.totalResources) : 0,
732
+ successfulResources: successfulResources.length,
733
+ failedResources: errors.length,
734
+ status
735
+ });
736
+ this.emitEvent(options, {
737
+ type: status === 'success' ? 'completed' : 'failed',
738
+ message: `Deployment with closures ${status} in ${duration}ms (${enhancedPlan.totalClosures} closures + ${enhancedPlan.totalResources} resources across ${enhancedPlan.levels.length} levels)`,
739
+ timestamp: new Date(),
740
+ });
741
+ // Store deployment state for rollback
742
+ this.deploymentState.set(deploymentId, {
743
+ deploymentId,
744
+ resources: deployedResources,
745
+ dependencyGraph: graph.dependencyGraph,
746
+ startTime: new Date(startTime),
747
+ endTime: new Date(),
748
+ status: status === 'success' ? 'completed' : status === 'partial' ? 'completed' : 'failed',
749
+ options,
750
+ });
751
+ return {
752
+ deploymentId,
753
+ resources: deployedResources,
754
+ dependencyGraph: graph.dependencyGraph,
755
+ duration,
756
+ status,
757
+ errors,
758
+ };
759
+ }
760
+ catch (error) {
761
+ // Re-throw circular dependency errors immediately - these are configuration errors
762
+ if (error instanceof CircularDependencyError) {
763
+ throw error;
764
+ }
765
+ const duration = Date.now() - startTime;
766
+ this.emitEvent(options, {
767
+ type: 'failed',
768
+ message: `Deployment with closures failed: ${error}`,
769
+ timestamp: new Date(),
770
+ error: error,
771
+ });
772
+ // Store deployment state even for failed deployments (for rollback)
773
+ this.deploymentState.set(deploymentId, {
774
+ deploymentId,
775
+ resources: deployedResources,
776
+ dependencyGraph: graph.dependencyGraph,
777
+ startTime: new Date(startTime),
778
+ endTime: new Date(),
779
+ status: 'failed',
780
+ options,
781
+ });
782
+ return {
783
+ deploymentId,
784
+ resources: deployedResources,
785
+ dependencyGraph: graph.dependencyGraph,
786
+ duration,
787
+ status: 'failed',
788
+ errors: [
789
+ {
790
+ resourceId: 'deployment',
791
+ phase: 'deployment',
792
+ error: error,
793
+ timestamp: new Date(),
794
+ },
795
+ ],
796
+ };
797
+ }
798
+ } /**
799
+
800
+ * Deploy a single resource
801
+ */
802
+ async deploySingleResource(resource, context, options) {
803
+ const resourceId = resource.id || resource.__resourceId || resource.metadata?.name || 'unknown';
804
+ const resourceLogger = this.logger.child({
805
+ resourceId,
806
+ kind: resource.kind,
807
+ name: resource.metadata?.name
808
+ });
809
+ resourceLogger.debug('Starting single resource deployment');
810
+ this.emitEvent(options, {
811
+ type: 'progress',
812
+ resourceId,
813
+ message: `Deploying ${resource.kind}/${resource.metadata?.name}`,
814
+ timestamp: new Date(),
815
+ });
816
+ // 1. Resolve all references in the resource
817
+ let resolvedResource;
818
+ try {
819
+ resourceLogger.debug('Resolving resource references', {
820
+ originalMetadata: resource.metadata
821
+ });
822
+ const resolveTimeout = options.timeout || 30000;
823
+ resolvedResource = (await Promise.race([
824
+ this.referenceResolver.resolveReferences(resource, context),
825
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Reference resolution timeout')), resolveTimeout)),
826
+ ]));
827
+ resourceLogger.debug('References resolved successfully', {
828
+ resolvedMetadata: resolvedResource.metadata,
829
+ hasReadinessEvaluator: !!resolvedResource.readinessEvaluator
830
+ });
831
+ }
832
+ catch (error) {
833
+ resourceLogger.warn('Reference resolution failed, using original resource', error);
834
+ resolvedResource = resource;
835
+ }
836
+ // 2. Apply namespace if specified, but only if resource doesn't already have one
837
+ if (options.namespace && resolvedResource.metadata && typeof resolvedResource.metadata.namespace !== 'string') {
838
+ resourceLogger.debug('Applying namespace from deployment options', {
839
+ targetNamespace: options.namespace,
840
+ currentNamespace: resolvedResource.metadata.namespace,
841
+ currentNamespaceType: typeof resolvedResource.metadata.namespace
842
+ });
843
+ // Create a completely new metadata object to avoid proxy issues
844
+ const newMetadata = {
845
+ ...resolvedResource.metadata,
846
+ namespace: options.namespace,
847
+ };
848
+ // Preserve the readiness evaluator when creating the new resource
849
+ const newResolvedResource = {
850
+ ...resolvedResource,
851
+ metadata: newMetadata,
852
+ };
853
+ // Copy the non-enumerable readiness evaluator if it exists
854
+ const readinessEvaluator = resolvedResource.readinessEvaluator;
855
+ if (readinessEvaluator) {
856
+ Object.defineProperty(newResolvedResource, 'readinessEvaluator', {
857
+ value: readinessEvaluator,
858
+ enumerable: false,
859
+ configurable: true,
860
+ writable: false
861
+ });
862
+ }
863
+ resolvedResource = newResolvedResource;
864
+ }
865
+ // 3. Apply the resource to the cluster (or simulate for dry run)
866
+ let appliedResource;
867
+ if (options.dryRun) {
868
+ // In dry run mode, don't actually create the resource
869
+ resourceLogger.debug('Dry run mode: simulating resource creation');
870
+ appliedResource = {
871
+ ...resolvedResource,
872
+ metadata: {
873
+ ...resolvedResource.metadata,
874
+ uid: 'dry-run-uid',
875
+ },
876
+ };
877
+ }
878
+ else {
879
+ // Apply resource with retry logic
880
+ const retryPolicy = options.retryPolicy || {
881
+ maxRetries: 3,
882
+ backoffMultiplier: 2,
883
+ initialDelay: 1000,
884
+ maxDelay: 30000,
885
+ };
886
+ let lastError;
887
+ for (let attempt = 0; attempt <= retryPolicy.maxRetries; attempt++) {
888
+ try {
889
+ resourceLogger.debug('Applying resource to cluster', { attempt });
890
+ // Check if resource already exists
891
+ let existing;
892
+ try {
893
+ const readResult = await this.k8sApi.read({
894
+ apiVersion: resolvedResource.apiVersion,
895
+ kind: resolvedResource.kind,
896
+ metadata: {
897
+ name: resolvedResource.metadata?.name || '',
898
+ namespace: resolvedResource.metadata?.namespace || 'default',
899
+ },
900
+ });
901
+ existing = readResult.body;
902
+ }
903
+ catch (error) {
904
+ // If it's a 404, the resource doesn't exist, which is expected for creation
905
+ if (error.statusCode !== 404) {
906
+ resourceLogger.error('Error checking resource existence', error);
907
+ throw error;
908
+ }
909
+ }
910
+ if (existing) {
911
+ // Resource exists, use patch for safer updates
912
+ resourceLogger.debug('Resource exists, patching');
913
+ const patchResult = await this.k8sApi.patch(resolvedResource);
914
+ appliedResource = patchResult.body;
915
+ }
916
+ else {
917
+ // Resource does not exist, create it
918
+ resourceLogger.debug('Resource does not exist, creating');
919
+ const createResult = await this.k8sApi.create(resolvedResource);
920
+ appliedResource = createResult.body;
921
+ }
922
+ resourceLogger.debug('Resource applied successfully', {
923
+ appliedName: appliedResource.metadata?.name,
924
+ appliedNamespace: appliedResource.metadata?.namespace,
925
+ operation: existing ? 'patched' : 'created',
926
+ attempt
927
+ });
928
+ // Success - break out of retry loop
929
+ break;
930
+ }
931
+ catch (error) {
932
+ lastError = error;
933
+ resourceLogger.error('Failed to apply resource to cluster', lastError, { attempt });
934
+ // If this was the last attempt, throw the error
935
+ if (attempt >= retryPolicy.maxRetries) {
936
+ throw new ResourceDeploymentError(resolvedResource.metadata?.name || 'unknown', resolvedResource.kind || 'Unknown', lastError);
937
+ }
938
+ // Calculate delay for next attempt
939
+ const delay = Math.min(retryPolicy.initialDelay * retryPolicy.backoffMultiplier ** attempt, retryPolicy.maxDelay);
940
+ resourceLogger.debug('Retrying resource deployment', {
941
+ attempt: attempt + 1,
942
+ maxRetries: retryPolicy.maxRetries,
943
+ delay
944
+ });
945
+ // Wait before retrying
946
+ await new Promise(resolve => setTimeout(resolve, delay));
947
+ }
948
+ }
949
+ }
950
+ // 4. Create deployed resource record
951
+ const deployedResource = {
952
+ id: resourceId,
953
+ kind: resolvedResource.kind || 'Unknown',
954
+ name: resolvedResource.metadata?.name || 'unknown',
955
+ namespace: resolvedResource.metadata?.namespace || 'default',
956
+ manifest: resolvedResource,
957
+ status: 'deployed',
958
+ deployedAt: new Date(),
959
+ };
960
+ // 5. Wait for resource to be ready if requested
961
+ if (options.waitForReady !== false) {
962
+ resourceLogger.debug('Waiting for resource to be ready');
963
+ await this.waitForResourceReady(deployedResource, options);
964
+ deployedResource.status = 'ready';
965
+ }
966
+ resourceLogger.debug('Single resource deployment completed');
967
+ return deployedResource;
968
+ }
969
+ /**
970
+ * Wait for a resource to be ready
971
+ */
972
+ async waitForResourceReady(deployedResource, options) {
973
+ const resourceKey = `${deployedResource.kind}/${deployedResource.name}/${deployedResource.namespace}`;
974
+ // Check if already marked as ready
975
+ if (deployedResource.status === 'ready' || this.readyResources.has(resourceKey)) {
976
+ this.logger.debug('Resource already marked as ready', { resourceKey });
977
+ return;
978
+ }
979
+ // Safety-first approach: check for readiness evaluator before starting the wait loop
980
+ const readinessEvaluator = deployedResource.manifest.readinessEvaluator;
981
+ // Debug logging removed
982
+ if (!readinessEvaluator) {
983
+ const errorMessage = `Resource ${deployedResource.kind}/${deployedResource.name} does not have a factory-provided readiness evaluator`;
984
+ this.logger.error('Missing factory-provided readiness evaluator');
985
+ throw new Error(errorMessage);
986
+ }
987
+ const startTime = Date.now();
988
+ const timeout = options.timeout || 300000; // 5 minutes default
989
+ let lastStatus = null;
990
+ while (Date.now() - startTime < timeout) {
991
+ try {
992
+ // Use custom readiness evaluator
993
+ const { body: liveResource } = await this.k8sApi.read({
994
+ apiVersion: deployedResource.manifest.apiVersion || '',
995
+ kind: deployedResource.kind,
996
+ metadata: {
997
+ name: deployedResource.name,
998
+ namespace: deployedResource.namespace,
999
+ },
1000
+ });
1001
+ const result = readinessEvaluator(liveResource);
1002
+ if (typeof result === 'boolean') {
1003
+ if (result) {
1004
+ this.readyResources.add(resourceKey);
1005
+ this.emitEvent(options, {
1006
+ type: 'resource-ready',
1007
+ resourceId: deployedResource.id,
1008
+ message: `${deployedResource.kind}/${deployedResource.name} ready (custom evaluator)`,
1009
+ timestamp: new Date(),
1010
+ });
1011
+ return;
1012
+ }
1013
+ }
1014
+ else if (result && typeof result === 'object' && 'ready' in result) {
1015
+ lastStatus = result;
1016
+ if (result.ready) {
1017
+ this.readyResources.add(resourceKey);
1018
+ this.emitEvent(options, {
1019
+ type: 'resource-ready',
1020
+ resourceId: deployedResource.id,
1021
+ message: result.message || `${deployedResource.kind}/${deployedResource.name} ready (custom evaluator)`,
1022
+ timestamp: new Date(),
1023
+ });
1024
+ return;
1025
+ }
1026
+ }
1027
+ // Emit status update if we have status information
1028
+ if (lastStatus && typeof lastStatus === 'object' && 'message' in lastStatus) {
1029
+ this.emitEvent(options, {
1030
+ type: 'resource-status',
1031
+ resourceId: deployedResource.id,
1032
+ message: `${deployedResource.kind}/${deployedResource.name}: ${lastStatus.message}`,
1033
+ timestamp: new Date(),
1034
+ });
1035
+ }
1036
+ // Wait before next check
1037
+ await new Promise(resolve => setTimeout(resolve, 2000));
1038
+ }
1039
+ catch (error) {
1040
+ // Emit error status event
1041
+ this.emitEvent(options, {
1042
+ type: 'resource-status',
1043
+ resourceId: deployedResource.id,
1044
+ message: `Unable to read resource status: ${error instanceof Error ? error.message : String(error)}`,
1045
+ timestamp: new Date(),
1046
+ });
1047
+ // If we can't read the resource, it's not ready yet
1048
+ await new Promise(resolve => setTimeout(resolve, 2000));
1049
+ }
1050
+ }
1051
+ // Timeout reached
1052
+ const timeoutMessage = lastStatus
1053
+ ? `Timeout waiting for ${deployedResource.kind}/${deployedResource.name}: ${lastStatus.message}`
1054
+ : `Timeout waiting for ${deployedResource.kind}/${deployedResource.name} to be ready`;
1055
+ throw new Error(timeoutMessage);
1056
+ }
1057
+ /**
1058
+ * Rollback deployed resources
1059
+ */
1060
+ async rollbackDeployedResources(deployedResources, options) {
1061
+ this.emitEvent(options, {
1062
+ type: 'rollback',
1063
+ message: 'Starting rollback of deployed resources',
1064
+ timestamp: new Date(),
1065
+ });
1066
+ const rolledBackResources = [];
1067
+ const errors = [];
1068
+ // Rollback in reverse order
1069
+ const reversedResources = [...deployedResources].reverse();
1070
+ for (const resource of reversedResources) {
1071
+ // Only try to rollback resources that were actually deployed (not failed)
1072
+ if (resource.status === 'failed') {
1073
+ continue; // Skip resources that failed to deploy
1074
+ }
1075
+ try {
1076
+ await this.k8sApi.delete({
1077
+ apiVersion: resource.manifest.apiVersion || '',
1078
+ kind: resource.kind,
1079
+ metadata: {
1080
+ name: resource.name,
1081
+ namespace: resource.namespace,
1082
+ },
1083
+ });
1084
+ rolledBackResources.push(`${resource.kind}/${resource.name}`);
1085
+ }
1086
+ catch (error) {
1087
+ // Log and collect errors for individual resource deletion failures
1088
+ this.logger.warn('Failed to delete resource during rollback', {
1089
+ error: error,
1090
+ resourceId: resource.id,
1091
+ kind: resource.kind,
1092
+ name: resource.name
1093
+ });
1094
+ errors.push({
1095
+ resourceId: resource.id,
1096
+ phase: 'rollback',
1097
+ error: error,
1098
+ timestamp: new Date(),
1099
+ });
1100
+ }
1101
+ }
1102
+ return { rolledBackResources, errors };
1103
+ }
1104
+ /**
1105
+ * Generate a unique deployment ID
1106
+ */
1107
+ generateDeploymentId() {
1108
+ return `deployment-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
1109
+ }
1110
+ /**
1111
+ * Emit deployment events
1112
+ */
1113
+ emitEvent(options, event) {
1114
+ if (options.progressCallback) {
1115
+ options.progressCallback(event);
1116
+ }
1117
+ }
1118
+ /**
1119
+ * Deploy a single resource (legacy method for compatibility)
1120
+ */
1121
+ async deployResource(resource, options) {
1122
+ const context = {
1123
+ deployedResources: [],
1124
+ kubeClient: this.kubeClient,
1125
+ ...(options.namespace && { namespace: options.namespace }),
1126
+ timeout: options.timeout || 30000,
1127
+ };
1128
+ return this.deploySingleResource(resource, context, options);
1129
+ }
1130
+ /**
1131
+ * Delete a resource from the cluster
1132
+ */
1133
+ async deleteResource(resource) {
1134
+ const deleteLogger = this.logger.child({
1135
+ resourceId: resource.id,
1136
+ kind: resource.kind,
1137
+ name: resource.name
1138
+ });
1139
+ try {
1140
+ await this.k8sApi.delete({
1141
+ apiVersion: resource.manifest.apiVersion || '',
1142
+ kind: resource.kind,
1143
+ metadata: {
1144
+ name: resource.name,
1145
+ namespace: resource.namespace,
1146
+ },
1147
+ });
1148
+ // Wait for resource to be deleted
1149
+ const timeout = 30000; // 30 seconds
1150
+ const startTime = Date.now();
1151
+ while (Date.now() - startTime < timeout) {
1152
+ try {
1153
+ await this.k8sApi.read({
1154
+ apiVersion: resource.manifest.apiVersion || '',
1155
+ kind: resource.kind,
1156
+ metadata: {
1157
+ name: resource.name,
1158
+ namespace: resource.namespace,
1159
+ },
1160
+ });
1161
+ // Resource still exists, wait and try again
1162
+ await new Promise((resolve) => setTimeout(resolve, 1000));
1163
+ }
1164
+ catch (error) {
1165
+ // Resource not found, deletion successful
1166
+ if (this.isNotFoundError(error)) {
1167
+ deleteLogger.debug('Resource successfully deleted');
1168
+ return;
1169
+ }
1170
+ throw error;
1171
+ }
1172
+ }
1173
+ throw new Error(`Timeout waiting for resource ${resource.kind}/${resource.name} to be deleted`);
1174
+ }
1175
+ catch (error) {
1176
+ deleteLogger.error('Failed to delete resource', error);
1177
+ throw error;
1178
+ }
1179
+ }
1180
+ /**
1181
+ * Wait for resource readiness (legacy method for compatibility)
1182
+ */
1183
+ async waitForResourceReadiness(resource, options) {
1184
+ return this.waitForResourceReady(resource, options);
1185
+ }
1186
+ /**
1187
+ * Rollback a deployment by ID
1188
+ */
1189
+ async rollback(deploymentId) {
1190
+ const startTime = Date.now();
1191
+ const deploymentRecord = this.deploymentState.get(deploymentId);
1192
+ if (!deploymentRecord) {
1193
+ throw new Error(`Deployment ${deploymentId} not found. Cannot rollback.`);
1194
+ }
1195
+ try {
1196
+ const { rolledBackResources, errors } = await this.rollbackDeployedResources(deploymentRecord.resources, deploymentRecord.options);
1197
+ const status = errors.length === 0 ? 'success' :
1198
+ rolledBackResources.length > 0 ? 'partial' : 'failed';
1199
+ return {
1200
+ deploymentId,
1201
+ rolledBackResources,
1202
+ duration: Date.now() - startTime,
1203
+ status,
1204
+ errors,
1205
+ };
1206
+ }
1207
+ catch (error) {
1208
+ // This shouldn't happen now since rollbackDeployedResources handles its own errors
1209
+ return {
1210
+ deploymentId,
1211
+ rolledBackResources: [],
1212
+ duration: Date.now() - startTime,
1213
+ status: 'failed',
1214
+ errors: [{
1215
+ resourceId: deploymentId,
1216
+ phase: 'rollback',
1217
+ error: error,
1218
+ timestamp: new Date(),
1219
+ }],
1220
+ };
1221
+ }
1222
+ }
1223
+ /**
1224
+ * Get deployment status by ID
1225
+ */
1226
+ async getStatus(deploymentId) {
1227
+ const deploymentRecord = this.deploymentState.get(deploymentId);
1228
+ if (!deploymentRecord) {
1229
+ return {
1230
+ deploymentId,
1231
+ status: 'unknown',
1232
+ startTime: new Date(),
1233
+ resources: [],
1234
+ };
1235
+ }
1236
+ const result = {
1237
+ deploymentId,
1238
+ status: deploymentRecord.status === 'completed' ? 'completed' :
1239
+ deploymentRecord.status === 'failed' ? 'failed' : 'running',
1240
+ startTime: deploymentRecord.startTime,
1241
+ resources: deploymentRecord.resources,
1242
+ };
1243
+ if (deploymentRecord.endTime) {
1244
+ result.endTime = deploymentRecord.endTime;
1245
+ result.duration = deploymentRecord.endTime.getTime() - deploymentRecord.startTime.getTime();
1246
+ }
1247
+ return result;
1248
+ }
1249
+ /**
1250
+ * Check if an error is a "not found" error
1251
+ */
1252
+ isNotFoundError(error) {
1253
+ if (error && typeof error === 'object') {
1254
+ const k8sError = error;
1255
+ return k8sError.statusCode === 404 || k8sError.body?.code === 404;
1256
+ }
1257
+ return false;
1258
+ }
1259
+ /**
1260
+ * Wait for CRD establishment if the resource is a custom resource
1261
+ */
1262
+ async waitForCRDIfCustomResource(resource, options, logger) {
1263
+ // Skip if this is not a custom resource
1264
+ if (!this.isCustomResource(resource)) {
1265
+ return;
1266
+ }
1267
+ const crdName = await this.getCRDNameForResource(resource);
1268
+ if (!crdName) {
1269
+ logger.warn('Could not determine CRD name for custom resource', {
1270
+ kind: resource.kind,
1271
+ apiVersion: resource.apiVersion
1272
+ });
1273
+ return;
1274
+ }
1275
+ logger.debug('Custom resource detected, waiting for CRD establishment', {
1276
+ resourceKind: resource.kind,
1277
+ crdName
1278
+ });
1279
+ await this.waitForCRDEstablishment({ metadata: { name: crdName } }, options, logger);
1280
+ logger.debug('CRD established, proceeding with custom resource deployment', {
1281
+ resourceKind: resource.kind,
1282
+ crdName
1283
+ });
1284
+ }
1285
+ /**
1286
+ * Check if a resource is a CustomResourceDefinition
1287
+ */
1288
+ isCRD(resource) {
1289
+ return resource.kind === 'CustomResourceDefinition' &&
1290
+ resource.apiVersion?.includes('apiextensions.k8s.io');
1291
+ }
1292
+ /**
1293
+ * Check if a resource is a custom resource (not a built-in Kubernetes resource)
1294
+ */
1295
+ isCustomResource(resource) {
1296
+ if (!resource.apiVersion || !resource.kind) {
1297
+ return false;
1298
+ }
1299
+ // Built-in Kubernetes API groups that are NOT custom resources
1300
+ const builtInApiGroups = [
1301
+ 'v1', // Core API group
1302
+ 'apps/v1',
1303
+ 'extensions/v1beta1',
1304
+ 'networking.k8s.io/v1',
1305
+ 'policy/v1',
1306
+ 'rbac.authorization.k8s.io/v1',
1307
+ 'storage.k8s.io/v1',
1308
+ 'apiextensions.k8s.io/v1', // CRDs themselves
1309
+ 'admissionregistration.k8s.io/v1',
1310
+ 'apiregistration.k8s.io/v1',
1311
+ 'authentication.k8s.io/v1',
1312
+ 'authorization.k8s.io/v1',
1313
+ 'autoscaling/v1',
1314
+ 'autoscaling/v2',
1315
+ 'batch/v1',
1316
+ 'certificates.k8s.io/v1',
1317
+ 'coordination.k8s.io/v1',
1318
+ 'discovery.k8s.io/v1',
1319
+ 'events.k8s.io/v1',
1320
+ 'flowcontrol.apiserver.k8s.io/v1beta3',
1321
+ 'node.k8s.io/v1',
1322
+ 'scheduling.k8s.io/v1'
1323
+ ];
1324
+ return !builtInApiGroups.includes(resource.apiVersion);
1325
+ }
1326
+ /**
1327
+ * Get the CRD name for a custom resource
1328
+ */
1329
+ async getCRDNameForResource(resource) {
1330
+ if (!resource.apiVersion || !resource.kind) {
1331
+ return null;
1332
+ }
1333
+ // Only return CRD name for custom resources
1334
+ if (!this.isCustomResource(resource)) {
1335
+ return null;
1336
+ }
1337
+ // Extract group from apiVersion (e.g., "example.com/v1" -> "example.com")
1338
+ const apiVersionParts = resource.apiVersion.split('/');
1339
+ const group = apiVersionParts.length > 1 ? apiVersionParts[0] : '';
1340
+ if (!group) {
1341
+ return null; // Core API resources don't have CRDs
1342
+ }
1343
+ try {
1344
+ // Try to find the CRD by querying the API
1345
+ const crds = await this.k8sApi.list('apiextensions.k8s.io/v1', 'CustomResourceDefinition');
1346
+ // Look for a CRD that matches our group and kind
1347
+ const matchingCrd = crds.body?.items?.find((crd) => {
1348
+ const crdSpec = crd.spec;
1349
+ return crdSpec?.group === group &&
1350
+ crdSpec?.names?.kind === resource.kind;
1351
+ });
1352
+ if (matchingCrd) {
1353
+ return matchingCrd.metadata?.name;
1354
+ }
1355
+ }
1356
+ catch (error) {
1357
+ // If we can't query CRDs, fall back to heuristic
1358
+ console.warn('Failed to query CRDs, using heuristic for CRD name generation:', error);
1359
+ }
1360
+ // Fallback: Convert Kind to plural lowercase (simple heuristic)
1361
+ const kind = resource.kind.toLowerCase();
1362
+ const plural = kind.endsWith('s') ? kind : `${kind}s`;
1363
+ return `${plural}.${group}`;
1364
+ }
1365
+ /**
1366
+ * Wait for a CRD to be established in the cluster
1367
+ */
1368
+ async waitForCRDEstablishment(crd, options, logger) {
1369
+ const crdName = crd.metadata?.name;
1370
+ const timeout = options.timeout || 300000; // 5 minutes default
1371
+ const startTime = Date.now();
1372
+ const pollInterval = 2000; // 2 seconds
1373
+ logger.debug('Waiting for CRD to exist and be established', { crdName, timeout });
1374
+ while (Date.now() - startTime < timeout) {
1375
+ try {
1376
+ // Check if CRD is established by reading its status
1377
+ const crdStatus = await this.k8sApi.read({
1378
+ apiVersion: 'apiextensions.k8s.io/v1',
1379
+ kind: 'CustomResourceDefinition',
1380
+ metadata: { name: crdName } // CRDs are cluster-scoped, no namespace needed
1381
+ });
1382
+ const conditions = crdStatus.body?.status?.conditions || [];
1383
+ const establishedCondition = conditions.find((c) => c.type === 'Established');
1384
+ if (establishedCondition?.status === 'True') {
1385
+ logger.debug('CRD exists and is established', { crdName });
1386
+ return;
1387
+ }
1388
+ logger.debug('CRD exists but not yet established, waiting...', {
1389
+ crdName,
1390
+ establishedStatus: establishedCondition?.status || 'unknown'
1391
+ });
1392
+ }
1393
+ catch (error) {
1394
+ // CRD might not exist yet (e.g., being installed by a closure)
1395
+ // This is expected in scenarios where closures install CRDs
1396
+ logger.debug('CRD not found yet, waiting for it to be created...', {
1397
+ crdName,
1398
+ error: error.message
1399
+ });
1400
+ }
1401
+ // Wait before next poll
1402
+ await new Promise(resolve => setTimeout(resolve, pollInterval));
1403
+ }
1404
+ // Timeout reached
1405
+ throw new Error(`Timeout waiting for CRD ${crdName} to be established after ${timeout}ms`);
1406
+ }
1407
+ }
1408
+ //# sourceMappingURL=engine.js.map