typekro 0.8.0 → 0.10.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.
- package/dist/.tsbuildinfo +1 -1
- package/dist/alchemy/deployers.d.ts +16 -1
- package/dist/alchemy/deployers.d.ts.map +1 -1
- package/dist/alchemy/deployers.js +131 -18
- package/dist/alchemy/deployers.js.map +1 -1
- package/dist/alchemy/deployment.d.ts +1 -1
- package/dist/alchemy/deployment.d.ts.map +1 -1
- package/dist/alchemy/deployment.js +1 -1
- package/dist/alchemy/deployment.js.map +1 -1
- package/dist/alchemy/kro-delete.d.ts +66 -0
- package/dist/alchemy/kro-delete.d.ts.map +1 -0
- package/dist/alchemy/kro-delete.js +183 -0
- package/dist/alchemy/kro-delete.js.map +1 -0
- package/dist/alchemy/resource-registration.d.ts +16 -0
- package/dist/alchemy/resource-registration.d.ts.map +1 -1
- package/dist/alchemy/resource-registration.js +138 -24
- package/dist/alchemy/resource-registration.js.map +1 -1
- package/dist/alchemy/types.d.ts +8 -4
- package/dist/alchemy/types.d.ts.map +1 -1
- package/dist/aspects.d.ts +3 -0
- package/dist/aspects.d.ts.map +1 -0
- package/dist/aspects.js +2 -0
- package/dist/aspects.js.map +1 -0
- package/dist/compositions/typekro-runtime/typekro-runtime.d.ts +1 -1
- package/dist/compositions/typekro-runtime/typekro-runtime.d.ts.map +1 -1
- package/dist/compositions/typekro-runtime/typekro-runtime.js +27 -9
- package/dist/compositions/typekro-runtime/typekro-runtime.js.map +1 -1
- package/dist/core/aspects/apply.d.ts +30 -0
- package/dist/core/aspects/apply.d.ts.map +1 -0
- package/dist/core/aspects/apply.js +369 -0
- package/dist/core/aspects/apply.js.map +1 -0
- package/dist/core/aspects/dev-aspects.d.ts +14 -0
- package/dist/core/aspects/dev-aspects.d.ts.map +1 -0
- package/dist/core/aspects/dev-aspects.js +70 -0
- package/dist/core/aspects/dev-aspects.js.map +1 -0
- package/dist/core/aspects/index.d.ts +31 -0
- package/dist/core/aspects/index.d.ts.map +1 -0
- package/dist/core/aspects/index.js +30 -0
- package/dist/core/aspects/index.js.map +1 -0
- package/dist/core/aspects/metadata-aspects.d.ts +12 -0
- package/dist/core/aspects/metadata-aspects.d.ts.map +1 -0
- package/dist/core/aspects/metadata-aspects.js +24 -0
- package/dist/core/aspects/metadata-aspects.js.map +1 -0
- package/dist/core/aspects/metadata.d.ts +16 -0
- package/dist/core/aspects/metadata.d.ts.map +1 -0
- package/dist/core/aspects/metadata.js +24 -0
- package/dist/core/aspects/metadata.js.map +1 -0
- package/dist/core/aspects/primitives.d.ts +23 -0
- package/dist/core/aspects/primitives.d.ts.map +1 -0
- package/dist/core/aspects/primitives.js +258 -0
- package/dist/core/aspects/primitives.js.map +1 -0
- package/dist/core/aspects/targets.d.ts +9 -0
- package/dist/core/aspects/targets.d.ts.map +1 -0
- package/dist/core/aspects/targets.js +23 -0
- package/dist/core/aspects/targets.js.map +1 -0
- package/dist/core/aspects/types.d.ts +361 -0
- package/dist/core/aspects/types.d.ts.map +1 -0
- package/dist/core/aspects/types.js +16 -0
- package/dist/core/aspects/types.js.map +1 -0
- package/dist/core/aspects/workload-aspects.d.ts +17 -0
- package/dist/core/aspects/workload-aspects.d.ts.map +1 -0
- package/dist/core/aspects/workload-aspects.js +40 -0
- package/dist/core/aspects/workload-aspects.js.map +1 -0
- package/dist/core/composition/context.d.ts +58 -2
- package/dist/core/composition/context.d.ts.map +1 -1
- package/dist/core/composition/context.js +4 -0
- package/dist/core/composition/context.js.map +1 -1
- package/dist/core/composition/imperative.d.ts +9 -0
- package/dist/core/composition/imperative.d.ts.map +1 -1
- package/dist/core/composition/imperative.js +538 -54
- package/dist/core/composition/imperative.js.map +1 -1
- package/dist/core/composition/nested-status-cel.d.ts +34 -1
- package/dist/core/composition/nested-status-cel.d.ts.map +1 -1
- package/dist/core/composition/nested-status-cel.js +379 -41
- package/dist/core/composition/nested-status-cel.js.map +1 -1
- package/dist/core/composition-debugger.d.ts +1 -1
- package/dist/core/composition-debugger.d.ts.map +1 -1
- package/dist/core/composition-debugger.js.map +1 -1
- package/dist/core/constants/brands.d.ts +1 -1
- package/dist/core/constants/brands.d.ts.map +1 -1
- package/dist/core/constants/brands.js +1 -1
- package/dist/core/constants/brands.js.map +1 -1
- package/dist/core/containers/build.d.ts.map +1 -1
- package/dist/core/containers/build.js +40 -12
- package/dist/core/containers/build.js.map +1 -1
- package/dist/core/dependencies/resolver.d.ts +19 -0
- package/dist/core/dependencies/resolver.d.ts.map +1 -1
- package/dist/core/dependencies/resolver.js +261 -1
- package/dist/core/dependencies/resolver.js.map +1 -1
- package/dist/core/deployment/client-provider-manager.d.ts +9 -3
- package/dist/core/deployment/client-provider-manager.d.ts.map +1 -1
- package/dist/core/deployment/client-provider-manager.js +12 -0
- package/dist/core/deployment/client-provider-manager.js.map +1 -1
- package/dist/core/deployment/crd-manager.d.ts +24 -0
- package/dist/core/deployment/crd-manager.d.ts.map +1 -1
- package/dist/core/deployment/crd-manager.js +79 -1
- package/dist/core/deployment/crd-manager.js.map +1 -1
- package/dist/core/deployment/deployment-state-discovery.d.ts +116 -0
- package/dist/core/deployment/deployment-state-discovery.d.ts.map +1 -0
- package/dist/core/deployment/deployment-state-discovery.js +400 -0
- package/dist/core/deployment/deployment-state-discovery.js.map +1 -0
- package/dist/core/deployment/direct-factory.d.ts +65 -6
- package/dist/core/deployment/direct-factory.d.ts.map +1 -1
- package/dist/core/deployment/direct-factory.js +584 -62
- package/dist/core/deployment/direct-factory.js.map +1 -1
- package/dist/core/deployment/engine.d.ts +64 -3
- package/dist/core/deployment/engine.d.ts.map +1 -1
- package/dist/core/deployment/engine.js +194 -27
- package/dist/core/deployment/engine.js.map +1 -1
- package/dist/core/deployment/event-filter.js +1 -1
- package/dist/core/deployment/event-filter.js.map +1 -1
- package/dist/core/deployment/event-monitor.d.ts +11 -0
- package/dist/core/deployment/event-monitor.d.ts.map +1 -1
- package/dist/core/deployment/event-monitor.js +14 -0
- package/dist/core/deployment/event-monitor.js.map +1 -1
- package/dist/core/deployment/handle-tracing.d.ts +14 -0
- package/dist/core/deployment/handle-tracing.d.ts.map +1 -0
- package/dist/core/deployment/handle-tracing.js +38 -0
- package/dist/core/deployment/handle-tracing.js.map +1 -0
- package/dist/core/deployment/kro-factory.d.ts +115 -3
- package/dist/core/deployment/kro-factory.d.ts.map +1 -1
- package/dist/core/deployment/kro-factory.js +922 -278
- package/dist/core/deployment/kro-factory.js.map +1 -1
- package/dist/core/deployment/kro-readiness.d.ts.map +1 -1
- package/dist/core/deployment/kro-readiness.js +21 -12
- package/dist/core/deployment/kro-readiness.js.map +1 -1
- package/dist/core/deployment/nested-composition-status.d.ts +1 -1
- package/dist/core/deployment/nested-composition-status.d.ts.map +1 -1
- package/dist/core/deployment/nested-composition-status.js +96 -53
- package/dist/core/deployment/nested-composition-status.js.map +1 -1
- package/dist/core/deployment/resource-applier.d.ts +15 -2
- package/dist/core/deployment/resource-applier.d.ts.map +1 -1
- package/dist/core/deployment/resource-applier.js +75 -25
- package/dist/core/deployment/resource-applier.js.map +1 -1
- package/dist/core/deployment/resource-tagging.d.ts +220 -0
- package/dist/core/deployment/resource-tagging.d.ts.map +1 -0
- package/dist/core/deployment/resource-tagging.js +292 -0
- package/dist/core/deployment/resource-tagging.js.map +1 -0
- package/dist/core/deployment/rollback-manager.d.ts +25 -4
- package/dist/core/deployment/rollback-manager.d.ts.map +1 -1
- package/dist/core/deployment/rollback-manager.js +70 -57
- package/dist/core/deployment/rollback-manager.js.map +1 -1
- package/dist/core/deployment/shared-utilities.d.ts +6 -0
- package/dist/core/deployment/shared-utilities.d.ts.map +1 -1
- package/dist/core/deployment/shared-utilities.js +32 -2
- package/dist/core/deployment/shared-utilities.js.map +1 -1
- package/dist/core/deployment/singleton-owner-drift.d.ts +16 -0
- package/dist/core/deployment/singleton-owner-drift.d.ts.map +1 -0
- package/dist/core/deployment/singleton-owner-drift.js +54 -0
- package/dist/core/deployment/singleton-owner-drift.js.map +1 -0
- package/dist/core/deployment/strategies/alchemy-strategy.d.ts +3 -1
- package/dist/core/deployment/strategies/alchemy-strategy.d.ts.map +1 -1
- package/dist/core/deployment/strategies/alchemy-strategy.js +121 -18
- package/dist/core/deployment/strategies/alchemy-strategy.js.map +1 -1
- package/dist/core/deployment/strategies/base-strategy.d.ts +9 -3
- package/dist/core/deployment/strategies/base-strategy.d.ts.map +1 -1
- package/dist/core/deployment/strategies/base-strategy.js +32 -4
- package/dist/core/deployment/strategies/base-strategy.js.map +1 -1
- package/dist/core/deployment/strategies/direct-strategy.d.ts +12 -4
- package/dist/core/deployment/strategies/direct-strategy.d.ts.map +1 -1
- package/dist/core/deployment/strategies/direct-strategy.js +112 -8
- package/dist/core/deployment/strategies/direct-strategy.js.map +1 -1
- package/dist/core/errors.d.ts +2 -2
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js.map +1 -1
- package/dist/core/expressions/analysis/cache.d.ts +2 -2
- package/dist/core/expressions/analysis/cache.d.ts.map +1 -1
- package/dist/core/expressions/analysis/cache.js +4 -0
- package/dist/core/expressions/analysis/cache.js.map +1 -1
- package/dist/core/expressions/analysis/fn-toString-self-test.d.ts.map +1 -1
- package/dist/core/expressions/analysis/fn-toString-self-test.js +0 -1
- package/dist/core/expressions/analysis/fn-toString-self-test.js.map +1 -1
- package/dist/core/expressions/analysis/shared-types.d.ts +2 -2
- package/dist/core/expressions/analysis/shared-types.d.ts.map +1 -1
- package/dist/core/expressions/analysis/source-map.d.ts.map +1 -1
- package/dist/core/expressions/analysis/source-map.js +1 -0
- package/dist/core/expressions/analysis/source-map.js.map +1 -1
- package/dist/core/expressions/analysis/types.d.ts +7 -7
- package/dist/core/expressions/analysis/types.d.ts.map +1 -1
- package/dist/core/expressions/composition/composition-analyzer-helpers.d.ts +29 -1
- package/dist/core/expressions/composition/composition-analyzer-helpers.d.ts.map +1 -1
- package/dist/core/expressions/composition/composition-analyzer-helpers.js +348 -17
- package/dist/core/expressions/composition/composition-analyzer-helpers.js.map +1 -1
- package/dist/core/expressions/composition/composition-analyzer-ternary.d.ts +2 -2
- package/dist/core/expressions/composition/composition-analyzer-ternary.d.ts.map +1 -1
- package/dist/core/expressions/composition/composition-analyzer-ternary.js +221 -10
- package/dist/core/expressions/composition/composition-analyzer-ternary.js.map +1 -1
- package/dist/core/expressions/composition/composition-analyzer-traversal.d.ts.map +1 -1
- package/dist/core/expressions/composition/composition-analyzer-traversal.js +67 -2
- package/dist/core/expressions/composition/composition-analyzer-traversal.js.map +1 -1
- package/dist/core/expressions/composition/composition-analyzer-types.d.ts +52 -0
- package/dist/core/expressions/composition/composition-analyzer-types.d.ts.map +1 -1
- package/dist/core/expressions/composition/composition-analyzer.d.ts.map +1 -1
- package/dist/core/expressions/composition/composition-analyzer.js +150 -6
- package/dist/core/expressions/composition/composition-analyzer.js.map +1 -1
- package/dist/core/expressions/composition/expression-analyzer.d.ts.map +1 -1
- package/dist/core/expressions/composition/expression-analyzer.js +21 -4
- package/dist/core/expressions/composition/expression-analyzer.js.map +1 -1
- package/dist/core/expressions/composition/imperative-analyzer.d.ts +1 -1
- package/dist/core/expressions/composition/imperative-analyzer.d.ts.map +1 -1
- package/dist/core/expressions/composition/imperative-analyzer.js +31 -7
- package/dist/core/expressions/composition/imperative-analyzer.js.map +1 -1
- package/dist/core/expressions/composition/scope-manager.d.ts +2 -2
- package/dist/core/expressions/composition/scope-manager.d.ts.map +1 -1
- package/dist/core/expressions/composition/scope-manager.js.map +1 -1
- package/dist/core/expressions/conditional/conditional-expression-processor.d.ts +3 -3
- package/dist/core/expressions/conditional/conditional-expression-processor.d.ts.map +1 -1
- package/dist/core/expressions/conditional/conditional-expression-processor.js.map +1 -1
- package/dist/core/expressions/conditional/conditional-integration.d.ts.map +1 -1
- package/dist/core/expressions/conditional/conditional-integration.js.map +1 -1
- package/dist/core/expressions/context/context-aware-generator.d.ts +5 -5
- package/dist/core/expressions/context/context-aware-generator.d.ts.map +1 -1
- package/dist/core/expressions/context/context-aware-generator.js.map +1 -1
- package/dist/core/expressions/context/context-detector.d.ts +3 -3
- package/dist/core/expressions/context/context-detector.d.ts.map +1 -1
- package/dist/core/expressions/context/context-detector.js.map +1 -1
- package/dist/core/expressions/context/context-validator.d.ts +6 -6
- package/dist/core/expressions/context/context-validator.d.ts.map +1 -1
- package/dist/core/expressions/context/context-validator.js +2 -2
- package/dist/core/expressions/context/context-validator.js.map +1 -1
- package/dist/core/expressions/factory/cel-conversion-engine.d.ts +4 -4
- package/dist/core/expressions/factory/cel-conversion-engine.d.ts.map +1 -1
- package/dist/core/expressions/factory/cel-conversion-engine.js.map +1 -1
- package/dist/core/expressions/factory/dependency-tracker.d.ts +2 -2
- package/dist/core/expressions/factory/dependency-tracker.d.ts.map +1 -1
- package/dist/core/expressions/factory/dependency-tracker.js +21 -5
- package/dist/core/expressions/factory/dependency-tracker.js.map +1 -1
- package/dist/core/expressions/factory/factory-integration.d.ts +2 -4
- package/dist/core/expressions/factory/factory-integration.d.ts.map +1 -1
- package/dist/core/expressions/factory/factory-integration.js +0 -6
- package/dist/core/expressions/factory/factory-integration.js.map +1 -1
- package/dist/core/expressions/factory/factory-pattern-handler.d.ts +3 -3
- package/dist/core/expressions/factory/factory-pattern-handler.d.ts.map +1 -1
- package/dist/core/expressions/factory/factory-pattern-handler.js +1 -0
- package/dist/core/expressions/factory/factory-pattern-handler.js.map +1 -1
- package/dist/core/expressions/factory/migration-helpers.js.map +1 -1
- package/dist/core/expressions/factory/resource-analyzer.d.ts +4 -4
- package/dist/core/expressions/factory/resource-analyzer.d.ts.map +1 -1
- package/dist/core/expressions/factory/resource-analyzer.js.map +1 -1
- package/dist/core/expressions/factory/resource-type-validator.d.ts +5 -5
- package/dist/core/expressions/factory/resource-type-validator.d.ts.map +1 -1
- package/dist/core/expressions/factory/resource-type-validator.js.map +1 -1
- package/dist/core/expressions/factory/status-builder-analyzer.d.ts +6 -7
- package/dist/core/expressions/factory/status-builder-analyzer.d.ts.map +1 -1
- package/dist/core/expressions/factory/status-builder-analyzer.js +0 -3
- package/dist/core/expressions/factory/status-builder-analyzer.js.map +1 -1
- package/dist/core/expressions/factory/status-builder-types.d.ts +1 -1
- package/dist/core/expressions/factory/status-builder-types.d.ts.map +1 -1
- package/dist/core/expressions/factory/status-cel-generation.d.ts +1 -1
- package/dist/core/expressions/factory/status-cel-generation.d.ts.map +1 -1
- package/dist/core/expressions/factory/status-cel-generation.js +1 -1
- package/dist/core/expressions/factory/status-cel-generation.js.map +1 -1
- package/dist/core/expressions/factory/status-field-analysis.d.ts +3 -3
- package/dist/core/expressions/factory/status-field-analysis.d.ts.map +1 -1
- package/dist/core/expressions/factory/status-field-analysis.js.map +1 -1
- package/dist/core/expressions/magic-proxy/magic-assignable-analyzer.d.ts +5 -5
- package/dist/core/expressions/magic-proxy/magic-assignable-analyzer.d.ts.map +1 -1
- package/dist/core/expressions/magic-proxy/magic-assignable-analyzer.js +1 -1
- package/dist/core/expressions/magic-proxy/magic-assignable-analyzer.js.map +1 -1
- package/dist/core/expressions/magic-proxy/magic-proxy-analyzer.d.ts +10 -10
- package/dist/core/expressions/magic-proxy/magic-proxy-analyzer.d.ts.map +1 -1
- package/dist/core/expressions/magic-proxy/magic-proxy-analyzer.js +5 -1
- package/dist/core/expressions/magic-proxy/magic-proxy-analyzer.js.map +1 -1
- package/dist/core/expressions/magic-proxy/magic-proxy-ast.d.ts +2 -2
- package/dist/core/expressions/magic-proxy/magic-proxy-ast.d.ts.map +1 -1
- package/dist/core/expressions/magic-proxy/magic-proxy-ast.js.map +1 -1
- package/dist/core/expressions/magic-proxy/magic-proxy-detector.d.ts +5 -5
- package/dist/core/expressions/magic-proxy/magic-proxy-detector.d.ts.map +1 -1
- package/dist/core/expressions/magic-proxy/magic-proxy-detector.js.map +1 -1
- package/dist/core/expressions/magic-proxy/magic-proxy-types.d.ts +2 -2
- package/dist/core/expressions/magic-proxy/magic-proxy-types.d.ts.map +1 -1
- package/dist/core/expressions/magic-proxy/optionality-handler.d.ts +1 -2
- package/dist/core/expressions/magic-proxy/optionality-handler.d.ts.map +1 -1
- package/dist/core/expressions/magic-proxy/optionality-handler.js +2 -15
- package/dist/core/expressions/magic-proxy/optionality-handler.js.map +1 -1
- package/dist/core/expressions/validation/compile-time-checker.d.ts +1 -1
- package/dist/core/expressions/validation/compile-time-checker.d.ts.map +1 -1
- package/dist/core/expressions/validation/compile-time-checker.js.map +1 -1
- package/dist/core/expressions/validation/compile-time-types.d.ts +2 -2
- package/dist/core/expressions/validation/compile-time-types.d.ts.map +1 -1
- package/dist/core/expressions/validation/kubernetes-field-types.d.ts +4 -4
- package/dist/core/expressions/validation/kubernetes-field-types.d.ts.map +1 -1
- package/dist/core/expressions/validation/kubernetes-field-types.js.map +1 -1
- package/dist/core/expressions/validation/resource-field-utils.d.ts +10 -10
- package/dist/core/expressions/validation/resource-field-utils.d.ts.map +1 -1
- package/dist/core/expressions/validation/resource-field-utils.js.map +1 -1
- package/dist/core/expressions/validation/resource-validation.d.ts +3 -3
- package/dist/core/expressions/validation/resource-validation.d.ts.map +1 -1
- package/dist/core/expressions/validation/resource-validation.js.map +1 -1
- package/dist/core/expressions/validation/type-inference-types.d.ts +2 -2
- package/dist/core/expressions/validation/type-inference-types.d.ts.map +1 -1
- package/dist/core/expressions/validation/type-safety.d.ts +2 -2
- package/dist/core/expressions/validation/type-safety.d.ts.map +1 -1
- package/dist/core/expressions/validation/type-safety.js +1 -0
- package/dist/core/expressions/validation/type-safety.js.map +1 -1
- package/dist/core/kubernetes/bun-api-client.js.map +1 -1
- package/dist/core/kubernetes/bun-http-library.d.ts.map +1 -1
- package/dist/core/kubernetes/bun-http-library.js +29 -3
- package/dist/core/kubernetes/bun-http-library.js.map +1 -1
- package/dist/core/kubernetes/client-provider.d.ts +12 -0
- package/dist/core/kubernetes/client-provider.d.ts.map +1 -1
- package/dist/core/kubernetes/client-provider.js +35 -0
- package/dist/core/kubernetes/client-provider.js.map +1 -1
- package/dist/core/metadata/resource-metadata.d.ts +49 -1
- package/dist/core/metadata/resource-metadata.d.ts.map +1 -1
- package/dist/core/metadata/resource-metadata.js.map +1 -1
- package/dist/core/proxy/create-resource.d.ts +15 -0
- package/dist/core/proxy/create-resource.d.ts.map +1 -1
- package/dist/core/proxy/create-resource.js +79 -2
- package/dist/core/proxy/create-resource.js.map +1 -1
- package/dist/core/readiness/registry.js +2 -2
- package/dist/core/readiness/registry.js.map +1 -1
- package/dist/core/references/cel-evaluator.d.ts +1 -4
- package/dist/core/references/cel-evaluator.d.ts.map +1 -1
- package/dist/core/references/cel-evaluator.js +3 -7
- package/dist/core/references/cel-evaluator.js.map +1 -1
- package/dist/core/references/cel.d.ts +22 -0
- package/dist/core/references/cel.d.ts.map +1 -1
- package/dist/core/references/cel.js +106 -8
- package/dist/core/references/cel.js.map +1 -1
- package/dist/core/references/external-refs.d.ts.map +1 -1
- package/dist/core/references/external-refs.js +3 -0
- package/dist/core/references/external-refs.js.map +1 -1
- package/dist/core/references/resolver.d.ts.map +1 -1
- package/dist/core/references/resolver.js +28 -17
- package/dist/core/references/resolver.js.map +1 -1
- package/dist/core/references/schema-proxy.d.ts +18 -10
- package/dist/core/references/schema-proxy.d.ts.map +1 -1
- package/dist/core/references/schema-proxy.js +174 -23
- package/dist/core/references/schema-proxy.js.map +1 -1
- package/dist/core/runtime-patches/crd-schema-fix.d.ts.map +1 -1
- package/dist/core/runtime-patches/crd-schema-fix.js +4 -1
- package/dist/core/runtime-patches/crd-schema-fix.js.map +1 -1
- package/dist/core/serialization/cel-optimizer.d.ts.map +1 -1
- package/dist/core/serialization/cel-optimizer.js +2 -0
- package/dist/core/serialization/cel-optimizer.js.map +1 -1
- package/dist/core/serialization/cel-references.d.ts +75 -1
- package/dist/core/serialization/cel-references.d.ts.map +1 -1
- package/dist/core/serialization/cel-references.js +692 -156
- package/dist/core/serialization/cel-references.js.map +1 -1
- package/dist/core/serialization/core.d.ts +8 -8
- package/dist/core/serialization/core.d.ts.map +1 -1
- package/dist/core/serialization/core.js +672 -90
- package/dist/core/serialization/core.js.map +1 -1
- package/dist/core/serialization/kro-post-processing.d.ts +1 -1
- package/dist/core/serialization/kro-post-processing.d.ts.map +1 -1
- package/dist/core/serialization/kro-post-processing.js +69 -22
- package/dist/core/serialization/kro-post-processing.js.map +1 -1
- package/dist/core/serialization/schema.d.ts +1 -0
- package/dist/core/serialization/schema.d.ts.map +1 -1
- package/dist/core/serialization/schema.js +378 -50
- package/dist/core/serialization/schema.js.map +1 -1
- package/dist/core/serialization/status-analysis-pipeline.d.ts +1 -1
- package/dist/core/serialization/status-analysis-pipeline.d.ts.map +1 -1
- package/dist/core/serialization/status-analysis-pipeline.js.map +1 -1
- package/dist/core/serialization/yaml.d.ts +3 -2
- package/dist/core/serialization/yaml.d.ts.map +1 -1
- package/dist/core/serialization/yaml.js +385 -55
- package/dist/core/serialization/yaml.js.map +1 -1
- package/dist/core/singleton/singleton.d.ts +16 -0
- package/dist/core/singleton/singleton.d.ts.map +1 -0
- package/dist/core/singleton/singleton.js +135 -0
- package/dist/core/singleton/singleton.js.map +1 -0
- package/dist/core/types/common.d.ts +2 -2
- package/dist/core/types/common.d.ts.map +1 -1
- package/dist/core/types/composable.d.ts +1 -1
- package/dist/core/types/composable.d.ts.map +1 -1
- package/dist/core/types/deployment.d.ts +129 -9
- package/dist/core/types/deployment.d.ts.map +1 -1
- package/dist/core/types/deployment.js +1 -1
- package/dist/core/types/deployment.js.map +1 -1
- package/dist/core/types/kubernetes.d.ts +25 -17
- package/dist/core/types/kubernetes.d.ts.map +1 -1
- package/dist/core/types/references.d.ts +1 -1
- package/dist/core/types/references.d.ts.map +1 -1
- package/dist/core/types/references.js.map +1 -1
- package/dist/core/types/resource-graph.d.ts +2 -1
- package/dist/core/types/resource-graph.d.ts.map +1 -1
- package/dist/core/types/schema.d.ts +1 -1
- package/dist/core/types/schema.d.ts.map +1 -1
- package/dist/core/types/serialization.d.ts +24 -6
- package/dist/core/types/serialization.d.ts.map +1 -1
- package/dist/core/validation/cel-validator.d.ts +15 -2
- package/dist/core/validation/cel-validator.d.ts.map +1 -1
- package/dist/core/validation/cel-validator.js +144 -63
- package/dist/core/validation/cel-validator.js.map +1 -1
- package/dist/factories/apisix/compositions/apisix-bootstrap.d.ts +2 -41
- package/dist/factories/apisix/compositions/apisix-bootstrap.d.ts.map +1 -1
- package/dist/factories/apisix/compositions/apisix-bootstrap.js +262 -217
- package/dist/factories/apisix/compositions/apisix-bootstrap.js.map +1 -1
- package/dist/factories/apisix/index.d.ts +2 -2
- package/dist/factories/apisix/index.js +2 -2
- package/dist/factories/apisix/resources/helm.d.ts +2 -2
- package/dist/factories/apisix/resources/helm.d.ts.map +1 -1
- package/dist/factories/apisix/resources/helm.js.map +1 -1
- package/dist/factories/apisix/types.d.ts +21 -11
- package/dist/factories/apisix/types.d.ts.map +1 -1
- package/dist/factories/apisix/types.js +106 -4
- package/dist/factories/apisix/types.js.map +1 -1
- package/dist/factories/apisix/utils/admin-credentials.d.ts +5 -3
- package/dist/factories/apisix/utils/admin-credentials.d.ts.map +1 -1
- package/dist/factories/apisix/utils/admin-credentials.js +14 -10
- package/dist/factories/apisix/utils/admin-credentials.js.map +1 -1
- package/dist/factories/apisix/utils/helm-values-mapper.d.ts.map +1 -1
- package/dist/factories/apisix/utils/helm-values-mapper.js +4 -2
- package/dist/factories/apisix/utils/helm-values-mapper.js.map +1 -1
- package/dist/factories/cert-manager/resources/challenges.js.map +1 -1
- package/dist/factories/cert-manager/types.d.ts +3 -3
- package/dist/factories/cert-manager/types.d.ts.map +1 -1
- package/dist/factories/cilium/compositions/cilium-bootstrap.d.ts +4 -4
- package/dist/factories/cilium/types.d.ts +3 -3
- package/dist/factories/cilium/types.d.ts.map +1 -1
- package/dist/factories/cnpg/compositions/cnpg-bootstrap.d.ts +1 -0
- package/dist/factories/cnpg/compositions/cnpg-bootstrap.d.ts.map +1 -1
- package/dist/factories/cnpg/compositions/cnpg-bootstrap.js +48 -0
- package/dist/factories/cnpg/compositions/cnpg-bootstrap.js.map +1 -1
- package/dist/factories/cnpg/resources/cluster.js +1 -1
- package/dist/factories/cnpg/resources/cluster.js.map +1 -1
- package/dist/factories/cnpg/resources/helm.d.ts.map +1 -1
- package/dist/factories/cnpg/resources/helm.js +1 -0
- package/dist/factories/cnpg/resources/helm.js.map +1 -1
- package/dist/factories/cnpg/resources/pooler.js +1 -1
- package/dist/factories/cnpg/resources/pooler.js.map +1 -1
- package/dist/factories/cnpg/types.d.ts +9 -8
- package/dist/factories/cnpg/types.d.ts.map +1 -1
- package/dist/factories/cnpg/types.js +11 -0
- package/dist/factories/cnpg/types.js.map +1 -1
- package/dist/factories/external-dns/compositions/external-dns-bootstrap.d.ts.map +1 -1
- package/dist/factories/external-dns/compositions/external-dns-bootstrap.js +153 -41
- package/dist/factories/external-dns/compositions/external-dns-bootstrap.js.map +1 -1
- package/dist/factories/external-dns/resources/dns-endpoint.js +1 -1
- package/dist/factories/external-dns/resources/dns-endpoint.js.map +1 -1
- package/dist/factories/external-dns/resources/helm.d.ts +1 -1
- package/dist/factories/external-dns/resources/helm.d.ts.map +1 -1
- package/dist/factories/external-dns/resources/helm.js +17 -10
- package/dist/factories/external-dns/resources/helm.js.map +1 -1
- package/dist/factories/external-dns/types.d.ts +5 -2
- package/dist/factories/external-dns/types.d.ts.map +1 -1
- package/dist/factories/external-dns/types.js.map +1 -1
- package/dist/factories/flux/git-repository.d.ts.map +1 -1
- package/dist/factories/flux/git-repository.js +1 -1
- package/dist/factories/flux/git-repository.js.map +1 -1
- package/dist/factories/flux/kustomize/kustomization.d.ts +2 -2
- package/dist/factories/flux/kustomize/kustomization.d.ts.map +1 -1
- package/dist/factories/flux/kustomize/readiness-evaluators.d.ts +1 -1
- package/dist/factories/flux/kustomize/readiness-evaluators.d.ts.map +1 -1
- package/dist/factories/flux/kustomize/readiness-evaluators.js +1 -1
- package/dist/factories/flux/kustomize/readiness-evaluators.js.map +1 -1
- package/dist/factories/helm/helm-release.d.ts +3 -2
- package/dist/factories/helm/helm-release.d.ts.map +1 -1
- package/dist/factories/helm/helm-release.js +1 -0
- package/dist/factories/helm/helm-release.js.map +1 -1
- package/dist/factories/helm/helm-repository.d.ts +1 -1
- package/dist/factories/helm/helm-repository.d.ts.map +1 -1
- package/dist/factories/helm/helm-repository.js +6 -4
- package/dist/factories/helm/helm-repository.js.map +1 -1
- package/dist/factories/helm/readiness-evaluators.d.ts +6 -6
- package/dist/factories/helm/readiness-evaluators.d.ts.map +1 -1
- package/dist/factories/helm/readiness-evaluators.js +15 -9
- package/dist/factories/helm/readiness-evaluators.js.map +1 -1
- package/dist/factories/helm/types.d.ts +5 -1
- package/dist/factories/helm/types.d.ts.map +1 -1
- package/dist/factories/inngest/compositions/inngest-bootstrap.d.ts +1 -0
- package/dist/factories/inngest/compositions/inngest-bootstrap.d.ts.map +1 -1
- package/dist/factories/inngest/compositions/inngest-bootstrap.js +4 -3
- package/dist/factories/inngest/compositions/inngest-bootstrap.js.map +1 -1
- package/dist/factories/inngest/resources/helm.js +1 -1
- package/dist/factories/inngest/resources/helm.js.map +1 -1
- package/dist/factories/inngest/types.d.ts +5 -4
- package/dist/factories/inngest/types.d.ts.map +1 -1
- package/dist/factories/inngest/types.js +2 -0
- package/dist/factories/inngest/types.js.map +1 -1
- package/dist/factories/kro/kro-custom-resource.js +1 -1
- package/dist/factories/kro/kro-custom-resource.js.map +1 -1
- package/dist/factories/kubernetes/config/config-map.d.ts +2 -2
- package/dist/factories/kubernetes/config/config-map.d.ts.map +1 -1
- package/dist/factories/kubernetes/config/secret.d.ts +2 -2
- package/dist/factories/kubernetes/config/secret.d.ts.map +1 -1
- package/dist/factories/kubernetes/networking/service.js +1 -1
- package/dist/factories/kubernetes/networking/service.js.map +1 -1
- package/dist/factories/kubernetes/yaml/yaml-directory.d.ts.map +1 -1
- package/dist/factories/kubernetes/yaml/yaml-directory.js +9 -0
- package/dist/factories/kubernetes/yaml/yaml-directory.js.map +1 -1
- package/dist/factories/kubernetes/yaml/yaml-file.d.ts.map +1 -1
- package/dist/factories/kubernetes/yaml/yaml-file.js +9 -0
- package/dist/factories/kubernetes/yaml/yaml-file.js.map +1 -1
- package/dist/factories/pebble/resources/helm.js.map +1 -1
- package/dist/factories/pebble/types.d.ts +2 -2
- package/dist/factories/searxng/compositions/searxng-bootstrap.d.ts +3 -2
- package/dist/factories/searxng/compositions/searxng-bootstrap.d.ts.map +1 -1
- package/dist/factories/searxng/compositions/searxng-bootstrap.js +205 -167
- package/dist/factories/searxng/compositions/searxng-bootstrap.js.map +1 -1
- package/dist/factories/searxng/resources/searxng.d.ts +1 -1
- package/dist/factories/searxng/resources/searxng.js +1 -1
- package/dist/factories/searxng/types.d.ts +5 -4
- package/dist/factories/searxng/types.d.ts.map +1 -1
- package/dist/factories/searxng/types.js +8 -7
- package/dist/factories/searxng/types.js.map +1 -1
- package/dist/factories/searxng/utils/settings-builder.d.ts +4 -3
- package/dist/factories/searxng/utils/settings-builder.d.ts.map +1 -1
- package/dist/factories/searxng/utils/settings-builder.js +4 -3
- package/dist/factories/searxng/utils/settings-builder.js.map +1 -1
- package/dist/factories/simple/config/config-map.d.ts +2 -2
- package/dist/factories/simple/config/config-map.d.ts.map +1 -1
- package/dist/factories/simple/config/secret.d.ts +2 -2
- package/dist/factories/simple/config/secret.d.ts.map +1 -1
- package/dist/factories/simple/helm/index.d.ts +1 -1
- package/dist/factories/simple/helm/index.d.ts.map +1 -1
- package/dist/factories/simple/helm/index.js.map +1 -1
- package/dist/factories/simple/index.d.ts +3 -3
- package/dist/factories/simple/index.d.ts.map +1 -1
- package/dist/factories/simple/storage/persistent-volume.js.map +1 -1
- package/dist/factories/simple/types.d.ts +11 -1
- package/dist/factories/simple/types.d.ts.map +1 -1
- package/dist/factories/simple/workloads/deployment.d.ts +4 -1
- package/dist/factories/simple/workloads/deployment.d.ts.map +1 -1
- package/dist/factories/simple/workloads/deployment.js +9 -2
- package/dist/factories/simple/workloads/deployment.js.map +1 -1
- package/dist/factories/simple/workloads/stateful-set.d.ts +4 -1
- package/dist/factories/simple/workloads/stateful-set.d.ts.map +1 -1
- package/dist/factories/simple/workloads/stateful-set.js +6 -2
- package/dist/factories/simple/workloads/stateful-set.js.map +1 -1
- package/dist/factories/valkey/compositions/valkey-bootstrap.d.ts +1 -0
- package/dist/factories/valkey/compositions/valkey-bootstrap.d.ts.map +1 -1
- package/dist/factories/valkey/compositions/valkey-bootstrap.js +116 -0
- package/dist/factories/valkey/compositions/valkey-bootstrap.js.map +1 -1
- package/dist/factories/valkey/resources/valkey.js +1 -1
- package/dist/factories/valkey/resources/valkey.js.map +1 -1
- package/dist/factories/valkey/types.d.ts +6 -5
- package/dist/factories/valkey/types.d.ts.map +1 -1
- package/dist/factories/valkey/types.js +10 -0
- package/dist/factories/valkey/types.js.map +1 -1
- package/dist/factories/webapp/compositions/web-app-with-processing.d.ts +90 -6
- package/dist/factories/webapp/compositions/web-app-with-processing.d.ts.map +1 -1
- package/dist/factories/webapp/compositions/web-app-with-processing.js +180 -20
- package/dist/factories/webapp/compositions/web-app-with-processing.js.map +1 -1
- package/dist/factories/webapp/index.d.ts +3 -4
- package/dist/factories/webapp/index.d.ts.map +1 -1
- package/dist/factories/webapp/index.js +3 -4
- package/dist/factories/webapp/index.js.map +1 -1
- package/dist/factories/webapp/types.d.ts +60 -2
- package/dist/factories/webapp/types.d.ts.map +1 -1
- package/dist/factories/webapp/types.js +80 -3
- package/dist/factories/webapp/types.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/shared/brands.d.ts +18 -8
- package/dist/shared/brands.d.ts.map +1 -1
- package/dist/shared/brands.js +19 -9
- package/dist/shared/brands.js.map +1 -1
- package/dist/utils/cel-escape.d.ts +12 -0
- package/dist/utils/cel-escape.d.ts.map +1 -0
- package/dist/utils/cel-escape.js +19 -0
- package/dist/utils/cel-escape.js.map +1 -0
- package/package.json +7 -2
|
@@ -7,18 +7,24 @@
|
|
|
7
7
|
import * as yaml from 'js-yaml';
|
|
8
8
|
import { toCamelCase } from '../../utils/string.js';
|
|
9
9
|
import { isCelExpression, isKubernetesRef } from '../../utils/type-guards.js';
|
|
10
|
+
import { applyAspects } from '../aspects/apply.js';
|
|
10
11
|
import { createCompositionContext, runWithCompositionContext } from '../composition/context.js';
|
|
12
|
+
import { buildNestedCompositionAliasTargets } from '../composition/nested-status-cel.js';
|
|
11
13
|
import { DEFAULT_DELETE_TIMEOUT, DEFAULT_FAST_POLL_INTERVAL, DEFAULT_MAX_RECURSION_DEPTH, } from '../config/defaults.js';
|
|
14
|
+
import { KUBERNETES_REF_SCHEMA_MARKER_SOURCE } from '../constants/brands.js';
|
|
12
15
|
import { DependencyResolver } from '../dependencies/index.js';
|
|
13
16
|
import { ensureError, ResourceGraphFactoryError, TypeKroError, ValidationError, } from '../errors.js';
|
|
14
17
|
import { getComponentLogger } from '../logging/index.js';
|
|
15
|
-
import { copyResourceMetadata, getResourceId, setResourceId } from '../metadata/index.js';
|
|
18
|
+
import { copyResourceMetadata, getMetadataField, getResourceId, setResourceId, } from '../metadata/index.js';
|
|
19
|
+
import { getSingletonResourceId } from '../singleton/singleton.js';
|
|
16
20
|
import { KubernetesClientManager } from './client-provider-manager.js';
|
|
21
|
+
import { BUILT_IN_GVKS } from './deployment-state-discovery.js';
|
|
17
22
|
import { DirectDeploymentEngine } from './engine.js';
|
|
23
|
+
import { logHandleSnapshot } from './handle-tracing.js';
|
|
18
24
|
import { synthesizeNestedCompositionStatus } from './nested-composition-status.js';
|
|
19
25
|
import { ResourceReadinessChecker } from './readiness.js';
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
26
|
+
import { generateInstanceName, getSingletonInstanceName, validateSpec, } from './shared-utilities.js';
|
|
27
|
+
import { assertNoDeployedSingletonSpecDrift, assertNoDiscoveredSingletonSpecDrift, singletonSpecFingerprintAnnotationValue, } from './singleton-owner-drift.js';
|
|
22
28
|
import { AlchemyDeploymentStrategy, DirectDeploymentStrategy } from './strategies/index.js';
|
|
23
29
|
/**
|
|
24
30
|
* DirectResourceFactory implementation
|
|
@@ -34,14 +40,19 @@ export class DirectResourceFactoryImpl {
|
|
|
34
40
|
resources;
|
|
35
41
|
closures;
|
|
36
42
|
schemaDefinition;
|
|
43
|
+
// biome-ignore lint/suspicious/noExplicitAny: status builders accept composition-specific resource maps that cannot be expressed more tightly here.
|
|
37
44
|
statusBuilder;
|
|
38
45
|
deploymentEngine;
|
|
39
46
|
alchemyScope;
|
|
40
47
|
factoryOptions;
|
|
48
|
+
singletonDefinitions;
|
|
49
|
+
singletonOwnerStatuses = new Map();
|
|
41
50
|
deployedInstances = new Map();
|
|
42
51
|
logger = getComponentLogger('direct-factory');
|
|
43
52
|
clientManager;
|
|
44
|
-
constructor(name, resources, schemaDefinition,
|
|
53
|
+
constructor(name, resources, schemaDefinition,
|
|
54
|
+
// biome-ignore lint/suspicious/noExplicitAny: constructor must preserve the generic status-builder resource map contract.
|
|
55
|
+
statusBuilder, options = {}) {
|
|
45
56
|
this.name = name;
|
|
46
57
|
this.namespace = options.namespace || 'default';
|
|
47
58
|
this.alchemyScope = options.alchemyScope;
|
|
@@ -51,6 +62,7 @@ export class DirectResourceFactoryImpl {
|
|
|
51
62
|
this.schemaDefinition = schemaDefinition;
|
|
52
63
|
this.statusBuilder = statusBuilder;
|
|
53
64
|
this.factoryOptions = options;
|
|
65
|
+
this.singletonDefinitions = options.singletonDefinitions ?? [];
|
|
54
66
|
this.clientManager = new KubernetesClientManager(options);
|
|
55
67
|
}
|
|
56
68
|
/**
|
|
@@ -59,6 +71,29 @@ export class DirectResourceFactoryImpl {
|
|
|
59
71
|
getClientProvider() {
|
|
60
72
|
return this.clientManager.getClientProvider();
|
|
61
73
|
}
|
|
74
|
+
getDebugState() {
|
|
75
|
+
return {
|
|
76
|
+
mode: this.mode,
|
|
77
|
+
namespace: this.namespace,
|
|
78
|
+
deployedInstances: this.deployedInstances.size,
|
|
79
|
+
hasDeploymentEngine: !!this.deploymentEngine,
|
|
80
|
+
clientManager: this.clientManager.getDebugState(),
|
|
81
|
+
deploymentEngine: this.deploymentEngine?.getDebugState(),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
async dispose() {
|
|
85
|
+
logHandleSnapshot(this.logger, 'direct-factory.dispose.before', {
|
|
86
|
+
factoryState: this.getDebugState(),
|
|
87
|
+
});
|
|
88
|
+
if (this.deploymentEngine) {
|
|
89
|
+
await this.deploymentEngine.dispose();
|
|
90
|
+
this.deploymentEngine = undefined;
|
|
91
|
+
}
|
|
92
|
+
this.clientManager.dispose();
|
|
93
|
+
logHandleSnapshot(this.logger, 'direct-factory.dispose.after', {
|
|
94
|
+
factoryState: this.getDebugState(),
|
|
95
|
+
});
|
|
96
|
+
}
|
|
62
97
|
/**
|
|
63
98
|
* Get or create the deployment engine using the centralized client provider
|
|
64
99
|
*/
|
|
@@ -81,17 +116,22 @@ export class DirectResourceFactoryImpl {
|
|
|
81
116
|
/**
|
|
82
117
|
* Deploy a new instance with the given spec
|
|
83
118
|
*/
|
|
84
|
-
async deploy(spec) {
|
|
119
|
+
async deploy(spec, opts) {
|
|
85
120
|
this.logger.debug('DirectResourceFactory deploy called', {
|
|
86
121
|
factoryName: this.name,
|
|
87
122
|
hasStatusBuilder: !!this.statusBuilder,
|
|
88
123
|
});
|
|
124
|
+
validateSpec(spec, this.schemaDefinition, {
|
|
125
|
+
kind: this.schemaDefinition.kind,
|
|
126
|
+
name: this.name,
|
|
127
|
+
});
|
|
89
128
|
// Use the consolidated deployment strategy
|
|
90
129
|
const strategy = this.getDeploymentStrategy();
|
|
91
130
|
this.logger.debug('Got deployment strategy', {
|
|
92
131
|
strategyType: strategy.constructor.name,
|
|
93
132
|
});
|
|
94
|
-
|
|
133
|
+
await this.ensureSingletonOwners(spec);
|
|
134
|
+
const instance = await strategy.deploy(spec, opts);
|
|
95
135
|
// Check if deployment failed and throw for user-facing error handling
|
|
96
136
|
if (instance.metadata?.annotations?.['typekro.io/deployment-status'] === 'failed') {
|
|
97
137
|
const errorMessage = instance.metadata?.annotations?.['typekro.io/deployment-error'] ||
|
|
@@ -99,7 +139,7 @@ export class DirectResourceFactoryImpl {
|
|
|
99
139
|
throw new ResourceGraphFactoryError(errorMessage, this.name, 'deployment');
|
|
100
140
|
}
|
|
101
141
|
// Track the deployed instance
|
|
102
|
-
const instanceName = this.generateInstanceName(spec);
|
|
142
|
+
const instanceName = opts?.instanceNameOverride ?? this.generateInstanceName(spec);
|
|
103
143
|
this.deployedInstances.set(instanceName, instance);
|
|
104
144
|
return instance;
|
|
105
145
|
}
|
|
@@ -118,35 +158,58 @@ export class DirectResourceFactoryImpl {
|
|
|
118
158
|
}
|
|
119
159
|
/**
|
|
120
160
|
* Get all deployed instances
|
|
161
|
+
*
|
|
162
|
+
* Direct mode currently reports same-process instances only. Cross-process
|
|
163
|
+
* discovery is implemented for `deleteInstance(name)`, but reconstructing
|
|
164
|
+
* fully typed Enhanced instances from live tagged resources is intentionally
|
|
165
|
+
* not attempted here.
|
|
121
166
|
*/
|
|
122
167
|
async getInstances() {
|
|
123
168
|
return Array.from(this.deployedInstances.values());
|
|
124
169
|
}
|
|
125
170
|
/**
|
|
126
|
-
* Delete a specific instance by name
|
|
171
|
+
* Delete a specific instance by name.
|
|
172
|
+
*
|
|
173
|
+
* Lookup order:
|
|
174
|
+
* 1. In-memory `deployedInstances` Map (same-process path) — uses
|
|
175
|
+
* the deployment-id annotation on the Enhanced instance proxy.
|
|
176
|
+
* 2. Cluster-side label discovery (cross-process path) — queries
|
|
177
|
+
* for all resources labeled `typekro.io/factory-name=<factory>,
|
|
178
|
+
* typekro.io/instance-name=<instance>`, reconstructs the
|
|
179
|
+
* dependency graph from per-resource `typekro.io/depends-on`
|
|
180
|
+
* annotations, and performs reverse-topological deletion.
|
|
181
|
+
*
|
|
182
|
+
* Both paths feed into the same graph-based reverse-topological
|
|
183
|
+
* delete via `engine.rollbackRecord`.
|
|
184
|
+
*
|
|
185
|
+
* **Scope filtering**: By default, unscoped (instance-private)
|
|
186
|
+
* resources are deleted and scoped resources are preserved. Pass
|
|
187
|
+
* `opts.scopes` to include broader-scope resources additively:
|
|
188
|
+
*
|
|
189
|
+
* ```ts
|
|
190
|
+
* await factory.deleteInstance('my-app'); // unscoped only (safe default)
|
|
191
|
+
* await factory.deleteInstance('my-app', { scopes: ['cluster'] }); // unscoped + cluster
|
|
192
|
+
* await factory.deleteInstance('my-app', { scopes: ['cluster'],
|
|
193
|
+
* includeUnscopedResources: false }); // cluster-only (leave app running)
|
|
194
|
+
* ```
|
|
127
195
|
*/
|
|
128
|
-
async deleteInstance(name) {
|
|
129
|
-
const
|
|
130
|
-
if (!instance) {
|
|
131
|
-
throw new TypeKroError(`Instance not found: ${name}`, 'INSTANCE_NOT_FOUND', {
|
|
132
|
-
instanceName: name,
|
|
133
|
-
factoryName: this.name,
|
|
134
|
-
});
|
|
135
|
-
}
|
|
196
|
+
async deleteInstance(name, opts) {
|
|
197
|
+
const engine = this.getDeploymentEngine();
|
|
136
198
|
try {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
199
|
+
const rollbackResult = await this.rollbackInstanceResources(name, opts);
|
|
200
|
+
if (rollbackResult.status !== 'success' || rollbackResult.errors.length > 0) {
|
|
201
|
+
const errorSummary = rollbackResult.errors
|
|
202
|
+
.map((error) => `${error.resourceId}: ${ensureError(error.error).message}`)
|
|
203
|
+
.join('; ');
|
|
204
|
+
throw new Error(`Cleanup incomplete for instance ${name}: rollback ${rollbackResult.status}${errorSummary ? ` (${errorSummary})` : ''}`);
|
|
142
205
|
}
|
|
143
|
-
const rollbackResult = await engine.rollback(deploymentId);
|
|
144
206
|
// Wait for any namespaces to be fully deleted before returning.
|
|
145
207
|
// Namespace deletion is asynchronous (enters "Terminating" phase) and can
|
|
146
208
|
// cause race conditions if the caller immediately re-creates resources.
|
|
147
209
|
const deletedNamespaces = rollbackResult.rolledBackResources
|
|
148
210
|
.filter((r) => r.startsWith('Namespace/'))
|
|
149
|
-
.map((r) => r.split('/')[1])
|
|
211
|
+
.map((r) => r.split('/')[1])
|
|
212
|
+
.filter((namespace) => namespace !== undefined);
|
|
150
213
|
if (deletedNamespaces.length > 0) {
|
|
151
214
|
// Delete PVCs in namespaces before waiting — StatefulSet PVCs have
|
|
152
215
|
// finalizers that block namespace termination until volumes are released.
|
|
@@ -159,19 +222,24 @@ export class DirectResourceFactoryImpl {
|
|
|
159
222
|
const pvcs = await coreApi.listNamespacedPersistentVolumeClaim({ namespace: ns });
|
|
160
223
|
if (pvcs.items.length > 0) {
|
|
161
224
|
this.logger.info('Deleting PVCs to unblock namespace termination', {
|
|
162
|
-
namespace: ns,
|
|
225
|
+
namespace: ns,
|
|
226
|
+
count: pvcs.items.length,
|
|
163
227
|
});
|
|
164
228
|
}
|
|
165
229
|
for (const pvc of pvcs.items) {
|
|
166
230
|
const pvcName = pvc.metadata?.name;
|
|
167
231
|
if (!pvcName)
|
|
168
232
|
continue;
|
|
169
|
-
await coreApi
|
|
233
|
+
await coreApi
|
|
234
|
+
.deleteNamespacedPersistentVolumeClaim({
|
|
170
235
|
name: pvcName,
|
|
171
236
|
namespace: ns,
|
|
172
|
-
})
|
|
237
|
+
})
|
|
238
|
+
.catch((err) => {
|
|
173
239
|
this.logger.info('PVC delete failed', {
|
|
174
|
-
pvc: pvcName,
|
|
240
|
+
pvc: pvcName,
|
|
241
|
+
namespace: ns,
|
|
242
|
+
error: String(err),
|
|
175
243
|
});
|
|
176
244
|
});
|
|
177
245
|
}
|
|
@@ -192,17 +260,81 @@ export class DirectResourceFactoryImpl {
|
|
|
192
260
|
this.deployedInstances.delete(name);
|
|
193
261
|
}
|
|
194
262
|
catch (error) {
|
|
195
|
-
//
|
|
196
|
-
//
|
|
263
|
+
// INSTANCE_NOT_FOUND bubbles up — the caller asked us to delete
|
|
264
|
+
// an instance that has neither in-memory state nor a persisted
|
|
265
|
+
// record. That's a legitimate error (wrong name, already cleaned
|
|
266
|
+
// up) and the caller needs to see it.
|
|
267
|
+
if (error instanceof TypeKroError && error.code === 'INSTANCE_NOT_FOUND') {
|
|
268
|
+
throw error;
|
|
269
|
+
}
|
|
270
|
+
// Soft-swallow "Cannot rollback" errors from the engine —
|
|
271
|
+
// they indicate the engine's in-memory deployment state has
|
|
272
|
+
// already been cleaned up (e.g., by a previous rollback call).
|
|
273
|
+
// The instance is effectively gone, so we remove from tracking.
|
|
197
274
|
const errorMessage = ensureError(error).message;
|
|
198
|
-
if (errorMessage.includes('
|
|
275
|
+
if (errorMessage.includes('Cannot rollback')) {
|
|
199
276
|
this.deployedInstances.delete(name);
|
|
200
|
-
// Don't throw - the instance is already gone
|
|
201
277
|
return;
|
|
202
278
|
}
|
|
203
279
|
throw new ResourceGraphFactoryError(`Failed to delete instance ${name}: ${errorMessage}`, this.name, 'cleanup');
|
|
204
280
|
}
|
|
205
281
|
}
|
|
282
|
+
buildKnownGvks() {
|
|
283
|
+
const crdHints = new Map();
|
|
284
|
+
for (const r of Object.values(this.resources)) {
|
|
285
|
+
if (!r.apiVersion || !r.kind)
|
|
286
|
+
continue;
|
|
287
|
+
const key = `${r.apiVersion}/${r.kind}`;
|
|
288
|
+
if (crdHints.has(key))
|
|
289
|
+
continue;
|
|
290
|
+
const scope = getMetadataField(r, 'scope');
|
|
291
|
+
crdHints.set(key, {
|
|
292
|
+
apiVersion: r.apiVersion,
|
|
293
|
+
kind: r.kind,
|
|
294
|
+
namespaced: scope !== 'cluster',
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
return [...BUILT_IN_GVKS, ...crdHints.values()];
|
|
298
|
+
}
|
|
299
|
+
async rollbackInstanceResources(name, opts) {
|
|
300
|
+
const engine = this.getDeploymentEngine();
|
|
301
|
+
const instance = this.deployedInstances.get(name);
|
|
302
|
+
if (instance) {
|
|
303
|
+
const deploymentId = instance.metadata?.annotations?.['typekro.io/deployment-id'];
|
|
304
|
+
if (deploymentId) {
|
|
305
|
+
try {
|
|
306
|
+
return await engine.rollback(deploymentId, {
|
|
307
|
+
...(opts?.scopes && { scopes: opts.scopes }),
|
|
308
|
+
...(opts?.includeUnscopedResources === false && { includeUnscopedResources: false }),
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
catch (error) {
|
|
312
|
+
const isNotFound = error instanceof ResourceGraphFactoryError && error.operation === 'cleanup';
|
|
313
|
+
if (!isNotFound) {
|
|
314
|
+
throw error;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
const record = await engine.loadDeploymentByInstance({
|
|
320
|
+
factoryName: this.name,
|
|
321
|
+
instanceName: name,
|
|
322
|
+
knownGvks: this.buildKnownGvks(),
|
|
323
|
+
});
|
|
324
|
+
if (!record) {
|
|
325
|
+
throw new TypeKroError(`Instance not found: ${name} (no in-memory state and no tagged resources on the cluster). The instance may have been cleaned up already, or was deployed with a typekro version that did not tag resources.`, 'INSTANCE_NOT_FOUND', { instanceName: name, factoryName: this.name });
|
|
326
|
+
}
|
|
327
|
+
this.logger.info('Cross-process cleanup: discovered deployment from cluster labels', {
|
|
328
|
+
instanceName: name,
|
|
329
|
+
factoryName: this.name,
|
|
330
|
+
deploymentId: record.deploymentId,
|
|
331
|
+
resourceCount: record.resources.length,
|
|
332
|
+
});
|
|
333
|
+
return engine.rollbackRecord(record, {
|
|
334
|
+
...(opts?.scopes && { scopes: opts.scopes }),
|
|
335
|
+
...(opts?.includeUnscopedResources === false && { includeUnscopedResources: false }),
|
|
336
|
+
});
|
|
337
|
+
}
|
|
206
338
|
/**
|
|
207
339
|
* Poll until the given namespaces no longer exist (HTTP 404).
|
|
208
340
|
* Namespaces enter a "Terminating" phase on deletion and may take time
|
|
@@ -214,6 +346,7 @@ export class DirectResourceFactoryImpl {
|
|
|
214
346
|
for (const ns of namespaces) {
|
|
215
347
|
// Each namespace gets its own timeout budget
|
|
216
348
|
const nsStartTime = Date.now();
|
|
349
|
+
let deleted = false;
|
|
217
350
|
while (Date.now() - nsStartTime < timeout) {
|
|
218
351
|
try {
|
|
219
352
|
await k8sApi.read({
|
|
@@ -229,20 +362,28 @@ export class DirectResourceFactoryImpl {
|
|
|
229
362
|
const k8sErr = error;
|
|
230
363
|
if (k8sErr.statusCode === 404 || k8sErr.body?.code === 404) {
|
|
231
364
|
this.logger.debug('Namespace fully deleted', { namespace: ns });
|
|
365
|
+
deleted = true;
|
|
232
366
|
break;
|
|
233
367
|
}
|
|
234
|
-
// Unexpected error —
|
|
368
|
+
// Unexpected error — fail loudly so callers do not assume cleanup completed.
|
|
235
369
|
this.logger.warn('Error polling namespace deletion', {
|
|
236
370
|
namespace: ns,
|
|
237
371
|
error: ensureError(error).message,
|
|
238
372
|
});
|
|
239
|
-
|
|
373
|
+
throw error;
|
|
240
374
|
}
|
|
241
375
|
}
|
|
376
|
+
if (!deleted) {
|
|
377
|
+
throw new ResourceGraphFactoryError(`Timed out waiting for namespace ${ns} to be deleted after ${timeout}ms`, this.name, 'cleanup');
|
|
378
|
+
}
|
|
242
379
|
}
|
|
243
380
|
}
|
|
244
381
|
/**
|
|
245
382
|
* Get factory status with real health checking using readiness evaluators
|
|
383
|
+
*
|
|
384
|
+
* Direct mode status is based on same-process instances returned by
|
|
385
|
+
* `getInstances()`. Use `deleteInstance(name)` for cross-process cleanup;
|
|
386
|
+
* status reconstruction from tagged live resources is not currently exposed.
|
|
246
387
|
*/
|
|
247
388
|
async getStatus() {
|
|
248
389
|
const instances = await this.getInstances();
|
|
@@ -460,27 +601,60 @@ export class DirectResourceFactoryImpl {
|
|
|
460
601
|
}
|
|
461
602
|
/**
|
|
462
603
|
* Rollback all deployments made by this factory
|
|
604
|
+
*
|
|
605
|
+
* This rolls back same-process deployments tracked by this factory instance.
|
|
606
|
+
* For cross-process cleanup, call `deleteInstance(name)` with the known
|
|
607
|
+
* instance name so TypeKro can discover tagged resources from the cluster.
|
|
463
608
|
*/
|
|
464
609
|
async rollback() {
|
|
465
610
|
this.logger.debug('Starting rollback for all deployed instances');
|
|
466
|
-
|
|
467
|
-
const
|
|
468
|
-
const kubeConfig = clientProvider.getKubeConfig();
|
|
469
|
-
// Create rollback manager with the provider's KubeConfig
|
|
470
|
-
const rollbackManager = createRollbackManagerWithKubeConfig(kubeConfig);
|
|
471
|
-
// Get all deployed instances as Enhanced resources
|
|
472
|
-
const resourcesToRollback = Array.from(this.deployedInstances.values());
|
|
611
|
+
const startedAt = Date.now();
|
|
612
|
+
const instanceNames = Array.from(this.deployedInstances.keys());
|
|
473
613
|
this.logger.debug('Rolling back resources', {
|
|
474
|
-
|
|
475
|
-
instanceNames
|
|
614
|
+
instanceCount: instanceNames.length,
|
|
615
|
+
instanceNames,
|
|
476
616
|
});
|
|
477
|
-
|
|
478
|
-
const
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
617
|
+
const rolledBackResources = [];
|
|
618
|
+
const errors = [];
|
|
619
|
+
let status = 'success';
|
|
620
|
+
for (const instanceName of instanceNames) {
|
|
621
|
+
try {
|
|
622
|
+
const result = await this.rollbackInstanceResources(instanceName);
|
|
623
|
+
rolledBackResources.push(...result.rolledBackResources);
|
|
624
|
+
errors.push(...result.errors);
|
|
625
|
+
if (result.status === 'failed') {
|
|
626
|
+
status = 'failed';
|
|
627
|
+
}
|
|
628
|
+
else if (result.status === 'partial' && status === 'success') {
|
|
629
|
+
status = 'partial';
|
|
630
|
+
}
|
|
631
|
+
if (result.status === 'success' && result.errors.length === 0) {
|
|
632
|
+
this.deployedInstances.delete(instanceName);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
catch (error) {
|
|
636
|
+
status = 'failed';
|
|
637
|
+
errors.push({
|
|
638
|
+
resourceId: instanceName,
|
|
639
|
+
phase: 'rollback',
|
|
640
|
+
error: ensureError(error),
|
|
641
|
+
timestamp: new Date(),
|
|
642
|
+
});
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
if (errors.length > 0 && status === 'success') {
|
|
646
|
+
status = rolledBackResources.length > 0 ? 'partial' : 'failed';
|
|
647
|
+
}
|
|
648
|
+
const result = {
|
|
649
|
+
deploymentId: `factory-rollback-${Date.now()}`,
|
|
650
|
+
rolledBackResources,
|
|
651
|
+
duration: Date.now() - startedAt,
|
|
652
|
+
status,
|
|
653
|
+
errors,
|
|
654
|
+
};
|
|
655
|
+
if (result.status === 'success') {
|
|
656
|
+
this.deployedInstances.clear();
|
|
657
|
+
}
|
|
484
658
|
this.logger.info('Rollback completed', {
|
|
485
659
|
status: result.status,
|
|
486
660
|
resourceCount: result.rolledBackResources.length,
|
|
@@ -517,7 +691,10 @@ export class DirectResourceFactoryImpl {
|
|
|
517
691
|
*/
|
|
518
692
|
toYaml(spec) {
|
|
519
693
|
// Resolve references with the actual spec values
|
|
520
|
-
const resolvedResources = this.resolveResourcesForSpec(spec)
|
|
694
|
+
const resolvedResources = applyAspects(this.resolveResourcesForSpec(spec), {
|
|
695
|
+
mode: 'direct',
|
|
696
|
+
aspects: this.factoryOptions.aspects ?? [],
|
|
697
|
+
});
|
|
521
698
|
// Validate that all values are fully resolved — no KubernetesRef or
|
|
522
699
|
// CelExpression objects should remain in direct-mode YAML output.
|
|
523
700
|
const unresolvedRefs = findUnresolvedReferences(resolvedResources);
|
|
@@ -551,6 +728,9 @@ export class DirectResourceFactoryImpl {
|
|
|
551
728
|
...(cleanResource.metadata?.labels
|
|
552
729
|
? { labels: cleanResource.metadata.labels }
|
|
553
730
|
: undefined),
|
|
731
|
+
...(cleanResource.metadata?.annotations
|
|
732
|
+
? { annotations: cleanResource.metadata.annotations }
|
|
733
|
+
: undefined),
|
|
554
734
|
},
|
|
555
735
|
};
|
|
556
736
|
// Handle different resource types
|
|
@@ -572,10 +752,13 @@ export class DirectResourceFactoryImpl {
|
|
|
572
752
|
/**
|
|
573
753
|
* Create a resource graph for a specific instance
|
|
574
754
|
*/
|
|
575
|
-
createResourceGraphForInstance(spec) {
|
|
755
|
+
createResourceGraphForInstance(spec, instanceNameOverride) {
|
|
576
756
|
const dependencyResolver = new DependencyResolver();
|
|
577
|
-
const resolvedResources = this.resolveResourcesForSpec(spec)
|
|
578
|
-
|
|
757
|
+
const resolvedResources = applyAspects(this.resolveResourcesForSpec(spec), {
|
|
758
|
+
mode: 'direct',
|
|
759
|
+
aspects: this.factoryOptions.aspects ?? [],
|
|
760
|
+
});
|
|
761
|
+
const instanceName = instanceNameOverride ?? this.generateInstanceName(spec);
|
|
579
762
|
const resourceArray = Object.values(resolvedResources).map((resource, index) => {
|
|
580
763
|
this.logger.debug('Processing resource for ID generation', {
|
|
581
764
|
index,
|
|
@@ -662,7 +845,8 @@ export class DirectResourceFactoryImpl {
|
|
|
662
845
|
}
|
|
663
846
|
}
|
|
664
847
|
catch (error) {
|
|
665
|
-
this.logger.error('Failed to re-execute composition
|
|
848
|
+
this.logger.error('Failed to re-execute composition with actual spec values', ensureError(error));
|
|
849
|
+
throw error;
|
|
666
850
|
}
|
|
667
851
|
}
|
|
668
852
|
// Fall back to the original reference resolution approach
|
|
@@ -699,6 +883,7 @@ export class DirectResourceFactoryImpl {
|
|
|
699
883
|
// with the same id (e.g., 'regionDep') get unique keys ('regionDep', 'regionDep-1', etc.)
|
|
700
884
|
const reExecutionContext = createCompositionContext('re-execution', {
|
|
701
885
|
deduplicateIds: true,
|
|
886
|
+
isReExecution: true,
|
|
702
887
|
});
|
|
703
888
|
// Execute the composition function within the new context and capture both resources and status
|
|
704
889
|
const { resources, status } = runWithCompositionContext(reExecutionContext, () => {
|
|
@@ -737,7 +922,7 @@ export class DirectResourceFactoryImpl {
|
|
|
737
922
|
}
|
|
738
923
|
catch (error) {
|
|
739
924
|
this.logger.error('Failed to re-execute composition', ensureError(error));
|
|
740
|
-
|
|
925
|
+
throw error;
|
|
741
926
|
}
|
|
742
927
|
}
|
|
743
928
|
/**
|
|
@@ -747,6 +932,22 @@ export class DirectResourceFactoryImpl {
|
|
|
747
932
|
getReExecutedStatus() {
|
|
748
933
|
return this.reExecutedStatus;
|
|
749
934
|
}
|
|
935
|
+
reExecuteSingletonStatus(singletonDefinition, liveStatusMap) {
|
|
936
|
+
const compositionFn = singletonDefinition.composition._compositionFn;
|
|
937
|
+
if (!compositionFn) {
|
|
938
|
+
return undefined;
|
|
939
|
+
}
|
|
940
|
+
const singletonContext = createCompositionContext('singleton-re-execution', {
|
|
941
|
+
deduplicateIds: true,
|
|
942
|
+
isReExecution: true,
|
|
943
|
+
});
|
|
944
|
+
singletonContext.liveStatusMap = liveStatusMap;
|
|
945
|
+
const status = runWithCompositionContext(singletonContext, () => compositionFn(singletonDefinition.spec));
|
|
946
|
+
if (status && typeof status === 'object' && !Array.isArray(status)) {
|
|
947
|
+
return status;
|
|
948
|
+
}
|
|
949
|
+
return undefined;
|
|
950
|
+
}
|
|
750
951
|
/**
|
|
751
952
|
* Re-execute the composition with live status data from deployed resources.
|
|
752
953
|
*
|
|
@@ -773,6 +974,7 @@ export class DirectResourceFactoryImpl {
|
|
|
773
974
|
// synthesize status entries from child resources' live data.
|
|
774
975
|
const probeContext = createCompositionContext('re-execution-probe', {
|
|
775
976
|
deduplicateIds: true,
|
|
977
|
+
isReExecution: true,
|
|
776
978
|
});
|
|
777
979
|
probeContext.liveStatusMap = liveStatusMap;
|
|
778
980
|
runWithCompositionContext(probeContext, () => {
|
|
@@ -787,10 +989,41 @@ export class DirectResourceFactoryImpl {
|
|
|
787
989
|
// This uses synthesizeNestedCompositionStatus which is shared between
|
|
788
990
|
// direct and KRO deployment strategies — it only depends on the probe
|
|
789
991
|
// context's resource keys and the liveStatusMap's deployed resource keys.
|
|
790
|
-
const enrichedMap = synthesizeNestedCompositionStatus(probeContext.resources, liveStatusMap, this.logger, probeContext.nestedCompositionIds);
|
|
992
|
+
const enrichedMap = synthesizeNestedCompositionStatus(probeContext.resources, liveStatusMap, this.logger, probeContext.nestedCompositionIds, probeContext.nestedStatusSnapshots);
|
|
993
|
+
// Framework invariant: direct-mode re-execution must preserve the same
|
|
994
|
+
// cross-composition semantics as KRO-mode serialization. If a user writes
|
|
995
|
+
// `const stack = nestedComp(...); return { ready: stack.status.ready && ... }`,
|
|
996
|
+
// TypeKro must resolve that alias in the framework rather than pushing
|
|
997
|
+
// CEL-specific workarounds into composition code.
|
|
998
|
+
const aliasTargets = buildNestedCompositionAliasTargets(this.factoryOptions.compositionFn.toString(), probeContext.nestedCompositionIds);
|
|
999
|
+
for (const [aliasName, baseId] of Object.entries(aliasTargets)) {
|
|
1000
|
+
const synthesizedStatus = enrichedMap.get(baseId);
|
|
1001
|
+
if (synthesizedStatus && !enrichedMap.has(aliasName)) {
|
|
1002
|
+
enrichedMap.set(aliasName, synthesizedStatus);
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
const singletonDefinitions = new Map();
|
|
1006
|
+
for (const definition of this.singletonDefinitions) {
|
|
1007
|
+
singletonDefinitions.set(definition.key, definition);
|
|
1008
|
+
}
|
|
1009
|
+
for (const definition of probeContext.singletonDefinitions?.values() ?? []) {
|
|
1010
|
+
singletonDefinitions.set(definition.key, definition);
|
|
1011
|
+
}
|
|
1012
|
+
for (const definition of singletonDefinitions.values()) {
|
|
1013
|
+
const singletonResourceId = getSingletonResourceId(definition.key);
|
|
1014
|
+
if (enrichedMap.has(singletonResourceId)) {
|
|
1015
|
+
continue;
|
|
1016
|
+
}
|
|
1017
|
+
const singletonStatus = this.singletonOwnerStatuses.get(singletonResourceId) ??
|
|
1018
|
+
this.reExecuteSingletonStatus(definition, liveStatusMap);
|
|
1019
|
+
if (singletonStatus) {
|
|
1020
|
+
enrichedMap.set(singletonResourceId, singletonStatus);
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
791
1023
|
// Phase 2: Real execution with enriched live status map
|
|
792
1024
|
const reExecutionContext = createCompositionContext('re-execution', {
|
|
793
1025
|
deduplicateIds: true,
|
|
1026
|
+
isReExecution: true,
|
|
794
1027
|
});
|
|
795
1028
|
reExecutionContext.liveStatusMap = enrichedMap;
|
|
796
1029
|
const { status } = runWithCompositionContext(reExecutionContext, () => {
|
|
@@ -920,6 +1153,19 @@ export class DirectResourceFactoryImpl {
|
|
|
920
1153
|
}
|
|
921
1154
|
return { found: true, value: currentValue };
|
|
922
1155
|
}
|
|
1156
|
+
resolveSpecPathValue(spec, specPath, logPath) {
|
|
1157
|
+
const pathParts = specPath.split('.').filter(Boolean);
|
|
1158
|
+
return this.traverseSpec(spec, pathParts, logPath);
|
|
1159
|
+
}
|
|
1160
|
+
stringifyCelFallbackValue(value) {
|
|
1161
|
+
if (value === null)
|
|
1162
|
+
return 'null';
|
|
1163
|
+
if (typeof value === 'string')
|
|
1164
|
+
return value;
|
|
1165
|
+
if (typeof value === 'number' || typeof value === 'boolean')
|
|
1166
|
+
return String(value);
|
|
1167
|
+
return JSON.stringify(value);
|
|
1168
|
+
}
|
|
923
1169
|
/**
|
|
924
1170
|
* Resolve schema references and CEL expressions to actual values for direct deployment.
|
|
925
1171
|
* This is the final, corrected version that handles both direct proxies and Cel.expr wrappers.
|
|
@@ -949,15 +1195,24 @@ export class DirectResourceFactoryImpl {
|
|
|
949
1195
|
this.logger.trace('Found CEL Expression', { path, expression: resource.expression });
|
|
950
1196
|
// The .expression property holds a string like "schema.spec.name-db-config"
|
|
951
1197
|
let expressionString = resource.expression;
|
|
1198
|
+
const exactSchemaRef = expressionString.match(/^schema\.spec\.([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*)$/);
|
|
1199
|
+
const exactSpecPath = exactSchemaRef?.[1];
|
|
1200
|
+
if (exactSpecPath !== undefined) {
|
|
1201
|
+
const resolved = this.resolveSpecPathValue(spec, exactSpecPath, path);
|
|
1202
|
+
if (resolved.found) {
|
|
1203
|
+
return resolved.value;
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
952
1206
|
// Use regex to find all `schema.spec.fieldName` placeholders in the string
|
|
953
1207
|
// and replace them with the corresponding values from the spec object.
|
|
954
1208
|
// The 'g' flag ensures all occurrences are replaced.
|
|
955
|
-
expressionString = expressionString.replace(/schema\.spec\.(\w
|
|
956
|
-
const
|
|
957
|
-
|
|
1209
|
+
expressionString = expressionString.replace(/schema\.spec\.([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*)/g, (_match, specPath) => {
|
|
1210
|
+
const resolved = this.resolveSpecPathValue(spec, specPath, path);
|
|
1211
|
+
const value = resolved.found ? resolved.value : undefined;
|
|
1212
|
+
this.logger.trace('Replacing CEL placeholder', { specPath, value });
|
|
958
1213
|
// If the value exists in the spec, convert it to a string for concatenation.
|
|
959
1214
|
// Otherwise, keep the original placeholder (though this shouldn't happen in valid cases).
|
|
960
|
-
return value !== undefined ?
|
|
1215
|
+
return value !== undefined ? this.stringifyCelFallbackValue(value) : _match;
|
|
961
1216
|
});
|
|
962
1217
|
this.logger.trace('Resolved CEL expression to value', {
|
|
963
1218
|
path,
|
|
@@ -1007,7 +1262,7 @@ export class DirectResourceFactoryImpl {
|
|
|
1007
1262
|
// Pattern: __KUBERNETES_REF_{resourceId}_{fieldPath}__
|
|
1008
1263
|
// For schema: __KUBERNETES_REF___schema___{fieldPath}__
|
|
1009
1264
|
// The fieldPath for schema refs is like "spec.baseName" or "spec.nested.field"
|
|
1010
|
-
const resolvedString = resource.replace(
|
|
1265
|
+
const resolvedString = resource.replace(new RegExp(KUBERNETES_REF_SCHEMA_MARKER_SOURCE, 'g'), (_match, fieldPath) => {
|
|
1011
1266
|
// fieldPath is like "spec.baseName" - we need to traverse starting from the schema root
|
|
1012
1267
|
const pathParts = fieldPath.split('.');
|
|
1013
1268
|
// The first part should be 'spec' or 'status'
|
|
@@ -1050,6 +1305,271 @@ export class DirectResourceFactoryImpl {
|
|
|
1050
1305
|
// Use the imported shared utility
|
|
1051
1306
|
return generateInstanceName(spec);
|
|
1052
1307
|
}
|
|
1308
|
+
async ensureTargetNamespace(namespace = this.namespace) {
|
|
1309
|
+
try {
|
|
1310
|
+
const { createBunCompatibleKubernetesObjectApi } = await import('../kubernetes/bun-api-client.js');
|
|
1311
|
+
const k8sApi = createBunCompatibleKubernetesObjectApi(this.getClientProvider().getKubeConfig());
|
|
1312
|
+
const waitForNamespaceDeletion = async () => {
|
|
1313
|
+
const start = Date.now();
|
|
1314
|
+
while (Date.now() - start < 120000) {
|
|
1315
|
+
try {
|
|
1316
|
+
const existing = (await k8sApi.read({
|
|
1317
|
+
apiVersion: 'v1',
|
|
1318
|
+
kind: 'Namespace',
|
|
1319
|
+
metadata: { name: namespace },
|
|
1320
|
+
}));
|
|
1321
|
+
if (!existing.metadata?.deletionTimestamp) {
|
|
1322
|
+
return;
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
catch (pollError) {
|
|
1326
|
+
const err = pollError;
|
|
1327
|
+
const code = err.statusCode ?? err.body?.code;
|
|
1328
|
+
if (code === 404) {
|
|
1329
|
+
return;
|
|
1330
|
+
}
|
|
1331
|
+
throw pollError;
|
|
1332
|
+
}
|
|
1333
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
1334
|
+
}
|
|
1335
|
+
throw new Error(`Namespace ${namespace} is still terminating after 120000ms`);
|
|
1336
|
+
};
|
|
1337
|
+
try {
|
|
1338
|
+
const existing = (await k8sApi.read({
|
|
1339
|
+
apiVersion: 'v1',
|
|
1340
|
+
kind: 'Namespace',
|
|
1341
|
+
metadata: { name: namespace },
|
|
1342
|
+
}));
|
|
1343
|
+
if (existing.metadata?.deletionTimestamp) {
|
|
1344
|
+
await waitForNamespaceDeletion();
|
|
1345
|
+
}
|
|
1346
|
+
else {
|
|
1347
|
+
return;
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
catch (readError) {
|
|
1351
|
+
const k8sErr = readError;
|
|
1352
|
+
const code = k8sErr.statusCode ?? k8sErr.body?.code;
|
|
1353
|
+
if (code !== 404) {
|
|
1354
|
+
throw readError;
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
try {
|
|
1358
|
+
await k8sApi.create({
|
|
1359
|
+
apiVersion: 'v1',
|
|
1360
|
+
kind: 'Namespace',
|
|
1361
|
+
metadata: {
|
|
1362
|
+
name: namespace,
|
|
1363
|
+
labels: {
|
|
1364
|
+
'app.kubernetes.io/managed-by': 'typekro',
|
|
1365
|
+
},
|
|
1366
|
+
},
|
|
1367
|
+
});
|
|
1368
|
+
}
|
|
1369
|
+
catch (createError) {
|
|
1370
|
+
const k8sErr = createError;
|
|
1371
|
+
const code = k8sErr.statusCode ?? k8sErr.body?.code;
|
|
1372
|
+
const isNamespaceTerminating = k8sErr.body?.reason === 'Forbidden' &&
|
|
1373
|
+
k8sErr.message?.includes('NamespaceTerminating') === true;
|
|
1374
|
+
if (isNamespaceTerminating) {
|
|
1375
|
+
await waitForNamespaceDeletion();
|
|
1376
|
+
await k8sApi.create({
|
|
1377
|
+
apiVersion: 'v1',
|
|
1378
|
+
kind: 'Namespace',
|
|
1379
|
+
metadata: {
|
|
1380
|
+
name: namespace,
|
|
1381
|
+
labels: {
|
|
1382
|
+
'app.kubernetes.io/managed-by': 'typekro',
|
|
1383
|
+
},
|
|
1384
|
+
},
|
|
1385
|
+
});
|
|
1386
|
+
}
|
|
1387
|
+
else if (code !== 409) {
|
|
1388
|
+
throw createError;
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
catch (error) {
|
|
1393
|
+
throw new ResourceGraphFactoryError(`Failed to ensure target namespace "${namespace}" exists: ${ensureError(error).message}`, this.name, 'deployment', ensureError(error));
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
async ensureSingletonOwners(spec) {
|
|
1397
|
+
const discoveredSingletons = new Map();
|
|
1398
|
+
if (this.factoryOptions.compositionFn) {
|
|
1399
|
+
const singletonContext = createCompositionContext('singleton-owner-discovery');
|
|
1400
|
+
runWithCompositionContext(singletonContext, () => {
|
|
1401
|
+
this.factoryOptions.compositionFn?.(spec);
|
|
1402
|
+
});
|
|
1403
|
+
for (const [key, definition] of singletonContext.singletonDefinitions ?? []) {
|
|
1404
|
+
discoveredSingletons.set(key, definition);
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
for (const definition of this.singletonDefinitions) {
|
|
1408
|
+
if (!discoveredSingletons.has(definition.key)) {
|
|
1409
|
+
discoveredSingletons.set(definition.key, definition);
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
if (discoveredSingletons.size === 0)
|
|
1413
|
+
return;
|
|
1414
|
+
for (const definition of discoveredSingletons.values()) {
|
|
1415
|
+
await this.ensureTargetNamespace(definition.registryNamespace);
|
|
1416
|
+
const singletonInstanceName = getSingletonInstanceName(definition.id);
|
|
1417
|
+
const singletonFactory = definition.composition.factory('direct', {
|
|
1418
|
+
namespace: definition.registryNamespace,
|
|
1419
|
+
waitForReady: true,
|
|
1420
|
+
...(this.factoryOptions.timeout !== undefined
|
|
1421
|
+
? { timeout: this.factoryOptions.timeout }
|
|
1422
|
+
: {}),
|
|
1423
|
+
...(this.factoryOptions.kubeConfig !== undefined
|
|
1424
|
+
? { kubeConfig: this.factoryOptions.kubeConfig }
|
|
1425
|
+
: {}),
|
|
1426
|
+
...(this.factoryOptions.skipTLSVerify !== undefined
|
|
1427
|
+
? { skipTLSVerify: this.factoryOptions.skipTLSVerify }
|
|
1428
|
+
: {}),
|
|
1429
|
+
});
|
|
1430
|
+
try {
|
|
1431
|
+
const existingInstances = await singletonFactory.getInstances();
|
|
1432
|
+
assertNoDeployedSingletonSpecDrift(definition, singletonInstanceName, existingInstances);
|
|
1433
|
+
if ('createResourceGraphForInstance' in singletonFactory &&
|
|
1434
|
+
existingInstances.length === 0) {
|
|
1435
|
+
const discovered = await this.getDeploymentEngine().loadDeploymentByInstance({
|
|
1436
|
+
factoryName: singletonFactory.name,
|
|
1437
|
+
instanceName: singletonInstanceName,
|
|
1438
|
+
});
|
|
1439
|
+
const discoveredResources = discovered?.resources ?? [];
|
|
1440
|
+
const driftCheck = assertNoDiscoveredSingletonSpecDrift(definition, singletonInstanceName, discoveredResources);
|
|
1441
|
+
if (driftCheck.hasLegacyUnfingerprintedResources) {
|
|
1442
|
+
const expectedGraph = singletonFactory.createResourceGraphForInstance(definition.spec, singletonInstanceName);
|
|
1443
|
+
const discoveredIds = new Set(discoveredResources.map((resource) => resource.id));
|
|
1444
|
+
const hasAllExpectedResources = expectedGraph.resources.every((resource) => discoveredIds.has(resource.id));
|
|
1445
|
+
const hasHelmReleaseResources = expectedGraph.resources.some((resource) => resource.manifest.kind === 'HelmRelease');
|
|
1446
|
+
const legacyStatus = this.reExecuteSingletonStatusFromDiscoveredResources(definition, discoveredResources);
|
|
1447
|
+
if (legacyStatus) {
|
|
1448
|
+
this.singletonOwnerStatuses.set(getSingletonResourceId(definition.key), legacyStatus);
|
|
1449
|
+
}
|
|
1450
|
+
if (hasAllExpectedResources && !hasHelmReleaseResources) {
|
|
1451
|
+
this.logger.warn('Skipping direct singleton owner reconciliation for legacy resources without a spec fingerprint', {
|
|
1452
|
+
singletonId: definition.id,
|
|
1453
|
+
singletonKey: definition.key,
|
|
1454
|
+
singletonInstanceName,
|
|
1455
|
+
registryNamespace: definition.registryNamespace,
|
|
1456
|
+
});
|
|
1457
|
+
continue;
|
|
1458
|
+
}
|
|
1459
|
+
this.logger.warn('Reconciling direct singleton owner because legacy resources may need repair', {
|
|
1460
|
+
singletonId: definition.id,
|
|
1461
|
+
singletonKey: definition.key,
|
|
1462
|
+
singletonInstanceName,
|
|
1463
|
+
registryNamespace: definition.registryNamespace,
|
|
1464
|
+
discoveredResourceCount: discoveredResources.length,
|
|
1465
|
+
expectedResourceCount: expectedGraph.resources.length,
|
|
1466
|
+
hasAllExpectedResources,
|
|
1467
|
+
hasHelmReleaseResources,
|
|
1468
|
+
});
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
const singletonDeployOptions = {
|
|
1472
|
+
instanceNameOverride: singletonInstanceName,
|
|
1473
|
+
singletonSpecFingerprint: singletonSpecFingerprintAnnotationValue(definition.specFingerprint),
|
|
1474
|
+
};
|
|
1475
|
+
const deployedSingleton = await singletonFactory.deploy(definition.spec, singletonDeployOptions);
|
|
1476
|
+
const singletonStatus = deployedSingleton.status;
|
|
1477
|
+
if (singletonStatus &&
|
|
1478
|
+
typeof singletonStatus === 'object' &&
|
|
1479
|
+
!Array.isArray(singletonStatus)) {
|
|
1480
|
+
this.singletonOwnerStatuses.set(getSingletonResourceId(definition.key), singletonStatus);
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
finally {
|
|
1484
|
+
await singletonFactory.dispose?.();
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
reExecuteSingletonStatusFromDiscoveredResources(definition, resources) {
|
|
1489
|
+
if (resources.length === 0)
|
|
1490
|
+
return null;
|
|
1491
|
+
const liveStatusMap = new Map();
|
|
1492
|
+
const localIdsByLiveIdentity = this.getSingletonLocalIdsByLiveIdentity(definition);
|
|
1493
|
+
const singletonInstanceName = getSingletonInstanceName(definition.id);
|
|
1494
|
+
for (const resource of resources) {
|
|
1495
|
+
const manifest = resource.manifest;
|
|
1496
|
+
const status = manifest && typeof manifest === 'object' && 'status' in manifest
|
|
1497
|
+
? manifest.status
|
|
1498
|
+
: undefined;
|
|
1499
|
+
const statusRecord = status && typeof status === 'object' && !Array.isArray(status)
|
|
1500
|
+
? status
|
|
1501
|
+
: {};
|
|
1502
|
+
for (const id of this.getSingletonStatusAliases(resource.id, manifest, singletonInstanceName, localIdsByLiveIdentity)) {
|
|
1503
|
+
liveStatusMap.set(id, statusRecord);
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
return this.reExecuteSingletonStatus(definition, liveStatusMap) ?? null;
|
|
1507
|
+
}
|
|
1508
|
+
getSingletonLocalIdsByLiveIdentity(definition) {
|
|
1509
|
+
const compositionFn = definition.composition._compositionFn;
|
|
1510
|
+
const idsByIdentity = new Map();
|
|
1511
|
+
if (!compositionFn)
|
|
1512
|
+
return idsByIdentity;
|
|
1513
|
+
const probeContext = createCompositionContext('singleton-status-discovery-probe', {
|
|
1514
|
+
deduplicateIds: true,
|
|
1515
|
+
isReExecution: true,
|
|
1516
|
+
});
|
|
1517
|
+
runWithCompositionContext(probeContext, () => compositionFn(definition.spec));
|
|
1518
|
+
for (const [id, resource] of Object.entries(probeContext.resources)) {
|
|
1519
|
+
const identity = this.getLiveIdentityKey(resource.kind, resource.metadata?.name, resource.metadata?.namespace);
|
|
1520
|
+
if (identity)
|
|
1521
|
+
idsByIdentity.set(identity, id);
|
|
1522
|
+
const namespaceAgnosticIdentity = this.getLiveIdentityKey(resource.kind, resource.metadata?.name);
|
|
1523
|
+
if (namespaceAgnosticIdentity)
|
|
1524
|
+
idsByIdentity.set(namespaceAgnosticIdentity, id);
|
|
1525
|
+
}
|
|
1526
|
+
return idsByIdentity;
|
|
1527
|
+
}
|
|
1528
|
+
getSingletonStatusAliases(discoveredId, manifest, singletonInstanceName, localIdsByLiveIdentity) {
|
|
1529
|
+
const aliases = new Set([discoveredId]);
|
|
1530
|
+
const annotationId = manifest && typeof manifest === 'object'
|
|
1531
|
+
? manifest.metadata
|
|
1532
|
+
?.annotations?.['typekro.io/resource-id']
|
|
1533
|
+
: undefined;
|
|
1534
|
+
if (annotationId)
|
|
1535
|
+
aliases.add(annotationId);
|
|
1536
|
+
const derivedId = this.deriveLocalIdFromDirectGraphId(discoveredId, singletonInstanceName, localIdsByLiveIdentity.values());
|
|
1537
|
+
if (derivedId)
|
|
1538
|
+
aliases.add(derivedId);
|
|
1539
|
+
if (manifest && typeof manifest === 'object') {
|
|
1540
|
+
const resource = manifest;
|
|
1541
|
+
const identity = this.getLiveIdentityKey(resource.kind, resource.metadata?.name, resource.metadata?.namespace);
|
|
1542
|
+
const namespaceAgnosticIdentity = this.getLiveIdentityKey(resource.kind, resource.metadata?.name);
|
|
1543
|
+
const localId = (identity ? localIdsByLiveIdentity.get(identity) : undefined) ??
|
|
1544
|
+
(namespaceAgnosticIdentity
|
|
1545
|
+
? localIdsByLiveIdentity.get(namespaceAgnosticIdentity)
|
|
1546
|
+
: undefined);
|
|
1547
|
+
if (localId)
|
|
1548
|
+
aliases.add(localId);
|
|
1549
|
+
}
|
|
1550
|
+
return [...aliases];
|
|
1551
|
+
}
|
|
1552
|
+
deriveLocalIdFromDirectGraphId(id, singletonInstanceName, candidateLocalIds = []) {
|
|
1553
|
+
const prefix = `${toCamelCase(singletonInstanceName)}Resource`;
|
|
1554
|
+
const match = id.match(new RegExp(`^${prefix}\\d+(.+)$`));
|
|
1555
|
+
if (!match?.[1])
|
|
1556
|
+
return undefined;
|
|
1557
|
+
const suffix = match[1].charAt(0).toLowerCase() + match[1].slice(1);
|
|
1558
|
+
const normalizedSuffix = suffix.toLowerCase();
|
|
1559
|
+
for (const candidate of candidateLocalIds) {
|
|
1560
|
+
if (candidate === suffix ||
|
|
1561
|
+
candidate.toLowerCase() === normalizedSuffix ||
|
|
1562
|
+
toCamelCase(candidate).toLowerCase() === normalizedSuffix) {
|
|
1563
|
+
return candidate;
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
return suffix;
|
|
1567
|
+
}
|
|
1568
|
+
getLiveIdentityKey(kind, name, namespace) {
|
|
1569
|
+
if (!kind || !name)
|
|
1570
|
+
return undefined;
|
|
1571
|
+
return `${kind}/${namespace ?? ''}/${name}`;
|
|
1572
|
+
}
|
|
1053
1573
|
}
|
|
1054
1574
|
/**
|
|
1055
1575
|
* Recursively walk a resolved resource tree and collect any remaining
|
|
@@ -1107,7 +1627,9 @@ function findUnresolvedReferences(resources) {
|
|
|
1107
1627
|
/**
|
|
1108
1628
|
* Create a DirectResourceFactory instance
|
|
1109
1629
|
*/
|
|
1110
|
-
export function createDirectResourceFactory(name, resources, schemaDefinition,
|
|
1630
|
+
export function createDirectResourceFactory(name, resources, schemaDefinition,
|
|
1631
|
+
// biome-ignore lint/suspicious/noExplicitAny: factory creation must accept status builders with composition-specific resource maps.
|
|
1632
|
+
statusBuilder, options = {}) {
|
|
1111
1633
|
return new DirectResourceFactoryImpl(name, resources, schemaDefinition, statusBuilder, options);
|
|
1112
1634
|
}
|
|
1113
1635
|
//# sourceMappingURL=direct-factory.js.map
|