typekro 0.33.9 → 0.34.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/compositions/typekro-runtime/typekro-runtime.d.ts +0 -33
- package/dist/compositions/typekro-runtime/typekro-runtime.d.ts.map +1 -1
- package/dist/compositions/typekro-runtime/typekro-runtime.js +63 -1
- package/dist/compositions/typekro-runtime/typekro-runtime.js.map +1 -1
- package/dist/compositions/typekro-runtime/types.d.ts +8 -0
- package/dist/compositions/typekro-runtime/types.d.ts.map +1 -1
- package/dist/compositions/typekro-runtime/types.js +1 -0
- package/dist/compositions/typekro-runtime/types.js.map +1 -1
- package/dist/core/aspects/values-merge.d.ts +17 -0
- package/dist/core/aspects/values-merge.d.ts.map +1 -1
- package/dist/core/aspects/values-merge.js +67 -8
- package/dist/core/aspects/values-merge.js.map +1 -1
- package/dist/core/deployment/direct-factory.d.ts +9 -0
- package/dist/core/deployment/direct-factory.d.ts.map +1 -1
- package/dist/core/deployment/direct-factory.js +37 -3
- package/dist/core/deployment/direct-factory.js.map +1 -1
- package/dist/core/deployment/engine.d.ts +34 -0
- package/dist/core/deployment/engine.d.ts.map +1 -1
- package/dist/core/deployment/engine.js +173 -29
- package/dist/core/deployment/engine.js.map +1 -1
- package/dist/core/deployment/index.d.ts +2 -0
- package/dist/core/deployment/index.d.ts.map +1 -1
- package/dist/core/deployment/index.js +1 -0
- package/dist/core/deployment/index.js.map +1 -1
- package/dist/core/deployment/k8s-helpers.d.ts +73 -0
- package/dist/core/deployment/k8s-helpers.d.ts.map +1 -1
- package/dist/core/deployment/k8s-helpers.js +198 -4
- package/dist/core/deployment/k8s-helpers.js.map +1 -1
- package/dist/core/deployment/kro-factory.d.ts.map +1 -1
- package/dist/core/deployment/kro-factory.js +21 -1
- package/dist/core/deployment/kro-factory.js.map +1 -1
- package/dist/core/deployment/status-leaf-resolution.d.ts +101 -0
- package/dist/core/deployment/status-leaf-resolution.d.ts.map +1 -0
- package/dist/core/deployment/status-leaf-resolution.js +232 -0
- package/dist/core/deployment/status-leaf-resolution.js.map +1 -0
- package/dist/core/deployment/strategies/base-strategy.d.ts.map +1 -1
- package/dist/core/deployment/strategies/base-strategy.js +31 -3
- package/dist/core/deployment/strategies/base-strategy.js.map +1 -1
- package/dist/core/deployment/strategies/kro-strategy.d.ts.map +1 -1
- package/dist/core/deployment/strategies/kro-strategy.js +8 -1
- package/dist/core/deployment/strategies/kro-strategy.js.map +1 -1
- package/dist/core/expressions/composition/composition-analyzer-helpers.d.ts.map +1 -1
- package/dist/core/expressions/composition/composition-analyzer-helpers.js +20 -2
- package/dist/core/expressions/composition/composition-analyzer-helpers.js.map +1 -1
- package/dist/core/kro/index.d.ts +6 -0
- package/dist/core/kro/index.d.ts.map +1 -0
- package/dist/core/kro/index.js +6 -0
- package/dist/core/kro/index.js.map +1 -0
- package/dist/core/kro/label-guard-capability.d.ts +141 -0
- package/dist/core/kro/label-guard-capability.d.ts.map +1 -0
- package/dist/core/kro/label-guard-capability.js +257 -0
- package/dist/core/kro/label-guard-capability.js.map +1 -0
- package/dist/core/kro/labels.d.ts +56 -0
- package/dist/core/kro/labels.d.ts.map +1 -0
- package/dist/core/kro/labels.js +62 -0
- package/dist/core/kro/labels.js.map +1 -0
- package/dist/core/kubernetes/api-capability.d.ts +196 -0
- package/dist/core/kubernetes/api-capability.d.ts.map +1 -0
- package/dist/core/kubernetes/api-capability.js +301 -0
- package/dist/core/kubernetes/api-capability.js.map +1 -0
- package/dist/core/kubernetes/index.d.ts +2 -0
- package/dist/core/kubernetes/index.d.ts.map +1 -1
- package/dist/core/kubernetes/index.js +2 -0
- package/dist/core/kubernetes/index.js.map +1 -1
- package/dist/core/kubernetes/naming.d.ts +100 -0
- package/dist/core/kubernetes/naming.d.ts.map +1 -0
- package/dist/core/kubernetes/naming.js +93 -0
- package/dist/core/kubernetes/naming.js.map +1 -0
- package/dist/core/planning/direct-runtime-adapter.d.ts.map +1 -1
- package/dist/core/planning/direct-runtime-adapter.js +54 -17
- package/dist/core/planning/direct-runtime-adapter.js.map +1 -1
- package/dist/core/planning/planner.d.ts.map +1 -1
- package/dist/core/planning/planner.js +17 -0
- package/dist/core/planning/planner.js.map +1 -1
- package/dist/core/planning/schema.d.ts.map +1 -1
- package/dist/core/planning/schema.js +7 -3
- package/dist/core/planning/schema.js.map +1 -1
- package/dist/core/references/cel-lexical-scanner.d.ts +100 -1
- package/dist/core/references/cel-lexical-scanner.d.ts.map +1 -1
- package/dist/core/references/cel-lexical-scanner.js +196 -2
- package/dist/core/references/cel-lexical-scanner.js.map +1 -1
- package/dist/core/references/cel.d.ts +249 -1
- package/dist/core/references/cel.d.ts.map +1 -1
- package/dist/core/references/cel.js +289 -8
- package/dist/core/references/cel.js.map +1 -1
- package/dist/core/serialization/arktype-ast.d.ts +21 -0
- package/dist/core/serialization/arktype-ast.d.ts.map +1 -0
- package/dist/core/serialization/arktype-ast.js +29 -0
- package/dist/core/serialization/arktype-ast.js.map +1 -0
- package/dist/core/serialization/cel-references.d.ts +133 -32
- package/dist/core/serialization/cel-references.d.ts.map +1 -1
- package/dist/core/serialization/cel-references.js +908 -109
- package/dist/core/serialization/cel-references.js.map +1 -1
- package/dist/core/serialization/core.d.ts.map +1 -1
- package/dist/core/serialization/core.js +13 -2
- package/dist/core/serialization/core.js.map +1 -1
- package/dist/core/serialization/schema.d.ts +16 -2
- package/dist/core/serialization/schema.d.ts.map +1 -1
- package/dist/core/serialization/schema.js +113 -21
- package/dist/core/serialization/schema.js.map +1 -1
- package/dist/core/types/composable.d.ts +7 -1
- package/dist/core/types/composable.d.ts.map +1 -1
- package/dist/core/types/deployment.d.ts +32 -2
- package/dist/core/types/deployment.d.ts.map +1 -1
- package/dist/core/types/serialization.d.ts +37 -0
- package/dist/core/types/serialization.d.ts.map +1 -1
- package/dist/core/validation/cel-dialect.d.ts +246 -0
- package/dist/core/validation/cel-dialect.d.ts.map +1 -0
- package/dist/core/validation/cel-dialect.js +1997 -0
- package/dist/core/validation/cel-dialect.js.map +1 -0
- package/dist/core/validation/cel-validator.d.ts.map +1 -1
- package/dist/core/validation/cel-validator.js +8 -1
- package/dist/core/validation/cel-validator.js.map +1 -1
- package/dist/core/validation/literal-status.d.ts +107 -0
- package/dist/core/validation/literal-status.d.ts.map +1 -0
- package/dist/core/validation/literal-status.js +346 -0
- package/dist/core/validation/literal-status.js.map +1 -0
- package/dist/core/validation/structural-spec-dependence.d.ts +179 -0
- package/dist/core/validation/structural-spec-dependence.d.ts.map +1 -0
- package/dist/core/validation/structural-spec-dependence.js +911 -0
- package/dist/core/validation/structural-spec-dependence.js.map +1 -0
- package/dist/factories/apisix/compositions/apisix-bootstrap.d.ts.map +1 -1
- package/dist/factories/apisix/compositions/apisix-bootstrap.js +9 -0
- package/dist/factories/apisix/compositions/apisix-bootstrap.js.map +1 -1
- package/dist/factories/clickhouse/compositions/clickhouse-cluster.d.ts +6 -0
- package/dist/factories/clickhouse/compositions/clickhouse-cluster.d.ts.map +1 -1
- package/dist/factories/clickhouse/compositions/clickhouse-cluster.js +273 -23
- package/dist/factories/clickhouse/compositions/clickhouse-cluster.js.map +1 -1
- package/dist/factories/clickhouse/resources/index.d.ts +1 -0
- package/dist/factories/clickhouse/resources/index.d.ts.map +1 -1
- package/dist/factories/clickhouse/resources/index.js +1 -0
- package/dist/factories/clickhouse/resources/index.js.map +1 -1
- package/dist/factories/clickhouse/resources/installation.d.ts.map +1 -1
- package/dist/factories/clickhouse/resources/installation.js +31 -4
- package/dist/factories/clickhouse/resources/installation.js.map +1 -1
- package/dist/factories/clickhouse/resources/s3-backup.d.ts +215 -0
- package/dist/factories/clickhouse/resources/s3-backup.d.ts.map +1 -0
- package/dist/factories/clickhouse/resources/s3-backup.js +410 -0
- package/dist/factories/clickhouse/resources/s3-backup.js.map +1 -0
- package/dist/factories/clickhouse/types.d.ts +416 -20
- package/dist/factories/clickhouse/types.d.ts.map +1 -1
- package/dist/factories/clickhouse/types.js +235 -11
- package/dist/factories/clickhouse/types.js.map +1 -1
- package/dist/factories/clickhouse/utils/helm-values-mapper.d.ts +42 -0
- package/dist/factories/clickhouse/utils/helm-values-mapper.d.ts.map +1 -1
- package/dist/factories/clickhouse/utils/helm-values-mapper.js +48 -0
- package/dist/factories/clickhouse/utils/helm-values-mapper.js.map +1 -1
- package/dist/factories/clickhouse/utils/index.d.ts +2 -0
- package/dist/factories/clickhouse/utils/index.d.ts.map +1 -1
- package/dist/factories/clickhouse/utils/index.js +2 -0
- package/dist/factories/clickhouse/utils/index.js.map +1 -1
- package/dist/factories/clickhouse/utils/s3-storage.d.ts +503 -0
- package/dist/factories/clickhouse/utils/s3-storage.d.ts.map +1 -0
- package/dist/factories/clickhouse/utils/s3-storage.js +1139 -0
- package/dist/factories/clickhouse/utils/s3-storage.js.map +1 -0
- package/dist/factories/clickhouse/utils/validation.d.ts +103 -0
- package/dist/factories/clickhouse/utils/validation.d.ts.map +1 -1
- package/dist/factories/clickhouse/utils/validation.js +129 -0
- package/dist/factories/clickhouse/utils/validation.js.map +1 -1
- package/dist/factories/clickhouse/utils/xml.d.ts +87 -0
- package/dist/factories/clickhouse/utils/xml.d.ts.map +1 -0
- package/dist/factories/clickhouse/utils/xml.js +151 -0
- package/dist/factories/clickhouse/utils/xml.js.map +1 -0
- package/dist/factories/clickstack/compositions/clickstack-bootstrap.d.ts +57 -0
- package/dist/factories/clickstack/compositions/clickstack-bootstrap.d.ts.map +1 -1
- package/dist/factories/clickstack/compositions/clickstack-bootstrap.js +266 -7
- package/dist/factories/clickstack/compositions/clickstack-bootstrap.js.map +1 -1
- package/dist/factories/clickstack/types.d.ts +205 -26
- package/dist/factories/clickstack/types.d.ts.map +1 -1
- package/dist/factories/clickstack/types.js +106 -8
- package/dist/factories/clickstack/types.js.map +1 -1
- package/dist/factories/clickstack/utils/collector-config.d.ts +104 -0
- package/dist/factories/clickstack/utils/collector-config.d.ts.map +1 -0
- package/dist/factories/clickstack/utils/collector-config.js +266 -0
- package/dist/factories/clickstack/utils/collector-config.js.map +1 -0
- package/dist/factories/clickstack/utils/helm-values-mapper.d.ts +26 -0
- package/dist/factories/clickstack/utils/helm-values-mapper.d.ts.map +1 -1
- package/dist/factories/clickstack/utils/helm-values-mapper.js +53 -12
- package/dist/factories/clickstack/utils/helm-values-mapper.js.map +1 -1
- package/dist/factories/clickstack/utils/index.d.ts +2 -0
- package/dist/factories/clickstack/utils/index.d.ts.map +1 -1
- package/dist/factories/clickstack/utils/index.js +2 -0
- package/dist/factories/clickstack/utils/index.js.map +1 -1
- package/dist/factories/clickstack/utils/storage.d.ts +449 -0
- package/dist/factories/clickstack/utils/storage.d.ts.map +1 -0
- package/dist/factories/clickstack/utils/storage.js +698 -0
- package/dist/factories/clickstack/utils/storage.js.map +1 -0
- package/dist/factories/cnpg/resources/helm.d.ts.map +1 -1
- package/dist/factories/cnpg/resources/helm.js +4 -4
- package/dist/factories/cnpg/resources/helm.js.map +1 -1
- package/dist/factories/cnpg/types.d.ts +10 -1
- package/dist/factories/cnpg/types.d.ts.map +1 -1
- package/dist/factories/cnpg/types.js.map +1 -1
- package/dist/factories/cnpg/utils/helm-values-mapper.d.ts +19 -2
- package/dist/factories/cnpg/utils/helm-values-mapper.d.ts.map +1 -1
- package/dist/factories/cnpg/utils/helm-values-mapper.js +22 -4
- package/dist/factories/cnpg/utils/helm-values-mapper.js.map +1 -1
- package/dist/factories/envoy-ai-gateway/compositions/gateway.d.ts.map +1 -1
- package/dist/factories/envoy-ai-gateway/compositions/gateway.js +16 -3
- package/dist/factories/envoy-ai-gateway/compositions/gateway.js.map +1 -1
- package/dist/factories/envoy-ai-gateway/constants.d.ts +5 -2
- package/dist/factories/envoy-ai-gateway/constants.d.ts.map +1 -1
- package/dist/factories/envoy-ai-gateway/constants.js +5 -2
- package/dist/factories/envoy-ai-gateway/constants.js.map +1 -1
- package/dist/factories/envoy-ai-gateway/resources/gateway.d.ts +12 -0
- package/dist/factories/envoy-ai-gateway/resources/gateway.d.ts.map +1 -1
- package/dist/factories/envoy-ai-gateway/resources/gateway.js +27 -104
- package/dist/factories/envoy-ai-gateway/resources/gateway.js.map +1 -1
- package/dist/factories/envoy-ai-gateway/types.d.ts +15 -47
- package/dist/factories/envoy-ai-gateway/types.d.ts.map +1 -1
- package/dist/factories/envoy-ai-gateway/types.js.map +1 -1
- package/dist/factories/gateway-api/constants.d.ts +27 -0
- package/dist/factories/gateway-api/constants.d.ts.map +1 -0
- package/dist/factories/gateway-api/constants.js +27 -0
- package/dist/factories/gateway-api/constants.js.map +1 -0
- package/dist/factories/gateway-api/index.d.ts +14 -0
- package/dist/factories/gateway-api/index.d.ts.map +1 -0
- package/dist/factories/gateway-api/index.js +14 -0
- package/dist/factories/gateway-api/index.js.map +1 -0
- package/dist/factories/gateway-api/readiness.d.ts +67 -0
- package/dist/factories/gateway-api/readiness.d.ts.map +1 -0
- package/dist/factories/gateway-api/readiness.js +213 -0
- package/dist/factories/gateway-api/readiness.js.map +1 -0
- package/dist/factories/gateway-api/resources/gateway.d.ts +91 -0
- package/dist/factories/gateway-api/resources/gateway.d.ts.map +1 -0
- package/dist/factories/gateway-api/resources/gateway.js +99 -0
- package/dist/factories/gateway-api/resources/gateway.js.map +1 -0
- package/dist/factories/gateway-api/resources/index.d.ts +2 -0
- package/dist/factories/gateway-api/resources/index.d.ts.map +1 -0
- package/dist/factories/gateway-api/resources/index.js +2 -0
- package/dist/factories/gateway-api/resources/index.js.map +1 -0
- package/dist/factories/gateway-api/types.d.ts +1269 -0
- package/dist/factories/gateway-api/types.d.ts.map +1 -0
- package/dist/factories/gateway-api/types.js +417 -0
- package/dist/factories/gateway-api/types.js.map +1 -0
- package/dist/factories/helm/readiness-evaluators.d.ts +21 -3
- package/dist/factories/helm/readiness-evaluators.d.ts.map +1 -1
- package/dist/factories/helm/readiness-evaluators.js +117 -11
- package/dist/factories/helm/readiness-evaluators.js.map +1 -1
- package/dist/factories/helm/types.d.ts +28 -0
- package/dist/factories/helm/types.d.ts.map +1 -1
- package/dist/factories/index.d.ts +2 -0
- package/dist/factories/index.d.ts.map +1 -1
- package/dist/factories/index.js +8 -0
- package/dist/factories/index.js.map +1 -1
- package/dist/factories/inngest/compositions/inngest-bootstrap.d.ts.map +1 -1
- package/dist/factories/inngest/compositions/inngest-bootstrap.js +10 -0
- package/dist/factories/inngest/compositions/inngest-bootstrap.js.map +1 -1
- package/dist/factories/kubernetes/admission/index.d.ts +2 -0
- package/dist/factories/kubernetes/admission/index.d.ts.map +1 -1
- package/dist/factories/kubernetes/admission/index.js +2 -0
- package/dist/factories/kubernetes/admission/index.js.map +1 -1
- package/dist/factories/kubernetes/admission/label-propagation-guard.d.ts +108 -0
- package/dist/factories/kubernetes/admission/label-propagation-guard.d.ts.map +1 -0
- package/dist/factories/kubernetes/admission/label-propagation-guard.js +247 -0
- package/dist/factories/kubernetes/admission/label-propagation-guard.js.map +1 -0
- package/dist/factories/kubernetes/admission/mutating-admission-policy.d.ts +286 -0
- package/dist/factories/kubernetes/admission/mutating-admission-policy.d.ts.map +1 -0
- package/dist/factories/kubernetes/admission/mutating-admission-policy.js +157 -0
- package/dist/factories/kubernetes/admission/mutating-admission-policy.js.map +1 -0
- package/dist/factories/opensearch/compositions/cluster.d.ts.map +1 -1
- package/dist/factories/opensearch/compositions/cluster.js +6 -1
- package/dist/factories/opensearch/compositions/cluster.js.map +1 -1
- package/dist/factories/ory/compositions/ory-identity-stack.d.ts +8 -8
- package/dist/factories/ory/types.d.ts +16 -16
- package/dist/factories/rook/compositions/object-storage-claim.d.ts +1 -1
- package/dist/factories/rook/compositions/rook-ceph-platform.js +8 -1
- package/dist/factories/rook/compositions/rook-ceph-platform.js.map +1 -1
- package/dist/factories/rook/types.d.ts +1 -1
- package/dist/factories/searxng/compositions/searxng-bootstrap.d.ts +1 -1
- package/dist/factories/searxng/compositions/searxng-bootstrap.d.ts.map +1 -1
- package/dist/factories/searxng/compositions/searxng-bootstrap.js +18 -13
- package/dist/factories/searxng/compositions/searxng-bootstrap.js.map +1 -1
- package/dist/factories/searxng/index.d.ts +3 -0
- package/dist/factories/searxng/index.d.ts.map +1 -1
- package/dist/factories/searxng/index.js +3 -0
- package/dist/factories/searxng/index.js.map +1 -1
- package/dist/factories/searxng/types.js +1 -1
- package/dist/factories/searxng/types.js.map +1 -1
- package/dist/factories/traefik/compositions/index.d.ts +6 -0
- package/dist/factories/traefik/compositions/index.d.ts.map +1 -0
- package/dist/factories/traefik/compositions/index.js +6 -0
- package/dist/factories/traefik/compositions/index.js.map +1 -0
- package/dist/factories/traefik/compositions/traefik-bootstrap.d.ts +185 -0
- package/dist/factories/traefik/compositions/traefik-bootstrap.d.ts.map +1 -0
- package/dist/factories/traefik/compositions/traefik-bootstrap.js +339 -0
- package/dist/factories/traefik/compositions/traefik-bootstrap.js.map +1 -0
- package/dist/factories/traefik/compositions/traefik-helm-repository.d.ts +16 -0
- package/dist/factories/traefik/compositions/traefik-helm-repository.d.ts.map +1 -0
- package/dist/factories/traefik/compositions/traefik-helm-repository.js +31 -0
- package/dist/factories/traefik/compositions/traefik-helm-repository.js.map +1 -0
- package/dist/factories/traefik/constants.d.ts +78 -0
- package/dist/factories/traefik/constants.d.ts.map +1 -0
- package/dist/factories/traefik/constants.js +104 -0
- package/dist/factories/traefik/constants.js.map +1 -0
- package/dist/factories/traefik/index.d.ts +25 -0
- package/dist/factories/traefik/index.d.ts.map +1 -0
- package/dist/factories/traefik/index.js +25 -0
- package/dist/factories/traefik/index.js.map +1 -0
- package/dist/factories/traefik/resources/common.d.ts +68 -0
- package/dist/factories/traefik/resources/common.d.ts.map +1 -0
- package/dist/factories/traefik/resources/common.js +59 -0
- package/dist/factories/traefik/resources/common.js.map +1 -0
- package/dist/factories/traefik/resources/gateway.d.ts +85 -0
- package/dist/factories/traefik/resources/gateway.d.ts.map +1 -0
- package/dist/factories/traefik/resources/gateway.js +109 -0
- package/dist/factories/traefik/resources/gateway.js.map +1 -0
- package/dist/factories/traefik/resources/helm.d.ts +56 -0
- package/dist/factories/traefik/resources/helm.d.ts.map +1 -0
- package/dist/factories/traefik/resources/helm.js +131 -0
- package/dist/factories/traefik/resources/helm.js.map +1 -0
- package/dist/factories/traefik/resources/index.d.ts +10 -0
- package/dist/factories/traefik/resources/index.d.ts.map +1 -0
- package/dist/factories/traefik/resources/index.js +10 -0
- package/dist/factories/traefik/resources/index.js.map +1 -0
- package/dist/factories/traefik/resources/middleware.d.ts +169 -0
- package/dist/factories/traefik/resources/middleware.d.ts.map +1 -0
- package/dist/factories/traefik/resources/middleware.js +225 -0
- package/dist/factories/traefik/resources/middleware.js.map +1 -0
- package/dist/factories/traefik/resources/routing.d.ts +113 -0
- package/dist/factories/traefik/resources/routing.d.ts.map +1 -0
- package/dist/factories/traefik/resources/routing.js +119 -0
- package/dist/factories/traefik/resources/routing.js.map +1 -0
- package/dist/factories/traefik/resources/tls.d.ts +85 -0
- package/dist/factories/traefik/resources/tls.d.ts.map +1 -0
- package/dist/factories/traefik/resources/tls.js +93 -0
- package/dist/factories/traefik/resources/tls.js.map +1 -0
- package/dist/factories/traefik/types.d.ts +2690 -0
- package/dist/factories/traefik/types.d.ts.map +1 -0
- package/dist/factories/traefik/types.js +1084 -0
- package/dist/factories/traefik/types.js.map +1 -0
- package/dist/factories/traefik/utils/helm-values-mapper.d.ts +198 -0
- package/dist/factories/traefik/utils/helm-values-mapper.d.ts.map +1 -0
- package/dist/factories/traefik/utils/helm-values-mapper.js +372 -0
- package/dist/factories/traefik/utils/helm-values-mapper.js.map +1 -0
- package/dist/factories/traefik/utils/index.d.ts +6 -0
- package/dist/factories/traefik/utils/index.d.ts.map +1 -0
- package/dist/factories/traefik/utils/index.js +6 -0
- package/dist/factories/traefik/utils/index.js.map +1 -0
- package/dist/factories/traefik/utils/middleware-validation.d.ts +42 -0
- package/dist/factories/traefik/utils/middleware-validation.d.ts.map +1 -0
- package/dist/factories/traefik/utils/middleware-validation.js +78 -0
- package/dist/factories/traefik/utils/middleware-validation.js.map +1 -0
- package/dist/factories/webapp/compositions/web-app-with-processing.d.ts.map +1 -1
- package/dist/factories/webapp/compositions/web-app-with-processing.js +10 -0
- package/dist/factories/webapp/compositions/web-app-with-processing.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/package.json +9 -1
|
@@ -0,0 +1,1084 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Traefik type definitions.
|
|
3
|
+
*
|
|
4
|
+
* **ArkType is the single source of truth.** Every configuration type in this
|
|
5
|
+
* file — the `traefik.io/v1alpha1` CRD specs, the middleware set, and the
|
|
6
|
+
* bootstrap composition's spec — is INFERRED from the ArkType schema declared
|
|
7
|
+
* next to it (`typeof XSchema.infer`), per `docs/advanced/integration-skill.md`
|
|
8
|
+
* Step 2. One declaration then validates at runtime, generates the KRO
|
|
9
|
+
* SimpleSchema, and types the factory, so the three cannot drift. Only STATUS
|
|
10
|
+
* types stay hand-written: they describe what a controller publishes rather
|
|
11
|
+
* than user input.
|
|
12
|
+
*
|
|
13
|
+
* Three layers live here:
|
|
14
|
+
*
|
|
15
|
+
* 1. **CRD spec schemas** — verified field-by-field against the
|
|
16
|
+
* `traefik.io/v1alpha1` CRDs shipped by chart 41.5.0 (Traefik v3.7.13), read
|
|
17
|
+
* back from a live API server with
|
|
18
|
+
* `kubectl get crd middlewares.traefik.io -o jsonpath='{.spec.versions[0].schema.openAPIV3Schema.properties.spec}'`.
|
|
19
|
+
* None of the Traefik CRDs has a `status` subresource, which is why the
|
|
20
|
+
* resource factories register an always-ready evaluator (see
|
|
21
|
+
* `resources/routing.ts`). Where a schema is stricter than the CRD it is
|
|
22
|
+
* deliberate and noted inline.
|
|
23
|
+
* 2. **Helm chart values** — {@link TraefikManagedHelmValues} is a CLOSED,
|
|
24
|
+
* precise description of the chart paths this factory maps, pins or reads
|
|
25
|
+
* back (verified against chart 41.5.0's `values.schema.json`). It carries no
|
|
26
|
+
* index signatures at any depth; {@link TraefikRawHelmValues} is the single,
|
|
27
|
+
* explicitly named raw-passthrough boundary for the rest of the chart.
|
|
28
|
+
* 3. **Bootstrap contract** — the runtime spec/status of the bootstrap
|
|
29
|
+
* composition. Following the ClickStack convention these carry only
|
|
30
|
+
* proxy-safe VALUES (names, namespaces, versions, ports, endpoints) that
|
|
31
|
+
* serialize cleanly as CEL refs in KRO mode. Choices that decide WHICH
|
|
32
|
+
* resources exist are build-time options on `makeTraefikBootstrap(...)`.
|
|
33
|
+
*
|
|
34
|
+
* @see https://doc.traefik.io/traefik/reference/routing-configuration/kubernetes/crd/
|
|
35
|
+
*/
|
|
36
|
+
import { type } from 'arktype';
|
|
37
|
+
import { deriveNameLengthLimit, DNS_LABEL_MAX_LENGTH, DNS_SUBDOMAIN_MAX_LENGTH, HELM_RELEASE_NAME_MAX_LENGTH, } from '../../core/kubernetes/naming.js';
|
|
38
|
+
import { gatewayApiClusterResourceMetadataShape } from '../gateway-api/types.js';
|
|
39
|
+
import { validateTraefikMiddlewareSpec } from './utils/middleware-validation.js';
|
|
40
|
+
/**
|
|
41
|
+
* Every Kubernetes name this factory derives from the `name` a caller supplies.
|
|
42
|
+
*
|
|
43
|
+
* The name is not used once: it names the Flux `HelmRelease` and is pinned as
|
|
44
|
+
* that release's `spec.releaseName`, it is pinned as the chart's
|
|
45
|
+
* `fullnameOverride` (so it
|
|
46
|
+
* names the ServiceAccount, RBAC, Deployment, IngressClass and the chart's own
|
|
47
|
+
* Services), and it names the entrypoint `Service` this factory owns. Each of
|
|
48
|
+
* those has a limit, and several of them append a suffix first — so the bound
|
|
49
|
+
* on `name` is whichever derived name runs out of room first, which is what
|
|
50
|
+
* {@link deriveNameLengthLimit} computes.
|
|
51
|
+
*
|
|
52
|
+
* Suffixes read off chart 41.5.0's templates rather than guessed; the chart
|
|
53
|
+
* itself carries the `-udp` case as a hard `len(fullname) < 60` check in
|
|
54
|
+
* `templates/_service.tpl`.
|
|
55
|
+
*
|
|
56
|
+
* Only names that a long `name` can actually make FAIL are listed, and each is
|
|
57
|
+
* held to the limit its own object kind is validated against:
|
|
58
|
+
*
|
|
59
|
+
* - **Services** (`<name>`, `<name>-udp`, `<name>-metrics`) are the real
|
|
60
|
+
* constraints. A Service name is an RFC 1035 label, capped at 63 characters,
|
|
61
|
+
* because it has to be resolvable as the first label of a cluster DNS name.
|
|
62
|
+
* - **The file-provider ConfigMap** is held to the DNS SUBDOMAIN limit, not the
|
|
63
|
+
* label limit: `metadata.name` on a ConfigMap is validated as a DNS
|
|
64
|
+
* subdomain (253). The same is true of the Deployment, ServiceAccount, RBAC
|
|
65
|
+
* and IngressClass the chart names from `fullnameOverride`, which is why
|
|
66
|
+
* none of them appears here — at 253 they cannot bind before the Services do.
|
|
67
|
+
* - **Pods are deliberately absent.** A Traefik Pod is named by the
|
|
68
|
+
* API server through `metadata.generateName`, and the generator truncates
|
|
69
|
+
* the base to `MaxGeneratedNameLength = 63 - 5` before appending its random
|
|
70
|
+
* suffix (`staging/src/k8s.io/apiserver/pkg/storage/names/generate.go` in
|
|
71
|
+
* kubernetes/kubernetes), so a generated Pod name can never exceed 63 and
|
|
72
|
+
* never fails on a long prefix. Reserving for one only rejected names that
|
|
73
|
+
* would have deployed fine. The truncation is not a functional concern
|
|
74
|
+
* either: nothing in this factory — or in Traefik — addresses a Pod by its
|
|
75
|
+
* hostname. The entrypoint Service selects Pods by the pinned
|
|
76
|
+
* `app.kubernetes.io/name` / `app.kubernetes.io/instance` labels, and there
|
|
77
|
+
* is no headless Service or `subdomain` giving these Pods per-Pod DNS.
|
|
78
|
+
*
|
|
79
|
+
* The Helm release name is the binding constraint, at Helm's own 53, and that
|
|
80
|
+
* 53 binds on `name` alone: `traefikHelmRelease` pins `spec.releaseName` to
|
|
81
|
+
* `name`, so the release name IS `name`. Left unset, Flux's
|
|
82
|
+
* `GetReleaseName()` would compose `<targetNamespace>-<name>` — this factory
|
|
83
|
+
* always sets `targetNamespace` — and the install namespace would eat into the
|
|
84
|
+
* 53, a term this derivation cannot express because the namespace is a runtime
|
|
85
|
+
* spec field (and a CEL reference in KRO mode) rather than something known when
|
|
86
|
+
* the schema is built.
|
|
87
|
+
*/
|
|
88
|
+
const TRAEFIK_GENERATED_NAMES = [
|
|
89
|
+
{
|
|
90
|
+
describedAs: "the HelmRelease's Helm release name",
|
|
91
|
+
limit: HELM_RELEASE_NAME_MAX_LENGTH,
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
describedAs: 'the entrypoint Service `<name>`',
|
|
95
|
+
limit: DNS_LABEL_MAX_LENGTH,
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
describedAs: "the chart's UDP Service `<name>-udp`",
|
|
99
|
+
suffix: '-udp',
|
|
100
|
+
limit: DNS_LABEL_MAX_LENGTH,
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
describedAs: "the chart's metrics Service `<name>-metrics`",
|
|
104
|
+
suffix: '-metrics',
|
|
105
|
+
limit: DNS_LABEL_MAX_LENGTH,
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
describedAs: "the chart's file-provider ConfigMap `<name>-file-provider`",
|
|
109
|
+
suffix: '-file-provider',
|
|
110
|
+
limit: DNS_SUBDOMAIN_MAX_LENGTH,
|
|
111
|
+
},
|
|
112
|
+
];
|
|
113
|
+
/**
|
|
114
|
+
* Longest `name` this factory accepts, derived from {@link TRAEFIK_GENERATED_NAMES}.
|
|
115
|
+
*
|
|
116
|
+
* Exported so the schema test can assert the derivation rather than a number
|
|
117
|
+
* copied out of it.
|
|
118
|
+
*/
|
|
119
|
+
export const TRAEFIK_NAME_LIMIT = deriveNameLengthLimit(TRAEFIK_GENERATED_NAMES);
|
|
120
|
+
const kubernetesName = type(/^[a-z0-9](?:[-a-z0-9]*[a-z0-9])?$/).and(
|
|
121
|
+
// `.configure` on the length constraint alone, so a name that violates the
|
|
122
|
+
// PATTERN still reports the pattern. The constraint itself stays a plain
|
|
123
|
+
// `maxLength` in the ArkType AST, which is what KRO SimpleSchema serializes.
|
|
124
|
+
type.string
|
|
125
|
+
.atMostLength(TRAEFIK_NAME_LIMIT.maxLength)
|
|
126
|
+
.configure({ message: TRAEFIK_NAME_LIMIT.message }));
|
|
127
|
+
/** A namespace or other DNS-1123 label: the RFC's own 63-character limit. */
|
|
128
|
+
const kubernetesDnsLabel = type(/^[a-z0-9](?:[-a-z0-9]*[a-z0-9])?$/).and('string <= 63');
|
|
129
|
+
/** A published port. Bounded as the Service/container port range, 1-65535. */
|
|
130
|
+
const kubernetesPort = '1 <= number.integer <= 65535';
|
|
131
|
+
// ============================================================================
|
|
132
|
+
// Shared primitives
|
|
133
|
+
// ============================================================================
|
|
134
|
+
/**
|
|
135
|
+
* ArkType definition of a Traefik duration.
|
|
136
|
+
*
|
|
137
|
+
* The CRDs accept an integer (nanoseconds) or a Go duration string such as
|
|
138
|
+
* `'90s'`; prefer the string form for readability.
|
|
139
|
+
*
|
|
140
|
+
* The numeric branch is `number.integer`, not a bare `number`: these are
|
|
141
|
+
* `x-kubernetes-int-or-string` fields whose integer branch the API server
|
|
142
|
+
* enforces, so `interval: 1.5` is rejected at admission. KRO SimpleSchema
|
|
143
|
+
* collapses a union to `object`, so ArkType is where that integrality is
|
|
144
|
+
* caught — which is why it has to be declared here.
|
|
145
|
+
*/
|
|
146
|
+
const traefikDuration = 'string | number.integer';
|
|
147
|
+
/**
|
|
148
|
+
* ArkType definition of a Traefik service port: a port number or a named port.
|
|
149
|
+
*
|
|
150
|
+
* Structurally identical to {@link traefikDuration} — both are
|
|
151
|
+
* `x-kubernetes-int-or-string` with an integral numeric branch — but named
|
|
152
|
+
* apart because a port and a duration are not interchangeable to a reader.
|
|
153
|
+
*/
|
|
154
|
+
const traefikPortValue = 'string | number.integer';
|
|
155
|
+
/** How Traefik derives the client IP from proxy headers. */
|
|
156
|
+
export const TraefikIpStrategySchema = type({
|
|
157
|
+
/** Depth position in `X-Forwarded-For`, counted from the right. */
|
|
158
|
+
'depth?': 'number.integer >= 0',
|
|
159
|
+
'excludedIPs?': 'string[]',
|
|
160
|
+
/** Group IPv6 clients into a shared subnet before keying. */
|
|
161
|
+
'ipv6Subnet?': 'number.integer',
|
|
162
|
+
});
|
|
163
|
+
/**
|
|
164
|
+
* What a `rateLimit` / `inFlightReq` middleware keys its counters on.
|
|
165
|
+
*
|
|
166
|
+
* Exactly one of these should be set; Traefik falls back to the client IP when
|
|
167
|
+
* none is given.
|
|
168
|
+
*/
|
|
169
|
+
export const TraefikSourceCriterionSchema = type({
|
|
170
|
+
/** Key on a request header, e.g. the principal emitted by `forwardAuth`. */
|
|
171
|
+
'requestHeaderName?': 'string',
|
|
172
|
+
'requestHost?': 'boolean',
|
|
173
|
+
'ipStrategy?': TraefikIpStrategySchema,
|
|
174
|
+
});
|
|
175
|
+
/** Sticky-session cookie configuration for a load-balanced service. */
|
|
176
|
+
export const TraefikStickyCookieSchema = type({
|
|
177
|
+
'cookie?': {
|
|
178
|
+
'name?': 'string',
|
|
179
|
+
'secure?': 'boolean',
|
|
180
|
+
'httpOnly?': 'boolean',
|
|
181
|
+
'sameSite?': '"none" | "lax" | "strict" | "None" | "Lax" | "Strict"',
|
|
182
|
+
'maxAge?': 'number.integer',
|
|
183
|
+
'path?': 'string',
|
|
184
|
+
'domain?': 'string',
|
|
185
|
+
},
|
|
186
|
+
});
|
|
187
|
+
/**
|
|
188
|
+
* Active health check performed by Traefik against a service's servers.
|
|
189
|
+
*
|
|
190
|
+
* The CRD spells the Host override `hostname`; there is no `host` field.
|
|
191
|
+
*/
|
|
192
|
+
export const TraefikHealthCheckSchema = type({
|
|
193
|
+
'path?': 'string',
|
|
194
|
+
'hostname?': 'string',
|
|
195
|
+
'scheme?': 'string',
|
|
196
|
+
'mode?': 'string',
|
|
197
|
+
'method?': 'string',
|
|
198
|
+
'status?': 'number.integer',
|
|
199
|
+
'port?': 'number.integer',
|
|
200
|
+
'interval?': traefikDuration,
|
|
201
|
+
'unhealthyInterval?': traefikDuration,
|
|
202
|
+
'timeout?': traefikDuration,
|
|
203
|
+
'headers?': 'Record<string, string>',
|
|
204
|
+
'followRedirects?': 'boolean',
|
|
205
|
+
});
|
|
206
|
+
/** A reference to a `Middleware` resource. */
|
|
207
|
+
export const TraefikMiddlewareRefSchema = type({
|
|
208
|
+
name: 'string',
|
|
209
|
+
'namespace?': 'string',
|
|
210
|
+
});
|
|
211
|
+
/** ArkType definition of the load-balancing strategies the CRD enumerates. */
|
|
212
|
+
const traefikLoadBalancerStrategy = '"wrr" | "p2c" | "hrw" | "leasttime" | "RoundRobin"';
|
|
213
|
+
/** One backend of an `IngressRoute` route or a `TraefikService`. */
|
|
214
|
+
export const TraefikServiceRefSchema = type({
|
|
215
|
+
name: 'string',
|
|
216
|
+
'namespace?': 'string',
|
|
217
|
+
'kind?': '"Service" | "TraefikService"',
|
|
218
|
+
/** Port number or named port — the CRD accepts either. */
|
|
219
|
+
'port?': traefikPortValue,
|
|
220
|
+
'scheme?': 'string',
|
|
221
|
+
'weight?': 'number.integer >= 0',
|
|
222
|
+
'strategy?': traefikLoadBalancerStrategy,
|
|
223
|
+
'passHostHeader?': 'boolean',
|
|
224
|
+
'nativeLB?': 'boolean',
|
|
225
|
+
'nodePortLB?': 'boolean',
|
|
226
|
+
'serversTransport?': 'string',
|
|
227
|
+
'sticky?': TraefikStickyCookieSchema,
|
|
228
|
+
'healthCheck?': TraefikHealthCheckSchema,
|
|
229
|
+
'passiveHealthCheck?': {
|
|
230
|
+
'failureWindow?': traefikDuration,
|
|
231
|
+
'maxFailedAttempts?': 'number.integer',
|
|
232
|
+
},
|
|
233
|
+
'responseForwarding?': { 'flushInterval?': 'string' },
|
|
234
|
+
'middlewares?': TraefikMiddlewareRefSchema.array(),
|
|
235
|
+
});
|
|
236
|
+
/** TLS configuration attached to a router. */
|
|
237
|
+
export const TraefikRouterTLSSchema = type({
|
|
238
|
+
/** Secret holding the certificate, e.g. one written by cert-manager. */
|
|
239
|
+
'secretName?': 'string',
|
|
240
|
+
'options?': { name: 'string', 'namespace?': 'string' },
|
|
241
|
+
'store?': { name: 'string', 'namespace?': 'string' },
|
|
242
|
+
'certResolver?': 'string',
|
|
243
|
+
'domains?': type({
|
|
244
|
+
'main?': 'string',
|
|
245
|
+
'sans?': 'string[]',
|
|
246
|
+
}).array(),
|
|
247
|
+
});
|
|
248
|
+
// ============================================================================
|
|
249
|
+
// IngressRoute / IngressRouteTCP
|
|
250
|
+
// ============================================================================
|
|
251
|
+
/** Per-route observability overrides. */
|
|
252
|
+
export const TraefikRouteObservabilitySchema = type({
|
|
253
|
+
'accessLogs?': 'boolean',
|
|
254
|
+
'metrics?': 'boolean',
|
|
255
|
+
'tracing?': 'boolean',
|
|
256
|
+
'traceVerbosity?': '"minimal" | "detailed"',
|
|
257
|
+
});
|
|
258
|
+
/** One `IngressRoute.spec.routes[]` entry. */
|
|
259
|
+
export const TraefikIngressRouteRuleSchema = type({
|
|
260
|
+
/** Traefik v3 rule expression, e.g. ``Host(`api.example.com`)``. */
|
|
261
|
+
match: 'string',
|
|
262
|
+
'kind?': '"Rule"',
|
|
263
|
+
/** Higher priority wins; Traefik defaults to the rule length. */
|
|
264
|
+
'priority?': 'number.integer',
|
|
265
|
+
'syntax?': 'string',
|
|
266
|
+
'services?': TraefikServiceRefSchema.array(),
|
|
267
|
+
'middlewares?': TraefikMiddlewareRefSchema.array(),
|
|
268
|
+
'observability?': TraefikRouteObservabilitySchema,
|
|
269
|
+
});
|
|
270
|
+
/** `IngressRoute.spec`. */
|
|
271
|
+
export const TraefikIngressRouteSpecSchema = type({
|
|
272
|
+
routes: TraefikIngressRouteRuleSchema.array(),
|
|
273
|
+
'entryPoints?': 'string[]',
|
|
274
|
+
'ingressClassName?': 'string',
|
|
275
|
+
'tls?': TraefikRouterTLSSchema,
|
|
276
|
+
'parentRefs?': type({ name: 'string', 'namespace?': 'string' }).array(),
|
|
277
|
+
});
|
|
278
|
+
/** One backend of an `IngressRouteTCP` route. */
|
|
279
|
+
export const TraefikTCPServiceRefSchema = type({
|
|
280
|
+
name: 'string',
|
|
281
|
+
port: traefikPortValue,
|
|
282
|
+
'namespace?': 'string',
|
|
283
|
+
'weight?': 'number.integer >= 0',
|
|
284
|
+
'tls?': 'boolean',
|
|
285
|
+
'nativeLB?': 'boolean',
|
|
286
|
+
'nodePortLB?': 'boolean',
|
|
287
|
+
'serversTransport?': 'string',
|
|
288
|
+
/** PROXY protocol version. The CRD admits only 1 or 2. */
|
|
289
|
+
'proxyProtocol?': { 'version?': '1 <= number.integer <= 2' },
|
|
290
|
+
});
|
|
291
|
+
/** One `IngressRouteTCP.spec.routes[]` entry. */
|
|
292
|
+
export const TraefikIngressRouteTCPRuleSchema = type({
|
|
293
|
+
/** TCP rule expression, e.g. ``HostSNI(`db.example.com`)``. */
|
|
294
|
+
match: 'string',
|
|
295
|
+
'priority?': 'number.integer',
|
|
296
|
+
'syntax?': '"v3" | "v2"',
|
|
297
|
+
'services?': TraefikTCPServiceRefSchema.array(),
|
|
298
|
+
'middlewares?': TraefikMiddlewareRefSchema.array(),
|
|
299
|
+
});
|
|
300
|
+
/** `IngressRouteTCP.spec`. */
|
|
301
|
+
export const TraefikIngressRouteTCPSpecSchema = type({
|
|
302
|
+
routes: TraefikIngressRouteTCPRuleSchema.array(),
|
|
303
|
+
'entryPoints?': 'string[]',
|
|
304
|
+
'ingressClassName?': 'string',
|
|
305
|
+
'tls?': TraefikRouterTLSSchema.and({ 'passthrough?': 'boolean' }),
|
|
306
|
+
});
|
|
307
|
+
// ============================================================================
|
|
308
|
+
// TraefikService / ServersTransport
|
|
309
|
+
// ============================================================================
|
|
310
|
+
/**
|
|
311
|
+
* `TraefikService.spec` — exactly one composition mode should be set.
|
|
312
|
+
*
|
|
313
|
+
* `failover.errors` is required because the CRD requires it alongside
|
|
314
|
+
* `service` and `fallback`.
|
|
315
|
+
*/
|
|
316
|
+
export const TraefikServiceSpecSchema = type({
|
|
317
|
+
'weighted?': {
|
|
318
|
+
'services?': TraefikServiceRefSchema.array(),
|
|
319
|
+
'sticky?': TraefikStickyCookieSchema,
|
|
320
|
+
},
|
|
321
|
+
'mirroring?': TraefikServiceRefSchema.and({
|
|
322
|
+
'maxBodySize?': 'number.integer',
|
|
323
|
+
'mirrorBody?': 'boolean',
|
|
324
|
+
'mirrors?': TraefikServiceRefSchema.and({ 'percent?': 'number.integer' }).array(),
|
|
325
|
+
}),
|
|
326
|
+
'failover?': {
|
|
327
|
+
service: TraefikServiceRefSchema,
|
|
328
|
+
fallback: TraefikServiceRefSchema,
|
|
329
|
+
errors: {
|
|
330
|
+
'status?': 'string[]',
|
|
331
|
+
'maxRequestBodyBytes?': 'number.integer',
|
|
332
|
+
},
|
|
333
|
+
},
|
|
334
|
+
'highestRandomWeight?': {
|
|
335
|
+
'services?': TraefikServiceRefSchema.array(),
|
|
336
|
+
},
|
|
337
|
+
});
|
|
338
|
+
/** `ServersTransport.spec` — how Traefik dials upstream servers. */
|
|
339
|
+
export const TraefikServersTransportSpecSchema = type({
|
|
340
|
+
'serverName?': 'string',
|
|
341
|
+
'insecureSkipVerify?': 'boolean',
|
|
342
|
+
'rootCAsSecrets?': 'string[]',
|
|
343
|
+
'rootCAs?': type({
|
|
344
|
+
'secret?': 'string',
|
|
345
|
+
'configMap?': 'string',
|
|
346
|
+
}).array(),
|
|
347
|
+
'certificatesSecrets?': 'string[]',
|
|
348
|
+
/** `-1` disables the pool; the CRD's own minimum. */
|
|
349
|
+
'maxIdleConnsPerHost?': 'number.integer >= -1',
|
|
350
|
+
'disableHTTP2?': 'boolean',
|
|
351
|
+
'peerCertURI?': 'string',
|
|
352
|
+
'minVersion?': 'string',
|
|
353
|
+
'maxVersion?': 'string',
|
|
354
|
+
'cipherSuites?': 'string[]',
|
|
355
|
+
'spiffe?': {
|
|
356
|
+
'ids?': 'string[]',
|
|
357
|
+
'trustDomain?': 'string',
|
|
358
|
+
},
|
|
359
|
+
/**
|
|
360
|
+
* Upstream timeouts. An edge fronting long-running requests must raise
|
|
361
|
+
* `responseHeaderTimeout` above the default 60s alongside the entrypoint's
|
|
362
|
+
* `respondingTimeouts`.
|
|
363
|
+
*/
|
|
364
|
+
'forwardingTimeouts?': {
|
|
365
|
+
'dialTimeout?': traefikDuration,
|
|
366
|
+
'responseHeaderTimeout?': traefikDuration,
|
|
367
|
+
'idleConnTimeout?': traefikDuration,
|
|
368
|
+
'readIdleTimeout?': traefikDuration,
|
|
369
|
+
'pingTimeout?': traefikDuration,
|
|
370
|
+
},
|
|
371
|
+
});
|
|
372
|
+
// ============================================================================
|
|
373
|
+
// TLSOption / TLSStore
|
|
374
|
+
// ============================================================================
|
|
375
|
+
/** Mutual-TLS behavior of a `TLSOption`. */
|
|
376
|
+
export const TraefikClientAuthSchema = type({
|
|
377
|
+
'secretNames?': 'string[]',
|
|
378
|
+
'clientAuthType?': '"NoClientCert" | "RequestClientCert" | "RequireAnyClientCert" | "VerifyClientCertIfGiven" | "RequireAndVerifyClientCert"',
|
|
379
|
+
});
|
|
380
|
+
/**
|
|
381
|
+
* `TLSOption.spec`.
|
|
382
|
+
*
|
|
383
|
+
* `minVersion`/`maxVersion` are narrower than the CRD's bare string: those four
|
|
384
|
+
* are the values Traefik accepts, so a typo is caught here instead of by the
|
|
385
|
+
* proxy at runtime. The CRD's deprecated `preferServerCipherSuites` is
|
|
386
|
+
* deliberately absent — Traefik v3 ignores it.
|
|
387
|
+
*/
|
|
388
|
+
export const TraefikTLSOptionSpecSchema = type({
|
|
389
|
+
'minVersion?': '"VersionTLS10" | "VersionTLS11" | "VersionTLS12" | "VersionTLS13"',
|
|
390
|
+
'maxVersion?': '"VersionTLS10" | "VersionTLS11" | "VersionTLS12" | "VersionTLS13"',
|
|
391
|
+
'cipherSuites?': 'string[]',
|
|
392
|
+
'curvePreferences?': 'string[]',
|
|
393
|
+
/** Reject connections whose SNI does not match a configured certificate. */
|
|
394
|
+
'sniStrict?': 'boolean',
|
|
395
|
+
'alpnProtocols?': 'string[]',
|
|
396
|
+
'disableSessionTickets?': 'boolean',
|
|
397
|
+
'clientAuth?': TraefikClientAuthSchema,
|
|
398
|
+
});
|
|
399
|
+
/** `TLSStore.spec`. */
|
|
400
|
+
export const TraefikTLSStoreSpecSchema = type({
|
|
401
|
+
/**
|
|
402
|
+
* Default certificate served when SNI matches no router certificate. Point
|
|
403
|
+
* this at the Secret a cert-manager `Certificate` writes.
|
|
404
|
+
*/
|
|
405
|
+
'defaultCertificate?': { secretName: 'string' },
|
|
406
|
+
/** ACME resolver used to generate the default certificate instead. */
|
|
407
|
+
'defaultGeneratedCert?': {
|
|
408
|
+
'resolver?': 'string',
|
|
409
|
+
'domain?': {
|
|
410
|
+
'main?': 'string',
|
|
411
|
+
'sans?': 'string[]',
|
|
412
|
+
},
|
|
413
|
+
},
|
|
414
|
+
'certificates?': type({ secretName: 'string' }).array(),
|
|
415
|
+
});
|
|
416
|
+
// ============================================================================
|
|
417
|
+
// Middleware — the OSS middleware set as a discriminated union
|
|
418
|
+
// ============================================================================
|
|
419
|
+
/** TLS client config shared by `forwardAuth` and the `rateLimit` Redis backend. */
|
|
420
|
+
const middlewareClientTlsShape = {
|
|
421
|
+
'caSecret?': 'string',
|
|
422
|
+
'certSecret?': 'string',
|
|
423
|
+
'insecureSkipVerify?': 'boolean',
|
|
424
|
+
};
|
|
425
|
+
/**
|
|
426
|
+
* Delegate authentication and authorization to an in-cluster authorizer.
|
|
427
|
+
*
|
|
428
|
+
* `address` is required although the CRD allows it to be absent: a
|
|
429
|
+
* `forwardAuth` with no authorizer fails every request.
|
|
430
|
+
*
|
|
431
|
+
* @security `trustForwardHeader` defaults to `false` in
|
|
432
|
+
* {@link TRAEFIK_FORWARD_AUTH_SECURE_DEFAULTS}: trusting `X-Forwarded-*` from
|
|
433
|
+
* an untrusted client lets a caller spoof its own identity. `authResponseHeaders`
|
|
434
|
+
* is an explicit allowlist — only the listed headers are copied from the
|
|
435
|
+
* authorizer response onto the upstream request.
|
|
436
|
+
*/
|
|
437
|
+
export const TraefikForwardAuthMiddlewareSchema = type({
|
|
438
|
+
/** URL of the authorizer, e.g. `http://authorizer.edge.svc.cluster.local:8080/auth`. */
|
|
439
|
+
address: 'string',
|
|
440
|
+
/** Copy `X-Forwarded-*` from the client to the authorizer. Keep `false` at an edge. */
|
|
441
|
+
'trustForwardHeader?': 'boolean',
|
|
442
|
+
/** Headers copied from the authorizer's response onto the upstream request. */
|
|
443
|
+
'authResponseHeaders?': 'string[]',
|
|
444
|
+
/** Regex alternative to `authResponseHeaders`. Prefer the explicit list. */
|
|
445
|
+
'authResponseHeadersRegex?': 'string',
|
|
446
|
+
/** Client headers forwarded to the authorizer. Empty means all of them. */
|
|
447
|
+
'authRequestHeaders?': 'string[]',
|
|
448
|
+
'addAuthCookiesToResponse?': 'string[]',
|
|
449
|
+
'authSigninURL?': 'string',
|
|
450
|
+
'forwardBody?': 'boolean',
|
|
451
|
+
'maxBodySize?': 'number.integer',
|
|
452
|
+
'maxResponseBodySize?': 'number.integer',
|
|
453
|
+
'headerField?': 'string',
|
|
454
|
+
'preserveLocationHeader?': 'boolean',
|
|
455
|
+
'preserveRequestMethod?': 'boolean',
|
|
456
|
+
'tls?': middlewareClientTlsShape,
|
|
457
|
+
});
|
|
458
|
+
/** Redis (or Valkey) backend making a rate limit shared across Traefik replicas. */
|
|
459
|
+
export const TraefikRateLimitRedisSchema = type({
|
|
460
|
+
endpoints: 'string[]',
|
|
461
|
+
/** Secret holding `username` / `password` keys. */
|
|
462
|
+
'secret?': 'string',
|
|
463
|
+
'db?': 'number.integer',
|
|
464
|
+
'poolSize?': 'number.integer',
|
|
465
|
+
'minIdleConns?': 'number.integer',
|
|
466
|
+
'maxActiveConns?': 'number.integer',
|
|
467
|
+
'dialTimeout?': traefikDuration,
|
|
468
|
+
'readTimeout?': traefikDuration,
|
|
469
|
+
'writeTimeout?': traefikDuration,
|
|
470
|
+
'tls?': middlewareClientTlsShape,
|
|
471
|
+
});
|
|
472
|
+
/**
|
|
473
|
+
* Token-bucket rate limit.
|
|
474
|
+
*
|
|
475
|
+
* Without `redis` each Traefik replica keeps its own counters, so the effective
|
|
476
|
+
* limit is `average × replicas`. Supply the Redis backend whenever the budget
|
|
477
|
+
* must hold for the whole edge.
|
|
478
|
+
*/
|
|
479
|
+
export const TraefikRateLimitMiddlewareSchema = type({
|
|
480
|
+
/** Sustained requests allowed per `period`. */
|
|
481
|
+
'average?': 'number.integer >= 0',
|
|
482
|
+
/** Requests absorbed above `average` before Traefik answers 429. */
|
|
483
|
+
'burst?': 'number.integer >= 0',
|
|
484
|
+
/** Window `average` is measured over. Defaults to one second. */
|
|
485
|
+
'period?': traefikDuration,
|
|
486
|
+
'sourceCriterion?': TraefikSourceCriterionSchema,
|
|
487
|
+
'redis?': TraefikRateLimitRedisSchema,
|
|
488
|
+
});
|
|
489
|
+
/** Cap on requests being handled concurrently, per source. */
|
|
490
|
+
export const TraefikInFlightReqMiddlewareSchema = type({
|
|
491
|
+
'amount?': 'number.integer >= 0',
|
|
492
|
+
'sourceCriterion?': TraefikSourceCriterionSchema,
|
|
493
|
+
});
|
|
494
|
+
/**
|
|
495
|
+
* CORS and browser security headers.
|
|
496
|
+
*
|
|
497
|
+
* The CRD's `sslRedirect`, `sslTemporaryRedirect`, `sslHost` and `sslForceHost`
|
|
498
|
+
* are deliberately absent: Traefik v3 dropped them in favour of the
|
|
499
|
+
* `redirectScheme` middleware, and the CRD keeps them only for v2 manifests.
|
|
500
|
+
*/
|
|
501
|
+
export const TraefikHeadersMiddlewareSchema = type({
|
|
502
|
+
'customRequestHeaders?': 'Record<string, string>',
|
|
503
|
+
'customResponseHeaders?': 'Record<string, string>',
|
|
504
|
+
'accessControlAllowCredentials?': 'boolean',
|
|
505
|
+
'accessControlAllowHeaders?': 'string[]',
|
|
506
|
+
'accessControlAllowMethods?': 'string[]',
|
|
507
|
+
'accessControlAllowOriginList?': 'string[]',
|
|
508
|
+
'accessControlAllowOriginListRegex?': 'string[]',
|
|
509
|
+
'accessControlExposeHeaders?': 'string[]',
|
|
510
|
+
'accessControlMaxAge?': 'number.integer',
|
|
511
|
+
'addVaryHeader?': 'boolean',
|
|
512
|
+
'allowedHosts?': 'string[]',
|
|
513
|
+
'hostsProxyHeaders?': 'string[]',
|
|
514
|
+
'sslProxyHeaders?': 'Record<string, string>',
|
|
515
|
+
'stsSeconds?': 'number.integer >= 0',
|
|
516
|
+
'stsIncludeSubdomains?': 'boolean',
|
|
517
|
+
'stsPreload?': 'boolean',
|
|
518
|
+
'forceSTSHeader?': 'boolean',
|
|
519
|
+
'frameDeny?': 'boolean',
|
|
520
|
+
'customFrameOptionsValue?': 'string',
|
|
521
|
+
'contentTypeNosniff?': 'boolean',
|
|
522
|
+
'browserXssFilter?': 'boolean',
|
|
523
|
+
'customBrowserXSSValue?': 'string',
|
|
524
|
+
'contentSecurityPolicy?': 'string',
|
|
525
|
+
'contentSecurityPolicyReportOnly?': 'string',
|
|
526
|
+
'publicKey?': 'string',
|
|
527
|
+
'referrerPolicy?': 'string',
|
|
528
|
+
'permissionsPolicy?': 'string',
|
|
529
|
+
'featurePolicy?': 'string',
|
|
530
|
+
/** Relaxes header enforcement for local development. Never enable in production. */
|
|
531
|
+
'isDevelopment?': 'boolean',
|
|
532
|
+
});
|
|
533
|
+
/** Redirect a request to another scheme, e.g. `web` → `websecure`. */
|
|
534
|
+
export const TraefikRedirectSchemeMiddlewareSchema = type({
|
|
535
|
+
scheme: '"http" | "https"',
|
|
536
|
+
'port?': 'string',
|
|
537
|
+
'permanent?': 'boolean',
|
|
538
|
+
});
|
|
539
|
+
/** Regex-based redirect. */
|
|
540
|
+
export const TraefikRedirectRegexMiddlewareSchema = type({
|
|
541
|
+
regex: 'string',
|
|
542
|
+
replacement: 'string',
|
|
543
|
+
'permanent?': 'boolean',
|
|
544
|
+
});
|
|
545
|
+
/** Remove one of `prefixes` from the request path before forwarding. */
|
|
546
|
+
export const TraefikStripPrefixMiddlewareSchema = type({
|
|
547
|
+
prefixes: 'string[]',
|
|
548
|
+
'forceSlash?': 'boolean',
|
|
549
|
+
});
|
|
550
|
+
/** Remove a regex-matched prefix from the request path. */
|
|
551
|
+
export const TraefikStripPrefixRegexMiddlewareSchema = type({
|
|
552
|
+
regex: 'string[]',
|
|
553
|
+
});
|
|
554
|
+
/** Prepend a prefix to the request path. */
|
|
555
|
+
export const TraefikAddPrefixMiddlewareSchema = type({
|
|
556
|
+
prefix: 'string',
|
|
557
|
+
});
|
|
558
|
+
/** Replace the whole request path. */
|
|
559
|
+
export const TraefikReplacePathMiddlewareSchema = type({
|
|
560
|
+
path: 'string',
|
|
561
|
+
});
|
|
562
|
+
/** Replace a regex-matched request path. */
|
|
563
|
+
export const TraefikReplacePathRegexMiddlewareSchema = type({
|
|
564
|
+
regex: 'string',
|
|
565
|
+
replacement: 'string',
|
|
566
|
+
});
|
|
567
|
+
/**
|
|
568
|
+
* Body buffering and size limits.
|
|
569
|
+
*
|
|
570
|
+
* `maxRequestBodyBytes` is the request-size cap an edge needs so an upstream
|
|
571
|
+
* cannot be flooded; a `retryExpression` requires buffering to be able to
|
|
572
|
+
* replay the body.
|
|
573
|
+
*/
|
|
574
|
+
export const TraefikBufferingMiddlewareSchema = type({
|
|
575
|
+
'maxRequestBodyBytes?': 'number.integer',
|
|
576
|
+
'memRequestBodyBytes?': 'number.integer',
|
|
577
|
+
'maxResponseBodyBytes?': 'number.integer',
|
|
578
|
+
'memResponseBodyBytes?': 'number.integer',
|
|
579
|
+
'retryExpression?': 'string',
|
|
580
|
+
});
|
|
581
|
+
/** Retry a request against the next available server. */
|
|
582
|
+
export const TraefikRetryMiddlewareSchema = type({
|
|
583
|
+
'attempts?': 'number.integer >= 0',
|
|
584
|
+
'initialInterval?': traefikDuration,
|
|
585
|
+
'timeout?': traefikDuration,
|
|
586
|
+
'status?': 'string[]',
|
|
587
|
+
/** `-1` means unlimited, which is the CRD's own minimum. */
|
|
588
|
+
'maxRequestBodyBytes?': 'number.integer >= -1',
|
|
589
|
+
'disableRetryOnNetworkError?': 'boolean',
|
|
590
|
+
'retryNonIdempotentMethod?': 'boolean',
|
|
591
|
+
});
|
|
592
|
+
/** Trip a circuit when the guard expression evaluates true. */
|
|
593
|
+
export const TraefikCircuitBreakerMiddlewareSchema = type({
|
|
594
|
+
'expression?': 'string',
|
|
595
|
+
'checkPeriod?': traefikDuration,
|
|
596
|
+
'fallbackDuration?': traefikDuration,
|
|
597
|
+
'recoveryDuration?': traefikDuration,
|
|
598
|
+
'responseCode?': '100 <= number.integer <= 599',
|
|
599
|
+
});
|
|
600
|
+
/** Allow only the listed source ranges. */
|
|
601
|
+
export const TraefikIpAllowListMiddlewareSchema = type({
|
|
602
|
+
sourceRange: 'string[]',
|
|
603
|
+
'ipStrategy?': TraefikIpStrategySchema,
|
|
604
|
+
'rejectStatusCode?': 'number.integer',
|
|
605
|
+
});
|
|
606
|
+
/** HTTP basic or digest auth backed by a Secret of htpasswd users. */
|
|
607
|
+
export const TraefikCredentialAuthMiddlewareSchema = type({
|
|
608
|
+
/** Secret containing a `users` key in htpasswd format. */
|
|
609
|
+
secret: 'string',
|
|
610
|
+
'realm?': 'string',
|
|
611
|
+
'removeHeader?': 'boolean',
|
|
612
|
+
'headerField?': 'string',
|
|
613
|
+
});
|
|
614
|
+
/** Response compression. */
|
|
615
|
+
export const TraefikCompressMiddlewareSchema = type({
|
|
616
|
+
'encodings?': 'string[]',
|
|
617
|
+
'defaultEncoding?': 'string',
|
|
618
|
+
'includedContentTypes?': 'string[]',
|
|
619
|
+
'excludedContentTypes?': 'string[]',
|
|
620
|
+
'minResponseBodyBytes?': 'number.integer >= 0',
|
|
621
|
+
});
|
|
622
|
+
/**
|
|
623
|
+
* Serve custom error pages from another service.
|
|
624
|
+
*
|
|
625
|
+
* `service` is required although the CRD allows it to be absent: without a
|
|
626
|
+
* backend there is nothing to serve the error page from.
|
|
627
|
+
*/
|
|
628
|
+
export const TraefikErrorsMiddlewareSchema = type({
|
|
629
|
+
'status?': 'string[]',
|
|
630
|
+
/** Rewrites are HTTP status codes, which the CRD types as integers. */
|
|
631
|
+
'statusRewrites?': 'Record<string, number.integer>',
|
|
632
|
+
'query?': 'string',
|
|
633
|
+
service: TraefikServiceRefSchema,
|
|
634
|
+
/** Client headers forwarded to the error-page service. */
|
|
635
|
+
'errorRequestHeaders?': 'string[]',
|
|
636
|
+
});
|
|
637
|
+
/** Apply an ordered list of other middlewares. */
|
|
638
|
+
export const TraefikChainMiddlewareSchema = type({
|
|
639
|
+
middlewares: TraefikMiddlewareRefSchema.array(),
|
|
640
|
+
});
|
|
641
|
+
/** Forward client-certificate information to the upstream. */
|
|
642
|
+
export const TraefikPassTLSClientCertMiddlewareSchema = type({
|
|
643
|
+
'pem?': 'boolean',
|
|
644
|
+
'info?': {
|
|
645
|
+
'notAfter?': 'boolean',
|
|
646
|
+
'notBefore?': 'boolean',
|
|
647
|
+
'sans?': 'boolean',
|
|
648
|
+
'serialNumber?': 'boolean',
|
|
649
|
+
'subject?': {
|
|
650
|
+
'commonName?': 'boolean',
|
|
651
|
+
'country?': 'boolean',
|
|
652
|
+
'domainComponent?': 'boolean',
|
|
653
|
+
'locality?': 'boolean',
|
|
654
|
+
'organization?': 'boolean',
|
|
655
|
+
'organizationalUnit?': 'boolean',
|
|
656
|
+
'province?': 'boolean',
|
|
657
|
+
'serialNumber?': 'boolean',
|
|
658
|
+
},
|
|
659
|
+
/** The CRD's issuer block has no `organizationalUnit`. */
|
|
660
|
+
'issuer?': {
|
|
661
|
+
'commonName?': 'boolean',
|
|
662
|
+
'country?': 'boolean',
|
|
663
|
+
'domainComponent?': 'boolean',
|
|
664
|
+
'locality?': 'boolean',
|
|
665
|
+
'organization?': 'boolean',
|
|
666
|
+
'province?': 'boolean',
|
|
667
|
+
'serialNumber?': 'boolean',
|
|
668
|
+
},
|
|
669
|
+
},
|
|
670
|
+
});
|
|
671
|
+
/** Auto-detect the response `Content-Type` when the upstream omits it. */
|
|
672
|
+
export const TraefikContentTypeMiddlewareSchema = type({
|
|
673
|
+
'autoDetect?': 'boolean',
|
|
674
|
+
});
|
|
675
|
+
/** Allow otherwise-rejected percent-encoded characters in the request path. */
|
|
676
|
+
export const TraefikEncodedCharactersMiddlewareSchema = type({
|
|
677
|
+
'allowEncodedSlash?': 'boolean',
|
|
678
|
+
'allowEncodedBackSlash?': 'boolean',
|
|
679
|
+
'allowEncodedNullCharacter?': 'boolean',
|
|
680
|
+
'allowEncodedSemicolon?': 'boolean',
|
|
681
|
+
'allowEncodedPercent?': 'boolean',
|
|
682
|
+
'allowEncodedQuestionMark?': 'boolean',
|
|
683
|
+
'allowEncodedHash?': 'boolean',
|
|
684
|
+
});
|
|
685
|
+
/** Bridge gRPC-Web clients to a gRPC upstream. */
|
|
686
|
+
export const TraefikGrpcWebMiddlewareSchema = type({
|
|
687
|
+
'allowOrigins?': 'string[]',
|
|
688
|
+
});
|
|
689
|
+
/**
|
|
690
|
+
* A Traefik plugin middleware.
|
|
691
|
+
*
|
|
692
|
+
* Keyed by the plugin name declared in `experimental.plugins`; the value shape
|
|
693
|
+
* belongs to the plugin itself. This is one of the boundaries where `unknown`
|
|
694
|
+
* is correct rather than lazy — the CRD marks it
|
|
695
|
+
* `x-kubernetes-preserve-unknown-fields`, so there is no schema to model.
|
|
696
|
+
*/
|
|
697
|
+
export const TraefikPluginMiddlewareSchema = type('Record<string, unknown>');
|
|
698
|
+
/**
|
|
699
|
+
* Every OSS middleware keyed by its CRD field name, all keys optional.
|
|
700
|
+
*
|
|
701
|
+
* A `Middleware` object carries exactly one of them, which
|
|
702
|
+
* {@link TraefikMiddlewareSpecSchema} enforces with `.narrow()` while keeping
|
|
703
|
+
* this base object shape intact so KRO SimpleSchema generation can still
|
|
704
|
+
* discover the fields.
|
|
705
|
+
*/
|
|
706
|
+
const TraefikMiddlewareSpecMapSchema = type({
|
|
707
|
+
'addPrefix?': TraefikAddPrefixMiddlewareSchema,
|
|
708
|
+
'basicAuth?': TraefikCredentialAuthMiddlewareSchema,
|
|
709
|
+
'buffering?': TraefikBufferingMiddlewareSchema,
|
|
710
|
+
'chain?': TraefikChainMiddlewareSchema,
|
|
711
|
+
'circuitBreaker?': TraefikCircuitBreakerMiddlewareSchema,
|
|
712
|
+
'compress?': TraefikCompressMiddlewareSchema,
|
|
713
|
+
'contentType?': TraefikContentTypeMiddlewareSchema,
|
|
714
|
+
'digestAuth?': TraefikCredentialAuthMiddlewareSchema,
|
|
715
|
+
'encodedCharacters?': TraefikEncodedCharactersMiddlewareSchema,
|
|
716
|
+
'errors?': TraefikErrorsMiddlewareSchema,
|
|
717
|
+
'forwardAuth?': TraefikForwardAuthMiddlewareSchema,
|
|
718
|
+
'grpcWeb?': TraefikGrpcWebMiddlewareSchema,
|
|
719
|
+
'headers?': TraefikHeadersMiddlewareSchema,
|
|
720
|
+
'inFlightReq?': TraefikInFlightReqMiddlewareSchema,
|
|
721
|
+
'ipAllowList?': TraefikIpAllowListMiddlewareSchema,
|
|
722
|
+
'passTLSClientCert?': TraefikPassTLSClientCertMiddlewareSchema,
|
|
723
|
+
'plugin?': TraefikPluginMiddlewareSchema,
|
|
724
|
+
'rateLimit?': TraefikRateLimitMiddlewareSchema,
|
|
725
|
+
'redirectRegex?': TraefikRedirectRegexMiddlewareSchema,
|
|
726
|
+
'redirectScheme?': TraefikRedirectSchemeMiddlewareSchema,
|
|
727
|
+
'replacePath?': TraefikReplacePathMiddlewareSchema,
|
|
728
|
+
'replacePathRegex?': TraefikReplacePathRegexMiddlewareSchema,
|
|
729
|
+
'retry?': TraefikRetryMiddlewareSchema,
|
|
730
|
+
'stripPrefix?': TraefikStripPrefixMiddlewareSchema,
|
|
731
|
+
'stripPrefixRegex?': TraefikStripPrefixRegexMiddlewareSchema,
|
|
732
|
+
});
|
|
733
|
+
/**
|
|
734
|
+
* `Middleware.spec` — exactly one middleware kind.
|
|
735
|
+
*
|
|
736
|
+
* The exactly-one invariant is a schema-level `.narrow()` rather than only a
|
|
737
|
+
* factory guard, per `integration-skill.md` ("Schema invariants"): two keys in
|
|
738
|
+
* one object is not a merge — Traefik applies one and silently drops the other.
|
|
739
|
+
* The narrow delegates to {@link validateTraefikMiddlewareSpec} so the rule has
|
|
740
|
+
* exactly one runtime implementation.
|
|
741
|
+
*/
|
|
742
|
+
export const TraefikMiddlewareSpecSchema = TraefikMiddlewareSpecMapSchema.narrow((data, ctx) => {
|
|
743
|
+
const issues = validateTraefikMiddlewareSpec(data);
|
|
744
|
+
return issues.length === 0 ? true : ctx.mustBe(issues.join(' '));
|
|
745
|
+
});
|
|
746
|
+
/**
|
|
747
|
+
* Secure `forwardAuth` defaults applied by
|
|
748
|
+
* `traefikForwardAuthMiddleware` (#172).
|
|
749
|
+
*
|
|
750
|
+
* @security `trustForwardHeader: false` means Traefik does not pass the
|
|
751
|
+
* client's own `X-Forwarded-*` headers to the authorizer, so a caller cannot
|
|
752
|
+
* assert its own identity or source address.
|
|
753
|
+
*/
|
|
754
|
+
export const TRAEFIK_FORWARD_AUTH_SECURE_DEFAULTS = {
|
|
755
|
+
trustForwardHeader: false,
|
|
756
|
+
};
|
|
757
|
+
// ============================================================================
|
|
758
|
+
// Resource configuration
|
|
759
|
+
//
|
|
760
|
+
// The identity half of every namespaced Traefik CRD factory's config. `spec`
|
|
761
|
+
// is the only part that varies by kind, so it stays a type parameter (see
|
|
762
|
+
// `resources/common.ts`) while everything a caller actually types by hand is
|
|
763
|
+
// declared once, here, and inferred from.
|
|
764
|
+
// ============================================================================
|
|
765
|
+
/**
|
|
766
|
+
* Identity of a namespaced Traefik CRD, without its behaviour.
|
|
767
|
+
*
|
|
768
|
+
* Extracted as a shape rather than re-declared per factory so the middleware
|
|
769
|
+
* builders' configs and {@link TraefikResourceConfig} cannot drift apart.
|
|
770
|
+
*
|
|
771
|
+
* These schemas are the source of truth for the TYPES and the target of the
|
|
772
|
+
* schema tests; the factories do not run them over their input, because inside
|
|
773
|
+
* a composition `name` may be a `KubernetesRef` proxy rather than a string and
|
|
774
|
+
* every one of these constraints would reject it.
|
|
775
|
+
*/
|
|
776
|
+
export const traefikResourceMetadataShape = {
|
|
777
|
+
name: kubernetesName,
|
|
778
|
+
namespace: kubernetesDnsLabel,
|
|
779
|
+
/** Extra labels merged onto the managed label set. */
|
|
780
|
+
'labels?': 'Record<string, string>',
|
|
781
|
+
'annotations?': 'Record<string, string>',
|
|
782
|
+
/** Resource graph id. Required when `name` is a schema reference. */
|
|
783
|
+
'id?': 'string > 0',
|
|
784
|
+
};
|
|
785
|
+
/** Identity of a namespaced Traefik CRD, without its behaviour. */
|
|
786
|
+
export const TraefikResourceMetadataSchema = type(traefikResourceMetadataShape);
|
|
787
|
+
/**
|
|
788
|
+
* Configuration for `traefikGatewayClass`.
|
|
789
|
+
*
|
|
790
|
+
* A `GatewayClass` is cluster-scoped, and its spec is pinned to Traefik's
|
|
791
|
+
* controller by the factory rather than supplied by the caller, so this config
|
|
792
|
+
* is the shared Gateway API identity shape plus one Traefik-specific field —
|
|
793
|
+
* fully inferred, with no `spec` to parameterise.
|
|
794
|
+
*/
|
|
795
|
+
export const TraefikGatewayClassConfigSchema = type({
|
|
796
|
+
...gatewayApiClusterResourceMetadataShape,
|
|
797
|
+
/** Optional description recorded on the class. */
|
|
798
|
+
'description?': 'string > 0',
|
|
799
|
+
});
|
|
800
|
+
/** Identity of a `Middleware`, without its behavior. */
|
|
801
|
+
export const TraefikMiddlewareMetadataSchema = TraefikResourceMetadataSchema;
|
|
802
|
+
/**
|
|
803
|
+
* Configuration for `traefikForwardAuthMiddleware`.
|
|
804
|
+
*
|
|
805
|
+
* `authResponseHeaders` is REQUIRED here although the CRD leaves it optional:
|
|
806
|
+
* an implicit "copy everything" would let an authorizer bug leak headers to
|
|
807
|
+
* the upstream, and a route with no allowlist silently drops the principal the
|
|
808
|
+
* upstream expects.
|
|
809
|
+
*/
|
|
810
|
+
export const TraefikForwardAuthMiddlewareConfigSchema = type({
|
|
811
|
+
...traefikResourceMetadataShape,
|
|
812
|
+
/** Authorizer URL, e.g. `http://authorizer.edge.svc.cluster.local:8080/authorize`. */
|
|
813
|
+
address: 'string > 0',
|
|
814
|
+
/** Headers copied from the authorizer's 2xx response onto the upstream request. */
|
|
815
|
+
authResponseHeaders: 'string[]',
|
|
816
|
+
/** Client headers forwarded to the authorizer. Omit to forward all of them. */
|
|
817
|
+
'authRequestHeaders?': 'string[]',
|
|
818
|
+
/**
|
|
819
|
+
* @security Defaults to `false`. Only enable when every client reaching this
|
|
820
|
+
* entrypoint is already behind a trusted proxy that rewrites
|
|
821
|
+
* `X-Forwarded-*`; otherwise a caller can assert its own source address.
|
|
822
|
+
*/
|
|
823
|
+
'trustForwardHeader?': 'boolean',
|
|
824
|
+
'forwardBody?': 'boolean',
|
|
825
|
+
'maxBodySize?': 'number.integer',
|
|
826
|
+
'tls?': middlewareClientTlsShape,
|
|
827
|
+
});
|
|
828
|
+
/** Every way a rate/concurrency budget can be keyed. Exactly one, or none. */
|
|
829
|
+
const middlewareBudgetKeyShape = {
|
|
830
|
+
/**
|
|
831
|
+
* Request header the budget is keyed on — typically the principal or tenant
|
|
832
|
+
* header a preceding `forwardAuth` produced. Mutually exclusive with
|
|
833
|
+
* `sourceCriterion`.
|
|
834
|
+
*/
|
|
835
|
+
'requestHeaderName?': 'string > 0',
|
|
836
|
+
/** Full source-criterion form, for IP-strategy or host keying. */
|
|
837
|
+
'sourceCriterion?': TraefikSourceCriterionSchema,
|
|
838
|
+
};
|
|
839
|
+
/**
|
|
840
|
+
* Reject a config that keys its budget two ways at once.
|
|
841
|
+
*
|
|
842
|
+
* `requestHeaderName` is sugar for `sourceCriterion.requestHeaderName`, so
|
|
843
|
+
* setting both is not a merge: the builder keeps `sourceCriterion` and
|
|
844
|
+
* silently drops the header name, which is the kind of quiet substitution the
|
|
845
|
+
* exactly-one middleware narrow exists to prevent. The rule was prose until
|
|
846
|
+
* now; the schema is where it belongs.
|
|
847
|
+
*/
|
|
848
|
+
function narrowBudgetKey(data, ctx) {
|
|
849
|
+
if (data.requestHeaderName !== undefined && data.sourceCriterion !== undefined) {
|
|
850
|
+
return ctx.mustBe('keyed either by requestHeaderName or by sourceCriterion, not both ' +
|
|
851
|
+
'(requestHeaderName is shorthand for sourceCriterion.requestHeaderName)');
|
|
852
|
+
}
|
|
853
|
+
return true;
|
|
854
|
+
}
|
|
855
|
+
/** Configuration for `traefikRateLimitMiddleware`. */
|
|
856
|
+
export const TraefikRateLimitMiddlewareConfigSchema = type({
|
|
857
|
+
...traefikResourceMetadataShape,
|
|
858
|
+
...middlewareBudgetKeyShape,
|
|
859
|
+
/** Sustained requests allowed per `period`. */
|
|
860
|
+
average: 'number.integer >= 0',
|
|
861
|
+
/** Requests absorbed above `average` before Traefik answers 429. */
|
|
862
|
+
burst: 'number.integer >= 0',
|
|
863
|
+
/** Window `average` is measured over. @default '1s' */
|
|
864
|
+
'period?': 'string > 0',
|
|
865
|
+
/**
|
|
866
|
+
* Shared Redis/Valkey backend. Without it each Traefik replica counts
|
|
867
|
+
* independently, so the effective budget is `average x replicas`.
|
|
868
|
+
*/
|
|
869
|
+
'redis?': TraefikRateLimitRedisSchema,
|
|
870
|
+
}).narrow(narrowBudgetKey);
|
|
871
|
+
/** Configuration for `traefikInFlightReqMiddleware`. */
|
|
872
|
+
export const TraefikInFlightReqMiddlewareConfigSchema = type({
|
|
873
|
+
...traefikResourceMetadataShape,
|
|
874
|
+
...middlewareBudgetKeyShape,
|
|
875
|
+
/** Maximum requests handled concurrently per source. */
|
|
876
|
+
amount: 'number.integer >= 0',
|
|
877
|
+
}).narrow(narrowBudgetKey);
|
|
878
|
+
/** Configuration for `traefikHeadersMiddleware`. */
|
|
879
|
+
export const TraefikHeadersMiddlewareConfigSchema = type({
|
|
880
|
+
...traefikResourceMetadataShape,
|
|
881
|
+
headers: TraefikHeadersMiddlewareSchema,
|
|
882
|
+
});
|
|
883
|
+
/** Configuration for `traefikRedirectSchemeMiddleware`. */
|
|
884
|
+
export const TraefikRedirectSchemeMiddlewareConfigSchema = type({
|
|
885
|
+
...traefikResourceMetadataShape,
|
|
886
|
+
/** @default 'https' */
|
|
887
|
+
'scheme?': '"http" | "https"',
|
|
888
|
+
/** @default true */
|
|
889
|
+
'permanent?': 'boolean',
|
|
890
|
+
'port?': 'string > 0',
|
|
891
|
+
});
|
|
892
|
+
/** Configuration for `traefikBufferingMiddleware`. */
|
|
893
|
+
export const TraefikBufferingMiddlewareConfigSchema = type({
|
|
894
|
+
...traefikResourceMetadataShape,
|
|
895
|
+
buffering: TraefikBufferingMiddlewareSchema,
|
|
896
|
+
});
|
|
897
|
+
/** Configuration for `traefikChainMiddleware`. */
|
|
898
|
+
export const TraefikChainMiddlewareConfigSchema = type({
|
|
899
|
+
...traefikResourceMetadataShape,
|
|
900
|
+
/** Middlewares applied in order. */
|
|
901
|
+
middlewares: TraefikMiddlewareRefSchema.array(),
|
|
902
|
+
});
|
|
903
|
+
/**
|
|
904
|
+
* Plugin declarations for `experimental.plugins`.
|
|
905
|
+
*
|
|
906
|
+
* Each plugin owns its own value shape, so this stays an `unknown` map by
|
|
907
|
+
* necessity — the same boundary as {@link TraefikPluginMiddleware}.
|
|
908
|
+
*/
|
|
909
|
+
export const TraefikPluginChartConfigSchema = type('Record<string, unknown>');
|
|
910
|
+
// ============================================================================
|
|
911
|
+
// Helm resource configuration
|
|
912
|
+
// ============================================================================
|
|
913
|
+
/**
|
|
914
|
+
* A Go duration as Flux's helm-controller parses it: one or more
|
|
915
|
+
* `<number><unit>` segments, e.g. `'1h'`, `'5m'`, `'90s'`, `'1h30m'`.
|
|
916
|
+
*
|
|
917
|
+
* Encoded as a schema constraint rather than a bare `string` because Flux
|
|
918
|
+
* rejects a malformed interval at ADMISSION — the HelmRelease is created and
|
|
919
|
+
* then never reconciles, which reads in the cluster as "Flux is broken"
|
|
920
|
+
* rather than as a typo.
|
|
921
|
+
*/
|
|
922
|
+
const fluxDuration = type(/^([0-9]+(\.[0-9]+)?(ns|us|ms|s|m|h))+$/);
|
|
923
|
+
/**
|
|
924
|
+
* CRD policy accepted by the Flux helm-controller.
|
|
925
|
+
*
|
|
926
|
+
* Kept as a literal union in the schema and re-stated as
|
|
927
|
+
* {@link HelmReleaseCrdsPolicy} in `factories/helm/types.ts`; the assertion
|
|
928
|
+
* below is what keeps the two from drifting.
|
|
929
|
+
*/
|
|
930
|
+
const helmReleaseCrdsPolicy = '"Skip" | "Create" | "CreateReplace"';
|
|
931
|
+
/** Configuration for the Traefik `HelmRepository`. */
|
|
932
|
+
export const TraefikHelmRepositoryConfigSchema = type({
|
|
933
|
+
name: kubernetesName,
|
|
934
|
+
/** Flux namespace holding the repository. Defaults to the Flux namespace. */
|
|
935
|
+
'namespace?': kubernetesDnsLabel,
|
|
936
|
+
/** @default DEFAULT_TRAEFIK_REPOSITORY_URL */
|
|
937
|
+
'url?': 'string > 0',
|
|
938
|
+
/** @default '1h' */
|
|
939
|
+
'interval?': fluxDuration,
|
|
940
|
+
'id?': 'string > 0',
|
|
941
|
+
});
|
|
942
|
+
/**
|
|
943
|
+
* Configuration for the Traefik `HelmRelease`, minus `values`.
|
|
944
|
+
*
|
|
945
|
+
* @see TraefikHelmReleaseConfig for why `values` is declared separately.
|
|
946
|
+
*/
|
|
947
|
+
export const TraefikHelmReleaseConfigSchema = type({
|
|
948
|
+
name: kubernetesName,
|
|
949
|
+
/** Namespace of the HelmRelease object. Defaults to the Flux namespace. */
|
|
950
|
+
'namespace?': kubernetesDnsLabel,
|
|
951
|
+
/** Namespace Traefik itself is installed into. */
|
|
952
|
+
'targetNamespace?': kubernetesDnsLabel,
|
|
953
|
+
/** @default DEFAULT_TRAEFIK_CHART_VERSION */
|
|
954
|
+
'version?': 'string > 0',
|
|
955
|
+
/** @default DEFAULT_TRAEFIK_REPOSITORY_NAME */
|
|
956
|
+
'repositoryName?': kubernetesDnsLabel,
|
|
957
|
+
'repositoryNamespace?': kubernetesDnsLabel,
|
|
958
|
+
/** @default '5m' */
|
|
959
|
+
'interval?': fluxDuration,
|
|
960
|
+
/** @default '10m' */
|
|
961
|
+
'timeout?': fluxDuration,
|
|
962
|
+
/** Whether Flux should create `targetNamespace`. @default false */
|
|
963
|
+
'createNamespace?': 'boolean',
|
|
964
|
+
/**
|
|
965
|
+
* CRD policy applied to BOTH `install.crds` and `upgrade.crds`.
|
|
966
|
+
*
|
|
967
|
+
* Flux defaults `upgrade.crds` to `Skip`, which would leave the CRDs of the
|
|
968
|
+
* first-installed chart version in place across a chart bump.
|
|
969
|
+
*
|
|
970
|
+
* @default DEFAULT_TRAEFIK_CRDS_POLICY (`'CreateReplace'`)
|
|
971
|
+
*/
|
|
972
|
+
'crds?': helmReleaseCrdsPolicy,
|
|
973
|
+
'id?': 'string > 0',
|
|
974
|
+
});
|
|
975
|
+
// ============================================================================
|
|
976
|
+
// Bootstrap composition contract (ArkType)
|
|
977
|
+
// ============================================================================
|
|
978
|
+
const traefikServiceTypeSchema = '"LoadBalancer" | "NodePort" | "ClusterIP"';
|
|
979
|
+
/**
|
|
980
|
+
* Runtime spec of the `traefikBootstrap` composition.
|
|
981
|
+
*
|
|
982
|
+
* Only proxy-safe values live here. `dashboard` is typed as the literal
|
|
983
|
+
* `false`: the dashboard and the insecure API are not switchable through this
|
|
984
|
+
* contract, and the values mapper pins them off regardless (#172).
|
|
985
|
+
*/
|
|
986
|
+
export const TraefikBootstrapConfigSchema = type({
|
|
987
|
+
name: kubernetesName,
|
|
988
|
+
'namespace?': kubernetesDnsLabel,
|
|
989
|
+
'chartVersion?': 'string > 0',
|
|
990
|
+
'replicas?': 'number.integer >= 1',
|
|
991
|
+
'ingressClass?': kubernetesDnsLabel,
|
|
992
|
+
'service?': {
|
|
993
|
+
'type?': traefikServiceTypeSchema,
|
|
994
|
+
/** Cloud load-balancer annotations. */
|
|
995
|
+
'annotations?': 'Record<string, string>',
|
|
996
|
+
},
|
|
997
|
+
/**
|
|
998
|
+
* Published ports and timeouts of the two entrypoints this edge exposes.
|
|
999
|
+
*
|
|
1000
|
+
* Both are always published by the Service this composition owns: whether a
|
|
1001
|
+
* port EXISTS is structural, so it cannot come from a runtime value that may
|
|
1002
|
+
* be a schema reference. Use the build-time `values` passthrough for a
|
|
1003
|
+
* chart-level entrypoint this factory does not model.
|
|
1004
|
+
*/
|
|
1005
|
+
'entrypoints?': {
|
|
1006
|
+
'web?': {
|
|
1007
|
+
'exposedPort?': kubernetesPort,
|
|
1008
|
+
},
|
|
1009
|
+
'websecure?': {
|
|
1010
|
+
'exposedPort?': kubernetesPort,
|
|
1011
|
+
/** Entrypoint responding timeouts, for requests longer than 60s. */
|
|
1012
|
+
'readTimeout?': 'string > 0',
|
|
1013
|
+
'writeTimeout?': 'string > 0',
|
|
1014
|
+
'idleTimeout?': 'string > 0',
|
|
1015
|
+
},
|
|
1016
|
+
},
|
|
1017
|
+
'providers?': {
|
|
1018
|
+
'crd?': 'boolean',
|
|
1019
|
+
'gatewayApi?': 'boolean',
|
|
1020
|
+
'kubernetesIngress?': 'boolean',
|
|
1021
|
+
},
|
|
1022
|
+
'accessLogs?': 'boolean',
|
|
1023
|
+
'logLevel?': '"TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR" | "FATAL" | "PANIC"',
|
|
1024
|
+
'otlp?': {
|
|
1025
|
+
/**
|
|
1026
|
+
* OTLP gRPC endpoint, `host:port`. Its presence is what enables metrics
|
|
1027
|
+
* and tracing export; omit the whole block to disable both.
|
|
1028
|
+
*/
|
|
1029
|
+
endpoint: 'string > 0',
|
|
1030
|
+
/**
|
|
1031
|
+
* Send OTLP without TLS. Defaults to `true` because the collector is
|
|
1032
|
+
* normally a same-cluster Service reached over the pod network; set it to
|
|
1033
|
+
* `false` for a collector that terminates TLS.
|
|
1034
|
+
*/
|
|
1035
|
+
'insecure?': 'boolean',
|
|
1036
|
+
'serviceName?': 'string > 0',
|
|
1037
|
+
},
|
|
1038
|
+
/** @security Only `false` is representable. */
|
|
1039
|
+
'dashboard?': 'false',
|
|
1040
|
+
});
|
|
1041
|
+
/**
|
|
1042
|
+
* Status contract of the `traefikBootstrap` composition.
|
|
1043
|
+
*
|
|
1044
|
+
* `loadBalancer` mirrors the entrypoint Service's
|
|
1045
|
+
* `status.loadBalancer.ingress[0]` and stays empty for `ClusterIP` /
|
|
1046
|
+
* `NodePort` services or while a cloud controller is still provisioning an
|
|
1047
|
+
* address.
|
|
1048
|
+
*
|
|
1049
|
+
* `version` is the chart version Flux actually installed, read back from the
|
|
1050
|
+
* owned `HelmRelease`'s `status.history[]` — an OBSERVED value rather than the
|
|
1051
|
+
* requested one, so a pinned-but-unavailable version can never be reported as
|
|
1052
|
+
* though it were live. It is empty until Flux records its first release.
|
|
1053
|
+
*
|
|
1054
|
+
* EVERY field here is a projection of a resource this composition owns, so it
|
|
1055
|
+
* hydrates identically in direct and KRO mode. That rules out literals: KRO
|
|
1056
|
+
* drops literal status fields, so declaring one would require a field the
|
|
1057
|
+
* instance never carries (#188). The entrypoint NAMES are therefore not in
|
|
1058
|
+
* this contract — they are fixed by this composition and exported as
|
|
1059
|
+
* `TRAEFIK_WEB_ENTRYPOINT` / `TRAEFIK_WEBSECURE_ENTRYPOINT` instead. Read the
|
|
1060
|
+
* live port names off the Service named by `serviceName` if a consumer needs
|
|
1061
|
+
* them at runtime.
|
|
1062
|
+
*/
|
|
1063
|
+
export const TraefikBootstrapStatusSchema = type({
|
|
1064
|
+
ready: 'boolean',
|
|
1065
|
+
failed: 'boolean',
|
|
1066
|
+
phase: '"Ready" | "Installing" | "Failed"',
|
|
1067
|
+
loadBalancer: {
|
|
1068
|
+
hostname: 'string',
|
|
1069
|
+
ip: 'string',
|
|
1070
|
+
},
|
|
1071
|
+
serviceName: 'string',
|
|
1072
|
+
version: 'string',
|
|
1073
|
+
});
|
|
1074
|
+
/** Spec of the shared `HelmRepository` singleton composition. */
|
|
1075
|
+
export const TraefikHelmRepositorySingletonSpecSchema = type({
|
|
1076
|
+
name: kubernetesDnsLabel,
|
|
1077
|
+
namespace: kubernetesDnsLabel,
|
|
1078
|
+
url: 'string > 0',
|
|
1079
|
+
});
|
|
1080
|
+
/** Status of the shared `HelmRepository` singleton composition. */
|
|
1081
|
+
export const TraefikHelmRepositorySingletonStatusSchema = type({
|
|
1082
|
+
ready: 'boolean',
|
|
1083
|
+
});
|
|
1084
|
+
//# sourceMappingURL=types.js.map
|