@aifabrix/builder 2.43.0 → 2.44.1
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/.cursor/rules/anchor-docs.mdc +15 -0
- package/.cursor/rules/cli-layout.mdc +75 -0
- package/.cursor/rules/project-rules.mdc +8 -0
- package/.npmrc.token +1 -0
- package/.nyc_output/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
- package/.nyc_output/processinfo/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
- package/.nyc_output/processinfo/index.json +1 -0
- package/README.md +1 -1
- package/anchor-docs/README.md +10 -0
- package/anchor-docs/_TEMPLATE +24 -0
- package/bin/aifabrix.js +13 -4
- package/integration/hubspot-test/README.md +31 -0
- package/integration/hubspot-test/create-hubspot.js +5 -5
- package/integration/hubspot-test/hubspot-test-datasource-company.json +58 -462
- package/integration/hubspot-test/hubspot-test-datasource-contact.json +61 -555
- package/integration/hubspot-test/hubspot-test-datasource-deal.json +63 -506
- package/integration/hubspot-test/hubspot-test-datasource-users.json +42 -83
- package/integration/hubspot-test/hubspot-test-deploy.json +3 -3
- package/integration/hubspot-test/test-dataplane-down-tests.js +1 -7
- package/integration/hubspot-test/test-dataplane-down.js +3 -3
- package/integration/hubspot-test/test.js +35 -43
- package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +23 -0
- package/integration/roundtrip-test-local/README.md +144 -0
- package/integration/roundtrip-test-local/application.yaml +13 -0
- package/integration/roundtrip-test-local/env.template +15 -0
- package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +14 -0
- package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +61 -0
- package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +25 -0
- package/integration/roundtrip-test-local2/README.md +144 -0
- package/integration/roundtrip-test-local2/application.yaml +13 -0
- package/integration/roundtrip-test-local2/env.template +15 -0
- package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +31 -0
- package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +86 -0
- package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +25 -0
- package/integration/test/wizard.yaml +8 -0
- package/jest.config.default.js +10 -0
- package/jest.config.integration.fixtures.js +22 -0
- package/jest.config.integration.js +21 -18
- package/jest.config.isolated.js +10 -0
- package/jest.projects.js +301 -0
- package/lib/api/certificates.api.js +62 -0
- package/lib/api/datasources-core.api.js +3 -3
- package/lib/api/dev-mtls-request.js +110 -0
- package/lib/api/dev-server-https.js +145 -0
- package/lib/api/dev.api.js +133 -144
- package/lib/api/index.js +11 -3
- package/lib/api/pipeline.api.js +67 -20
- package/lib/api/types/certificates.types.js +48 -0
- package/lib/api/types/dev.types.js +4 -3
- package/lib/api/types/pipeline.types.js +8 -5
- package/lib/api/types/validation-run.types.js +56 -0
- package/lib/api/validation-run.api.js +111 -0
- package/lib/api/validation-runner.js +109 -0
- package/lib/app/certification-show-enrich.js +129 -0
- package/lib/app/certification-verify-rows.js +60 -0
- package/lib/app/config.js +1 -1
- package/lib/app/deploy-status-display.js +2 -2
- package/lib/app/deploy.js +7 -6
- package/lib/app/display.js +2 -1
- package/lib/app/dockerfile.js +3 -2
- package/lib/app/down.js +2 -1
- package/lib/app/helpers.js +6 -5
- package/lib/app/index.js +27 -8
- package/lib/app/list.js +7 -6
- package/lib/app/push.js +4 -3
- package/lib/app/register.js +16 -7
- package/lib/app/rotate-secret.js +14 -13
- package/lib/app/run-container-start.js +184 -0
- package/lib/app/run-docker-fallback.js +108 -0
- package/lib/app/run-env-compose.js +30 -42
- package/lib/app/run-helpers.js +49 -126
- package/lib/app/run-infra-requirements.js +30 -0
- package/lib/app/run-resolve-image.js +21 -0
- package/lib/app/run.js +74 -21
- package/lib/app/show-display.js +44 -1
- package/lib/app/show.js +93 -9
- package/lib/build/index.js +13 -10
- package/lib/certification/cli-cert-sync-skip.js +21 -0
- package/lib/certification/merge-certification-from-artifact.js +185 -0
- package/lib/certification/post-unified-cert-sync.js +33 -0
- package/lib/certification/sync-after-external-command.js +52 -0
- package/lib/certification/sync-system-certification.js +197 -0
- package/lib/cli/index.js +2 -0
- package/lib/cli/setup-app.help.js +67 -0
- package/lib/cli/setup-app.js +61 -121
- package/lib/cli/setup-app.test-commands.js +195 -0
- package/lib/cli/setup-auth.js +19 -5
- package/lib/cli/setup-credential-deployment.js +22 -8
- package/lib/cli/setup-dev-path-commands.js +124 -0
- package/lib/cli/setup-dev.js +170 -113
- package/lib/cli/setup-environment.js +7 -1
- package/lib/cli/setup-external-system.js +84 -23
- package/lib/cli/setup-infra.js +126 -47
- package/lib/cli/setup-parameters.js +32 -0
- package/lib/cli/setup-secrets.js +137 -18
- package/lib/cli/setup-service-user.js +1 -1
- package/lib/cli/setup-utility.js +54 -22
- package/lib/commands/app-down.js +5 -7
- package/lib/commands/app-install.js +14 -7
- package/lib/commands/app-logs.js +13 -10
- package/lib/commands/app-shell.js +4 -1
- package/lib/commands/app-test.js +25 -19
- package/lib/commands/app.js +32 -11
- package/lib/commands/auth-config.js +6 -6
- package/lib/commands/auth-status.js +4 -3
- package/lib/commands/credential-env.js +4 -3
- package/lib/commands/credential-list.js +5 -4
- package/lib/commands/credential-push.js +4 -3
- package/lib/commands/datasource-unified-test-cli.js +428 -0
- package/lib/commands/datasource-unified-test-cli.options.js +191 -0
- package/lib/commands/datasource-unified-test-e2e-cli-helpers.js +106 -0
- package/lib/commands/datasource-validation-cli.js +143 -0
- package/lib/commands/datasource.js +125 -95
- package/lib/commands/deployment-list.js +6 -5
- package/lib/commands/dev-cli-handlers.js +122 -18
- package/lib/commands/dev-down.js +4 -3
- package/lib/commands/dev-init.js +231 -116
- package/lib/commands/dev-show-display.js +473 -0
- package/lib/commands/login-credentials.js +3 -2
- package/lib/commands/login-device.js +4 -3
- package/lib/commands/login.js +5 -4
- package/lib/commands/logout.js +8 -7
- package/lib/commands/parameters-validate.js +54 -0
- package/lib/commands/repair-datasource.js +314 -68
- package/lib/commands/repair-env-template.js +2 -2
- package/lib/commands/repair.js +21 -3
- package/lib/commands/secrets-list.js +23 -12
- package/lib/commands/secrets-remove-all.js +220 -0
- package/lib/commands/secrets-remove.js +21 -12
- package/lib/commands/secrets-set.js +21 -12
- package/lib/commands/secrets-validate.js +4 -4
- package/lib/commands/secure.js +10 -9
- package/lib/commands/service-user.js +26 -25
- package/lib/commands/test-e2e-external.js +27 -1
- package/lib/commands/up-common.js +3 -2
- package/lib/commands/up-dataplane.js +29 -16
- package/lib/commands/up-miso.js +19 -29
- package/lib/commands/upload.js +149 -39
- package/lib/commands/wizard-core-helpers.js +1 -1
- package/lib/commands/wizard-dataplane.js +4 -3
- package/lib/commands/wizard-helpers.js +3 -3
- package/lib/commands/wizard.js +2 -2
- package/lib/core/admin-secrets.js +14 -5
- package/lib/core/audit-logger.js +12 -4
- package/lib/core/config-attach-extensions.js +46 -0
- package/lib/core/config-runtime-paths.js +29 -0
- package/lib/core/config.js +55 -56
- package/lib/core/diff.js +3 -2
- package/lib/core/ensure-encryption-key.js +1 -1
- package/lib/core/secrets-ensure-infra.js +77 -0
- package/lib/core/secrets-ensure.js +120 -64
- package/lib/core/secrets-env-write.js +35 -7
- package/lib/core/secrets-infra-placeholder-sync.js +61 -0
- package/lib/core/secrets.js +200 -37
- package/lib/core/templates-env.js +4 -3
- package/lib/datasource/abac-validator.js +1 -10
- package/lib/datasource/deploy.js +75 -53
- package/lib/datasource/field-reference-validator.js +9 -6
- package/lib/datasource/integration-context.js +63 -0
- package/lib/datasource/list.js +8 -7
- package/lib/datasource/log-viewer.js +189 -67
- package/lib/datasource/resolve-app.js +4 -4
- package/lib/datasource/test-e2e.js +113 -146
- package/lib/datasource/test-integration.js +114 -122
- package/lib/datasource/unified-validation-run-body.js +68 -0
- package/lib/datasource/unified-validation-run-post.js +23 -0
- package/lib/datasource/unified-validation-run-resolve.js +43 -0
- package/lib/datasource/unified-validation-run.js +93 -0
- package/lib/datasource/validate.js +157 -13
- package/lib/deployment/deployer.js +4 -3
- package/lib/deployment/environment.js +7 -6
- package/lib/deployment/push.js +17 -8
- package/lib/external-system/delete.js +4 -3
- package/lib/external-system/deploy.js +166 -53
- package/lib/external-system/download-helpers.js +1 -1
- package/lib/external-system/download.js +7 -6
- package/lib/external-system/generator.js +92 -6
- package/lib/external-system/integration-test-dispatch.js +26 -0
- package/lib/external-system/test-execution.js +5 -1
- package/lib/external-system/test-helpers.js +0 -4
- package/lib/external-system/test-system-level-helpers.js +110 -0
- package/lib/external-system/test-system-level.js +83 -44
- package/lib/external-system/test.js +59 -8
- package/lib/generator/builders.js +23 -11
- package/lib/generator/deploy-manifest-azure-kv.js +81 -0
- package/lib/generator/external.js +16 -4
- package/lib/generator/helpers.js +58 -3
- package/lib/generator/index.js +4 -0
- package/lib/generator/split-readme.js +12 -7
- package/lib/generator/split-variables.js +2 -1
- package/lib/generator/split.js +1 -1
- package/lib/generator/wizard-readme.js +3 -3
- package/lib/generator/wizard.js +8 -8
- package/lib/infrastructure/compose.js +70 -7
- package/lib/infrastructure/helpers-docker-check.js +67 -0
- package/lib/infrastructure/helpers.js +203 -42
- package/lib/infrastructure/index.js +31 -18
- package/lib/infrastructure/services.js +21 -67
- package/lib/internal/fs-real-sync.js +104 -0
- package/lib/internal/node-fs.js +98 -0
- package/lib/parameters/database-secret-values.js +173 -0
- package/lib/parameters/infra-kv-discovery.js +121 -0
- package/lib/parameters/infra-parameter-catalog.js +458 -0
- package/lib/parameters/infra-parameter-validate.js +64 -0
- package/lib/schema/application-schema.json +37 -17
- package/lib/schema/datasource-test-run.schema.json +493 -0
- package/lib/schema/deployment-rules.yaml +102 -63
- package/lib/schema/external-datasource.schema.json +1200 -442
- package/lib/schema/external-system.schema.json +203 -5
- package/lib/schema/flag-map-validation-run.json +31 -0
- package/lib/schema/infra-parameter.schema.json +106 -0
- package/lib/schema/infra.parameter.yaml +421 -0
- package/lib/schema/type/credential-auth-templates.json +40 -0
- package/lib/schema/type/document-storage.json +226 -0
- package/lib/schema/type/message-service.json +123 -0
- package/lib/schema/type/vector-store.json +88 -0
- package/lib/utils/aifabrix-runtime-config-dir.js +132 -0
- package/lib/utils/api-error-handler.js +2 -2
- package/lib/utils/api.js +77 -17
- package/lib/utils/app-register-api.js +3 -2
- package/lib/utils/app-register-auth.js +1 -1
- package/lib/utils/app-register-config.js +4 -4
- package/lib/utils/app-register-display.js +3 -2
- package/lib/utils/app-register-validator.js +3 -2
- package/lib/utils/app-run-containers.js +26 -22
- package/lib/utils/app-scoped-config.js +31 -0
- package/lib/utils/app-service-env-from-builder.js +164 -0
- package/lib/utils/build-copy.js +1 -1
- package/lib/utils/build-helpers.js +20 -20
- package/lib/utils/build-resolve-image.js +165 -0
- package/lib/utils/cli-layout-chalk.js +8 -0
- package/lib/utils/cli-test-layout-chalk.js +267 -0
- package/lib/utils/cli-utils.js +88 -11
- package/lib/utils/compose-db-passwords.js +138 -0
- package/lib/utils/compose-generate-docker-compose.js +216 -0
- package/lib/utils/compose-generator.js +197 -291
- package/lib/utils/compose-miso-env.js +18 -0
- package/lib/utils/compose-traefik-ingress-base.js +158 -0
- package/lib/utils/config-paths.js +166 -7
- package/lib/utils/config-scoped-resources-preference.js +41 -0
- package/lib/utils/configuration-env-resolver.js +11 -8
- package/lib/utils/controller-deployment-outcome.js +68 -0
- package/lib/utils/credential-display.js +2 -2
- package/lib/utils/credential-secrets-env.js +5 -5
- package/lib/utils/dataplane-pipeline-warning.js +4 -3
- package/lib/utils/datasource-test-run-capability-scope.js +43 -0
- package/lib/utils/datasource-test-run-certificate-tty.js +82 -0
- package/lib/utils/datasource-test-run-debug-display.js +137 -0
- package/lib/utils/datasource-test-run-debug-slice.js +93 -0
- package/lib/utils/datasource-test-run-display.js +459 -0
- package/lib/utils/datasource-test-run-exit.js +83 -0
- package/lib/utils/datasource-test-run-legacy-adapter.js +93 -0
- package/lib/utils/datasource-test-run-report-version.js +51 -0
- package/lib/utils/datasource-test-run-schema-sync.js +59 -0
- package/lib/utils/datasource-test-run-tty-log.js +81 -0
- package/lib/utils/datasource-validation-watch.js +266 -0
- package/lib/utils/declarative-url-ports.js +47 -0
- package/lib/utils/derive-env-key-from-client-id.js +41 -0
- package/lib/utils/dev-ca-install.js +185 -23
- package/lib/utils/dev-cert-helper.js +266 -17
- package/lib/utils/dev-hosts-helper.js +307 -0
- package/lib/utils/dev-init-cert-hints.js +37 -0
- package/lib/utils/dev-init-health-messages.js +52 -0
- package/lib/utils/dev-init-resolve.js +86 -0
- package/lib/utils/dev-init-ssh-merge.js +65 -0
- package/lib/utils/dev-ssh-config-helper.js +196 -0
- package/lib/utils/dev-user-groups.js +93 -0
- package/lib/utils/docker-build.js +42 -17
- package/lib/utils/docker-exec.js +28 -0
- package/lib/utils/docker-manifest-public-port.js +116 -0
- package/lib/utils/docker-not-running-hint.js +52 -0
- package/lib/utils/docker.js +98 -11
- package/lib/utils/ensure-dev-certs-for-remote-docker.js +192 -0
- package/lib/utils/env-config-loader.js +10 -91
- package/lib/utils/env-copy.js +19 -10
- package/lib/utils/env-map.js +35 -8
- package/lib/utils/env-template.js +2 -2
- package/lib/utils/environment-scoped-resources.js +144 -0
- package/lib/utils/error-formatter.js +92 -13
- package/lib/utils/error-formatters/http-status-errors.js +6 -5
- package/lib/utils/error-formatters/network-errors.js +2 -1
- package/lib/utils/error-formatters/permission-errors.js +2 -1
- package/lib/utils/error-formatters/validation-errors.js +2 -1
- package/lib/utils/external-readme.js +8 -1
- package/lib/utils/external-system-display.js +242 -136
- package/lib/utils/external-system-local-test-tty.js +389 -0
- package/lib/utils/external-system-readiness-core.js +377 -0
- package/lib/utils/external-system-readiness-deploy-display.js +270 -0
- package/lib/utils/external-system-readiness-display-internals.js +150 -0
- package/lib/utils/external-system-readiness-display.js +186 -0
- package/lib/utils/external-system-system-test-tty-overview.js +120 -0
- package/lib/utils/external-system-system-test-tty.js +417 -0
- package/lib/utils/external-system-test-helpers.js +24 -6
- package/lib/utils/external-system-validators.js +30 -12
- package/lib/utils/health-check-url.js +119 -0
- package/lib/utils/health-check.js +59 -25
- package/lib/utils/help-builder.js +11 -8
- package/lib/utils/image-version.js +4 -8
- package/lib/utils/infra-containers.js +4 -7
- package/lib/utils/infra-env-defaults.js +162 -0
- package/lib/utils/infra-status-display.js +167 -0
- package/lib/utils/infra-status.js +16 -8
- package/lib/utils/local-secrets.js +3 -4
- package/lib/utils/paths.js +148 -47
- package/lib/utils/port-resolver.js +10 -23
- package/lib/utils/redis-env-scope.js +62 -0
- package/lib/utils/register-aifabrix-shell-env.js +204 -0
- package/lib/utils/remote-builder-validation.js +99 -0
- package/lib/utils/remote-dev-auth.js +117 -21
- package/lib/utils/remote-docker-env.js +67 -15
- package/lib/utils/remote-secrets-loader.js +13 -4
- package/lib/utils/resolve-docker-image-ref.js +124 -0
- package/lib/utils/schema-loader.js +22 -9
- package/lib/utils/secrets-bash-kv.js +25 -0
- package/lib/utils/secrets-generator.js +169 -49
- package/lib/utils/secrets-helpers.js +70 -59
- package/lib/utils/secrets-kv-scope.js +60 -0
- package/lib/utils/secrets-utils.js +32 -38
- package/lib/utils/secrets-validation.js +3 -1
- package/lib/utils/secrets-yaml-preserve.js +109 -0
- package/lib/utils/ssh-key-helper.js +4 -2
- package/lib/utils/template-helpers.js +2 -2
- package/lib/utils/test-log-writer.js +3 -3
- package/lib/utils/token-manager.js +1 -2
- package/lib/utils/url-declarative-public-base.js +188 -0
- package/lib/utils/url-declarative-resolve-build.js +493 -0
- package/lib/utils/url-declarative-resolve-load-doc.js +51 -0
- package/lib/utils/url-declarative-resolve.js +220 -0
- package/lib/utils/url-declarative-token-parse.js +74 -0
- package/lib/utils/url-declarative-url-flags.js +50 -0
- package/lib/utils/url-declarative-vdir-inactive-env.js +99 -0
- package/lib/utils/url-public-path-prefix.js +34 -0
- package/lib/utils/urls-local-registry.js +220 -0
- package/lib/utils/validation-report-tty-kit.js +77 -0
- package/lib/utils/validation-run-poll.js +112 -0
- package/lib/utils/validation-run-post-retry.js +85 -0
- package/lib/utils/validation-run-request.js +116 -0
- package/lib/utils/variable-transformer.js +21 -4
- package/lib/utils/yaml-preserve.js +33 -14
- package/lib/validation/datasource-warnings.js +56 -0
- package/lib/validation/env-template-auth.js +1 -1
- package/lib/validation/external-manifest-validator.js +27 -7
- package/lib/validation/validate-display.js +37 -31
- package/lib/validation/validate-external-cert-sync.js +23 -0
- package/lib/validation/validate.js +8 -14
- package/lib/validation/validator-unresolved-placeholders.js +98 -0
- package/lib/validation/validator.js +22 -65
- package/lib/validation/wizard-config-validator.js +2 -1
- package/package.json +9 -4
- package/scripts/check-datasource-test-run-schema-sync.js +34 -0
- package/scripts/diagnose-cli.js +150 -0
- package/scripts/install-local.js +307 -55
- package/scripts/pnpm-global-remove.js +48 -0
- package/templates/README.md +15 -2
- package/templates/applications/dataplane/application.yaml +52 -2
- package/templates/applications/dataplane/env.template +79 -17
- package/templates/applications/dataplane/rbac.yaml +8 -0
- package/templates/applications/keycloak/application.yaml +9 -1
- package/templates/applications/keycloak/env.template +15 -6
- package/templates/applications/miso-controller/application.yaml +10 -2
- package/templates/applications/miso-controller/env.template +42 -12
- package/templates/applications/miso-controller/rbac.yaml +5 -0
- package/templates/external-system/README.md.hbs +20 -7
- package/templates/external-system/deploy.js.hbs +5 -5
- package/templates/external-system/external-datasource.yaml.hbs +197 -118
- package/templates/infra/compose.yaml.hbs +33 -16
- package/templates/infra/servers.json.hbs +3 -1
- package/templates/python/docker-compose.hbs +16 -0
- package/templates/typescript/docker-compose.hbs +16 -0
- package/lib/api/external-test.api.js +0 -111
- package/lib/schema/env-config.yaml +0 -60
package/lib/core/secrets.js
CHANGED
|
@@ -24,10 +24,14 @@ const {
|
|
|
24
24
|
rewriteInfraEndpoints,
|
|
25
25
|
readYamlAtPath,
|
|
26
26
|
applyCanonicalSecretsOverride,
|
|
27
|
-
ensureNonEmptySecrets,
|
|
28
27
|
validateSecrets
|
|
29
28
|
} = require('../utils/secrets-helpers');
|
|
30
29
|
const { buildEnvVarMap } = require('../utils/env-map');
|
|
30
|
+
const {
|
|
31
|
+
mergeInfraParameterDefaultsForCli,
|
|
32
|
+
getInfraParameterCatalog,
|
|
33
|
+
readRelaxedCatalogDefaults
|
|
34
|
+
} = require('../parameters/infra-parameter-catalog');
|
|
31
35
|
const { resolveServicePortsInEnvContent } = require('../utils/secrets-url');
|
|
32
36
|
const {
|
|
33
37
|
updatePortForDocker,
|
|
@@ -35,7 +39,7 @@ const {
|
|
|
35
39
|
applyDockerEnvOverride,
|
|
36
40
|
getContainerPortFromDockerEnv
|
|
37
41
|
} = require('./secrets-docker-env');
|
|
38
|
-
const { getContainerPortFromPath } = require('../utils/port-resolver');
|
|
42
|
+
const { getContainerPortFromPath, loadVariablesFromPath } = require('../utils/port-resolver');
|
|
39
43
|
const {
|
|
40
44
|
generateMissingSecrets,
|
|
41
45
|
createDefaultSecrets
|
|
@@ -48,11 +52,21 @@ const {
|
|
|
48
52
|
const {
|
|
49
53
|
loadUserSecrets,
|
|
50
54
|
loadPrimaryUserSecrets,
|
|
51
|
-
loadDefaultSecrets
|
|
55
|
+
loadDefaultSecrets,
|
|
56
|
+
ensurePrimaryUserSecretsFileExists
|
|
52
57
|
} = require('../utils/secrets-utils');
|
|
53
58
|
const { decryptSecret, isEncrypted } = require('../utils/secrets-encryption');
|
|
54
59
|
const pathsUtil = require('../utils/paths');
|
|
55
60
|
const { ensureSecureFilePermissions } = require('../utils/secure-file-permissions');
|
|
61
|
+
const { readAppEnvironmentScopedFlagForAppPath } = require('../utils/app-scoped-config');
|
|
62
|
+
const { computeEffectiveEnvironmentScopedResources, redisDbIndexForScopedRunEnv } = require('../utils/environment-scoped-resources');
|
|
63
|
+
const { applyRedisDbIndexToEnvContent } = require('../utils/redis-env-scope');
|
|
64
|
+
const { expandDeclarativeUrlsInEnvContent } = require('../utils/url-declarative-resolve');
|
|
65
|
+
const { rewriteInactiveDeclarativeVdirPublicContent } = require('../utils/url-declarative-vdir-inactive-env');
|
|
66
|
+
const {
|
|
67
|
+
mergeDockerManifestPublishedPort,
|
|
68
|
+
rewriteDockerManifestPublicPortEnvLine
|
|
69
|
+
} = require('../utils/docker-manifest-public-port');
|
|
56
70
|
|
|
57
71
|
/**
|
|
58
72
|
* Generates a canonical secret name from an environment variable key.
|
|
@@ -128,8 +142,8 @@ async function decryptSecretsObject(secrets) {
|
|
|
128
142
|
* @function loadSecrets
|
|
129
143
|
* @param {string} [secretsPath] - Path to secrets file (optional, for explicit override)
|
|
130
144
|
* @param {string} [appName] - Application name (optional, for backward compatibility)
|
|
131
|
-
* @returns {Promise<Object>} Loaded secrets object with decrypted values
|
|
132
|
-
* @throws {Error} If
|
|
145
|
+
* @returns {Promise<Object>} Loaded secrets object with decrypted values (may be empty after bootstrap file create)
|
|
146
|
+
* @throws {Error} If explicit secretsPath is set but file is missing or invalid
|
|
133
147
|
*
|
|
134
148
|
* @example
|
|
135
149
|
* const secrets = await loadSecrets('../../secrets.local.yaml');
|
|
@@ -172,16 +186,17 @@ function mergeUserWithConfigFile(userSecrets, resolvedConfigPath) {
|
|
|
172
186
|
|
|
173
187
|
/**
|
|
174
188
|
* Loads config secrets path, merges with user secrets (user/master wins, public fills missing).
|
|
175
|
-
* User/master =
|
|
189
|
+
* User/master = getPrimaryUserSecretsLocalPath() (config dir; same file as loadPrimaryUserSecrets).
|
|
176
190
|
* Public = aifabrix-secrets path from config. Used by loadSecrets cascade.
|
|
177
|
-
* When
|
|
191
|
+
* When the effective shared-secrets target (after remote-dev resolution) is an http(s) URL,
|
|
192
|
+
* fetches shared secrets from API (never persisted to disk).
|
|
178
193
|
*
|
|
179
194
|
* @async
|
|
180
195
|
* @returns {Promise<Object|null>} Merged secrets object or null
|
|
181
196
|
*/
|
|
182
197
|
async function loadMergedConfigAndUserSecrets() {
|
|
183
198
|
const { loadRemoteSharedSecrets, mergeUserWithRemoteSecrets } = require('../utils/remote-secrets-loader');
|
|
184
|
-
const
|
|
199
|
+
const remoteDevAuth = require('../utils/remote-dev-auth');
|
|
185
200
|
const userSecrets = loadPrimaryUserSecrets();
|
|
186
201
|
const hasKeys = (obj) => obj && Object.keys(obj).length > 0;
|
|
187
202
|
const userOrNull = () => (hasKeys(userSecrets) ? userSecrets : null);
|
|
@@ -190,7 +205,8 @@ async function loadMergedConfigAndUserSecrets() {
|
|
|
190
205
|
if (!configSecretsPath) {
|
|
191
206
|
return userOrNull();
|
|
192
207
|
}
|
|
193
|
-
|
|
208
|
+
const effectiveShared = await remoteDevAuth.resolveSharedSecretsEndpoint(configSecretsPath);
|
|
209
|
+
if (remoteDevAuth.isRemoteSecretsUrl(effectiveShared)) {
|
|
194
210
|
const remoteSecrets = await loadRemoteSharedSecrets();
|
|
195
211
|
const merged = mergeUserWithRemoteSecrets(userSecrets, remoteSecrets);
|
|
196
212
|
return hasKeys(merged) ? merged : userOrNull();
|
|
@@ -254,9 +270,12 @@ async function loadSecrets(secretsPath, _appName) {
|
|
|
254
270
|
}
|
|
255
271
|
return await decryptSecretsObject(explicitSecrets);
|
|
256
272
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
273
|
+
let mergedSecrets = await loadSecretsWithFallbacks();
|
|
274
|
+
if (!mergedSecrets || Object.keys(mergedSecrets).length === 0) {
|
|
275
|
+
ensurePrimaryUserSecretsFileExists();
|
|
276
|
+
mergedSecrets = await loadSecretsWithFallbacks();
|
|
277
|
+
}
|
|
278
|
+
return await decryptSecretsObject(mergedSecrets || {});
|
|
260
279
|
}
|
|
261
280
|
|
|
262
281
|
/**
|
|
@@ -279,7 +298,7 @@ async function loadSecrets(secretsPath, _appName) {
|
|
|
279
298
|
* const resolved = await resolveKvReferences(template, secrets, 'local');
|
|
280
299
|
* // Returns: 'DATABASE_URL=postgresql://user:pass@localhost:5432/db'
|
|
281
300
|
*/
|
|
282
|
-
async function resolveKvReferences(envTemplate, secrets, environment = 'local', secretsFilePaths = null, appName = null) {
|
|
301
|
+
async function resolveKvReferences(envTemplate, secrets, environment = 'local', secretsFilePaths = null, appName = null, scopedKv = null) {
|
|
283
302
|
const os = require('os');
|
|
284
303
|
|
|
285
304
|
// Get developer-id for port variables (local and docker: *_PUBLIC_PORT = base + devId*100)
|
|
@@ -290,25 +309,56 @@ async function resolveKvReferences(envTemplate, secrets, environment = 'local',
|
|
|
290
309
|
// ignore, buildEnvVarMap will use default
|
|
291
310
|
}
|
|
292
311
|
|
|
293
|
-
|
|
312
|
+
const envKey = String(environment || 'local').toLowerCase();
|
|
313
|
+
const mapContext = envKey === 'docker' || envKey === 'local' ? envKey : 'local';
|
|
314
|
+
|
|
315
|
+
let envVars = await buildEnvVarMap(mapContext, os, developerId);
|
|
294
316
|
if (!envVars || Object.keys(envVars).length === 0) {
|
|
295
317
|
// Fallback to local environment variables if requested environment does not exist
|
|
296
318
|
envVars = await buildEnvVarMap('local', os, developerId);
|
|
297
319
|
}
|
|
298
320
|
const resolved = interpolateEnvVars(envTemplate, envVars);
|
|
299
|
-
const missing = collectMissingSecrets(resolved, secrets);
|
|
321
|
+
const missing = collectMissingSecrets(resolved, secrets, scopedKv);
|
|
300
322
|
if (missing.length > 0) {
|
|
301
323
|
const fileInfo = formatMissingSecretsFileInfo(secretsFilePaths);
|
|
302
324
|
const resolveCommand = appName ? `aifabrix resolve ${appName}` : 'aifabrix resolve <app-name>';
|
|
303
325
|
throw new Error(`Missing secrets: ${missing.join(', ')}${fileInfo}\n\nRun "${resolveCommand}" to generate missing secrets.`);
|
|
304
326
|
}
|
|
305
|
-
return replaceKvInContent(resolved, secrets, envVars);
|
|
327
|
+
return replaceKvInContent(resolved, secrets, envVars, scopedKv);
|
|
306
328
|
}
|
|
307
329
|
|
|
308
|
-
/**
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
330
|
+
/**
|
|
331
|
+
* Resolve run env key and effective env-scoped kv/redis behavior for generateEnvContent.
|
|
332
|
+
*
|
|
333
|
+
* @async
|
|
334
|
+
* @param {string} appPath - Builder application directory
|
|
335
|
+
* @param {Object} [options] - generateEnvContent options; may set runEnvKey
|
|
336
|
+
* @returns {Promise<{ runEnvKey: string, effective: boolean }>}
|
|
337
|
+
*/
|
|
338
|
+
async function buildScopedKvContext(appPath, options = {}) {
|
|
339
|
+
let runEnvKey;
|
|
340
|
+
if (options.runEnvKey !== undefined && options.runEnvKey !== null) {
|
|
341
|
+
runEnvKey = String(options.runEnvKey).toLowerCase();
|
|
342
|
+
} else if (typeof config.getCurrentEnvironment === 'function') {
|
|
343
|
+
runEnvKey = String((await config.getCurrentEnvironment()) || 'dev').toLowerCase();
|
|
344
|
+
} else {
|
|
345
|
+
runEnvKey = 'dev';
|
|
346
|
+
}
|
|
347
|
+
const userCfg =
|
|
348
|
+
typeof config.getConfig === 'function'
|
|
349
|
+
? await config.getConfig()
|
|
350
|
+
: { useEnvironmentScopedResources: false };
|
|
351
|
+
const useGate = Boolean(userCfg.useEnvironmentScopedResources);
|
|
352
|
+
const appFlag = readAppEnvironmentScopedFlagForAppPath(appPath);
|
|
353
|
+
const effective = computeEffectiveEnvironmentScopedResources(useGate, appFlag, runEnvKey);
|
|
354
|
+
return { runEnvKey, effective };
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Redis/DB service endpoints for docker env interpolation.
|
|
359
|
+
* @returns {Promise<{ redisHost: string, redisPort: number, dbHost: string, dbPort: number }>}
|
|
360
|
+
*/
|
|
361
|
+
async function getDockerRedisDbEndpoints() {
|
|
312
362
|
const { getEnvHosts, getServiceHost, getServicePort, getLocalhostOverride } = require('../utils/env-endpoints');
|
|
313
363
|
const hosts = await getEnvHosts('docker');
|
|
314
364
|
const localhostOverride = getLocalhostOverride('docker');
|
|
@@ -316,16 +366,97 @@ async function applyDockerTransformations(resolved, variablesPath) {
|
|
|
316
366
|
const redisPort = await getServicePort('REDIS_PORT', 'redis', hosts, 'docker', null);
|
|
317
367
|
const dbHost = getServiceHost(hosts.DB_HOST, 'docker', 'postgres', localhostOverride);
|
|
318
368
|
const dbPort = await getServicePort('DB_PORT', 'postgres', hosts, 'docker', null);
|
|
369
|
+
return { redisHost, redisPort, dbHost, dbPort };
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Config inputs for declarative url:// expansion (keeps expandDeclarativeUrlsIfPresent small).
|
|
374
|
+
* @param {string} appPath
|
|
375
|
+
* @returns {Promise<Object>}
|
|
376
|
+
*/
|
|
377
|
+
async function loadDeclarativeUrlExpandInputs(appPath) {
|
|
378
|
+
const userCfg = await config.getConfig();
|
|
379
|
+
let remoteServer = null;
|
|
380
|
+
try {
|
|
381
|
+
const rs = await config.getRemoteServer();
|
|
382
|
+
if (rs && String(rs).trim()) {
|
|
383
|
+
remoteServer = String(rs).trim();
|
|
384
|
+
}
|
|
385
|
+
} catch {
|
|
386
|
+
remoteServer = null;
|
|
387
|
+
}
|
|
388
|
+
let developerIdRaw = null;
|
|
389
|
+
try {
|
|
390
|
+
developerIdRaw = await config.getDeveloperId();
|
|
391
|
+
} catch {
|
|
392
|
+
developerIdRaw = null;
|
|
393
|
+
}
|
|
394
|
+
let infraTlsEnabled = false;
|
|
395
|
+
try {
|
|
396
|
+
infraTlsEnabled = await config.getTlsEnabled();
|
|
397
|
+
} catch {
|
|
398
|
+
infraTlsEnabled = false;
|
|
399
|
+
}
|
|
400
|
+
return {
|
|
401
|
+
userCfg,
|
|
402
|
+
remoteServer,
|
|
403
|
+
developerIdRaw,
|
|
404
|
+
infraTlsEnabled,
|
|
405
|
+
appScopedFlag: readAppEnvironmentScopedFlagForAppPath(appPath)
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* After kv:// resolution, expand url:// references when application config exists.
|
|
411
|
+
* @param {string} resolved
|
|
412
|
+
* @param {string} appName
|
|
413
|
+
* @param {string} appPath
|
|
414
|
+
* @param {string|null} variablesPath
|
|
415
|
+
* @param {string} environment
|
|
416
|
+
* @param {boolean} envOnly
|
|
417
|
+
* @returns {Promise<string>}
|
|
418
|
+
*/
|
|
419
|
+
async function expandDeclarativeUrlsIfPresent(resolved, appName, appPath, variablesPath, environment, envOnly) {
|
|
420
|
+
if (envOnly || !variablesPath) {
|
|
421
|
+
return resolved;
|
|
422
|
+
}
|
|
423
|
+
const { userCfg, remoteServer, developerIdRaw, infraTlsEnabled, appScopedFlag } =
|
|
424
|
+
await loadDeclarativeUrlExpandInputs(appPath);
|
|
425
|
+
resolved = rewriteInactiveDeclarativeVdirPublicContent(resolved, variablesPath, userCfg);
|
|
426
|
+
if (!resolved.includes('url://')) {
|
|
427
|
+
return resolved;
|
|
428
|
+
}
|
|
429
|
+
return expandDeclarativeUrlsInEnvContent(resolved, {
|
|
430
|
+
profile: environment === 'docker' ? 'docker' : 'local',
|
|
431
|
+
currentAppKey: appName,
|
|
432
|
+
variablesPath,
|
|
433
|
+
useEnvironmentScopedResources: Boolean(userCfg.useEnvironmentScopedResources),
|
|
434
|
+
appEnvironmentScopedResources: appScopedFlag,
|
|
435
|
+
remoteServer,
|
|
436
|
+
developerIdRaw,
|
|
437
|
+
traefik: Boolean(userCfg.traefik),
|
|
438
|
+
infraTlsEnabled
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/** Docker env transformations: ports, infra endpoints, PORT. */
|
|
443
|
+
async function applyDockerTransformations(resolved, variablesPath) {
|
|
444
|
+
resolved = await resolveServicePortsInEnvContent(resolved, 'docker');
|
|
445
|
+
resolved = await rewriteInfraEndpoints(resolved, 'docker');
|
|
446
|
+
const { redisHost, redisPort, dbHost, dbPort } = await getDockerRedisDbEndpoints();
|
|
319
447
|
let dockerEnv = await getBaseDockerEnv();
|
|
320
448
|
dockerEnv = applyDockerEnvOverride(dockerEnv);
|
|
321
449
|
const containerPort = getContainerPortFromPath(variablesPath) ?? getContainerPortFromDockerEnv(dockerEnv) ?? 3000;
|
|
322
450
|
const envVars = await buildEnvVarMap('docker', null, null, { appPort: containerPort });
|
|
451
|
+
const appDoc = loadVariablesFromPath(variablesPath);
|
|
452
|
+
await mergeDockerManifestPublishedPort(envVars, appDoc);
|
|
323
453
|
envVars.REDIS_HOST = redisHost;
|
|
324
454
|
envVars.REDIS_PORT = String(redisPort);
|
|
325
455
|
envVars.DB_HOST = dbHost;
|
|
326
456
|
envVars.DB_PORT = String(dbPort);
|
|
327
457
|
envVars.PORT = String(containerPort);
|
|
328
458
|
resolved = interpolateEnvVars(resolved, envVars);
|
|
459
|
+
resolved = rewriteDockerManifestPublicPortEnvLine(resolved, envVars, appDoc);
|
|
329
460
|
return updatePortForDocker(resolved, variablesPath);
|
|
330
461
|
}
|
|
331
462
|
/** Environment-specific transformations to resolved content. */
|
|
@@ -357,8 +488,22 @@ async function generateEnvContent(appName, secretsPath, environment = 'local', f
|
|
|
357
488
|
await secretsEnsure.ensureSecretsFromEnvTemplate(templatePath, { preferredFilePath: preferredPath });
|
|
358
489
|
}
|
|
359
490
|
const secrets = await loadSecrets(secretsPath, appName);
|
|
360
|
-
|
|
491
|
+
const { runEnvKey, effective } = await buildScopedKvContext(appPath, options);
|
|
492
|
+
const scopedKv = { envKey: runEnvKey, effective };
|
|
493
|
+
let resolved = await resolveKvReferences(template, secrets, environment, secretsPaths, appName, scopedKv);
|
|
494
|
+
resolved = await expandDeclarativeUrlsIfPresent(
|
|
495
|
+
resolved,
|
|
496
|
+
appName,
|
|
497
|
+
appPath,
|
|
498
|
+
variablesPath,
|
|
499
|
+
environment,
|
|
500
|
+
Boolean(options.envOnly)
|
|
501
|
+
);
|
|
361
502
|
resolved = await applyEnvironmentTransformations(resolved, environment, variablesPath);
|
|
503
|
+
if (effective) {
|
|
504
|
+
const idx = redisDbIndexForScopedRunEnv(runEnvKey);
|
|
505
|
+
resolved = applyRedisDbIndexToEnvContent(resolved, idx);
|
|
506
|
+
}
|
|
362
507
|
|
|
363
508
|
return resolved;
|
|
364
509
|
}
|
|
@@ -538,39 +683,57 @@ async function formatAdminSecretsContent(adminObj) {
|
|
|
538
683
|
return lines.join('\n');
|
|
539
684
|
}
|
|
540
685
|
|
|
541
|
-
|
|
542
|
-
async function generateAdminSecretsEnv(secretsPath) {
|
|
543
|
-
let secrets;
|
|
544
|
-
|
|
686
|
+
async function loadSecretsOrBootstrapForAdmin(secretsPath) {
|
|
545
687
|
try {
|
|
546
|
-
|
|
688
|
+
return await loadSecrets(secretsPath);
|
|
547
689
|
} catch (error) {
|
|
548
690
|
const defaultSecretsPath = secretsPath || path.join(pathsUtil.getAifabrixHome(), 'secrets.yaml');
|
|
549
691
|
if (!fs.existsSync(defaultSecretsPath)) {
|
|
550
692
|
logger.log('Creating default secrets file...');
|
|
551
693
|
await createDefaultSecrets(defaultSecretsPath);
|
|
552
|
-
|
|
553
|
-
} else {
|
|
554
|
-
throw error;
|
|
694
|
+
return await loadSecrets(secretsPath);
|
|
555
695
|
}
|
|
696
|
+
throw error;
|
|
556
697
|
}
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
function getInfraDefaultsMergedForAdmin() {
|
|
701
|
+
try {
|
|
702
|
+
return mergeInfraParameterDefaultsForCli(getInfraParameterCatalog().data, {});
|
|
703
|
+
} catch {
|
|
704
|
+
return {};
|
|
561
705
|
}
|
|
706
|
+
}
|
|
562
707
|
|
|
708
|
+
function buildLocalAdminSecretsObject(secrets, infraDefaults) {
|
|
563
709
|
const raw = secrets['postgres-passwordKeyVault'];
|
|
564
|
-
const
|
|
565
|
-
|
|
566
|
-
|
|
710
|
+
const relaxed = readRelaxedCatalogDefaults();
|
|
711
|
+
const postgresPassword =
|
|
712
|
+
(raw && String(raw).trim()) ||
|
|
713
|
+
infraDefaults.adminPassword ||
|
|
714
|
+
relaxed.adminPassword ||
|
|
715
|
+
'';
|
|
716
|
+
const pgAdminEmail = infraDefaults.adminEmail || relaxed.adminEmail || '';
|
|
717
|
+
return {
|
|
567
718
|
POSTGRES_PASSWORD: postgresPassword,
|
|
568
|
-
PGADMIN_DEFAULT_EMAIL:
|
|
719
|
+
PGADMIN_DEFAULT_EMAIL: pgAdminEmail,
|
|
569
720
|
PGADMIN_DEFAULT_PASSWORD: postgresPassword,
|
|
570
721
|
REDIS_HOST: 'local:redis:6379:0:',
|
|
571
722
|
REDIS_COMMANDER_USER: 'admin',
|
|
572
723
|
REDIS_COMMANDER_PASSWORD: postgresPassword
|
|
573
724
|
};
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
/** Generates admin secrets for infrastructure (beside config.yaml, typically ~/.aifabrix/admin-secrets.env). Defaults from infra.parameter.yaml `defaults`. */
|
|
728
|
+
async function generateAdminSecretsEnv(secretsPath) {
|
|
729
|
+
const secrets = await loadSecretsOrBootstrapForAdmin(secretsPath);
|
|
730
|
+
const infraDefaults = getInfraDefaultsMergedForAdmin();
|
|
731
|
+
const adminObj = buildLocalAdminSecretsObject(secrets, infraDefaults);
|
|
732
|
+
const aifabrixDir = pathsUtil.getAifabrixSystemDir();
|
|
733
|
+
const adminEnvPath = path.join(aifabrixDir, 'admin-secrets.env');
|
|
734
|
+
if (!fs.existsSync(aifabrixDir)) {
|
|
735
|
+
fs.mkdirSync(aifabrixDir, { recursive: true, mode: 0o700 });
|
|
736
|
+
}
|
|
574
737
|
const adminSecrets = await formatAdminSecretsContent(adminObj);
|
|
575
738
|
fs.writeFileSync(adminEnvPath, adminSecrets, { mode: 0o600 });
|
|
576
739
|
return adminEnvPath;
|
|
@@ -106,9 +106,10 @@ function buildMonitoringEnv(config) {
|
|
|
106
106
|
return {
|
|
107
107
|
'MISO_CONTROLLER_URL': config.controllerUrl || 'https://controller.aifabrix.dev',
|
|
108
108
|
'MISO_ENVIRONMENT': 'dev',
|
|
109
|
-
|
|
110
|
-
'
|
|
111
|
-
'
|
|
109
|
+
// Filled after `aifabrix register <app>`; empty avoids bogus kv placeholders in new apps
|
|
110
|
+
'MISO_CLIENTID': '',
|
|
111
|
+
'MISO_CLIENTSECRET': '',
|
|
112
|
+
'MISO_WEB_SERVER_URL': 'url://miso-controller-public'
|
|
112
113
|
};
|
|
113
114
|
}
|
|
114
115
|
|
|
@@ -99,7 +99,7 @@ function validateCrossSystemJson(crossSystemJson) {
|
|
|
99
99
|
|
|
100
100
|
/**
|
|
101
101
|
* Validates ABAC configuration for a parsed datasource.
|
|
102
|
-
* Checks dimensions
|
|
102
|
+
* Checks dimensions from config.abac, crossSystemJson, and rejects legacy crossSystem.
|
|
103
103
|
*
|
|
104
104
|
* @function validateAbac
|
|
105
105
|
* @param {Object} parsed - Parsed datasource object (after JSON parse)
|
|
@@ -134,15 +134,6 @@ function validateAbac(parsed) {
|
|
|
134
134
|
));
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
const fieldMappingsDimensions = parsed?.fieldMappings?.dimensions;
|
|
138
|
-
if (fieldMappingsDimensions && typeof fieldMappingsDimensions === 'object') {
|
|
139
|
-
errors.push(...validateDimensionsObject(
|
|
140
|
-
fieldMappingsDimensions,
|
|
141
|
-
'fieldMappings.dimensions',
|
|
142
|
-
attributeNames
|
|
143
|
-
));
|
|
144
|
-
}
|
|
145
|
-
|
|
146
137
|
if (abac.crossSystemJson) {
|
|
147
138
|
errors.push(...validateCrossSystemJson(abac.crossSystemJson));
|
|
148
139
|
}
|
package/lib/datasource/deploy.js
CHANGED
|
@@ -17,6 +17,16 @@ const { publishDatasourceViaPipeline } = require('../api/pipeline.api');
|
|
|
17
17
|
const { formatApiError } = require('../utils/api-error-handler');
|
|
18
18
|
const logger = require('../utils/logger');
|
|
19
19
|
const { logDataplanePipelineWarning } = require('../utils/dataplane-pipeline-warning');
|
|
20
|
+
const {
|
|
21
|
+
sectionTitle,
|
|
22
|
+
headerKeyValue,
|
|
23
|
+
metadata,
|
|
24
|
+
infoLine,
|
|
25
|
+
formatStatusKeyValue,
|
|
26
|
+
formatBlockingError,
|
|
27
|
+
successGlyph,
|
|
28
|
+
failureGlyph
|
|
29
|
+
} = require('../utils/cli-test-layout-chalk');
|
|
20
30
|
const {
|
|
21
31
|
buildResolvedEnvMapForIntegration,
|
|
22
32
|
resolveConfigurationValues
|
|
@@ -64,41 +74,41 @@ async function getDataplaneUrl(controllerUrl, appKey, environment, authConfig) {
|
|
|
64
74
|
}
|
|
65
75
|
|
|
66
76
|
/**
|
|
67
|
-
* Validate
|
|
68
|
-
* @param {string}
|
|
69
|
-
* @param {string} filePath - File path
|
|
70
|
-
* @param {Object} options - Options
|
|
77
|
+
* Validate deploy CLI input (file path or datasource key, same rules as `datasource validate`).
|
|
78
|
+
* @param {string} fileOrKey - Path to JSON or datasource `key` under integration/<app>/
|
|
71
79
|
* @throws {Error} If validation fails
|
|
72
80
|
*/
|
|
73
|
-
function
|
|
74
|
-
if (!
|
|
75
|
-
throw new Error('
|
|
76
|
-
}
|
|
77
|
-
if (!filePath || typeof filePath !== 'string') {
|
|
78
|
-
throw new Error('File path is required');
|
|
81
|
+
function validateDeployFileOrKeyInput(fileOrKey) {
|
|
82
|
+
if (!fileOrKey || typeof fileOrKey !== 'string' || !fileOrKey.trim()) {
|
|
83
|
+
throw new Error('File path or datasource key is required');
|
|
79
84
|
}
|
|
80
85
|
}
|
|
81
86
|
|
|
82
87
|
/**
|
|
83
|
-
* Validate and load datasource file
|
|
88
|
+
* Validate and load datasource file (path or datasource key, resolved like `datasource validate`).
|
|
84
89
|
* @async
|
|
85
|
-
* @param {string}
|
|
90
|
+
* @param {string} filePathOrKey - Path to datasource JSON or datasource `key`
|
|
86
91
|
* @returns {Promise<Object>} Datasource configuration
|
|
87
92
|
* @throws {Error} If validation or loading fails
|
|
88
93
|
*/
|
|
89
|
-
async function validateAndLoadDatasourceFile(
|
|
90
|
-
logger.log(
|
|
91
|
-
const validation = await validateDatasourceFile(
|
|
94
|
+
async function validateAndLoadDatasourceFile(filePathOrKey) {
|
|
95
|
+
logger.log(infoLine('ℹ Validating datasource file'));
|
|
96
|
+
const validation = await validateDatasourceFile(filePathOrKey);
|
|
92
97
|
if (!validation.valid) {
|
|
93
|
-
logger.
|
|
98
|
+
logger.log('');
|
|
99
|
+
logger.error(formatBlockingError('Datasource validation failed'));
|
|
94
100
|
validation.errors.forEach(error => {
|
|
95
|
-
logger.error(
|
|
101
|
+
logger.error(formatBlockingError(error));
|
|
96
102
|
});
|
|
97
103
|
throw new Error('Datasource file validation failed');
|
|
98
104
|
}
|
|
99
|
-
logger.log(chalk.green('✓ Datasource file is valid'));
|
|
100
105
|
|
|
101
|
-
const
|
|
106
|
+
const resolvedPath = validation.resolvedPath;
|
|
107
|
+
logger.log(headerKeyValue('File:', resolvedPath));
|
|
108
|
+
logger.log(`${successGlyph()} ${chalk.white('Datasource file is valid.')}`);
|
|
109
|
+
logger.log('');
|
|
110
|
+
|
|
111
|
+
const content = fs.readFileSync(resolvedPath, 'utf8');
|
|
102
112
|
try {
|
|
103
113
|
return JSON.parse(content);
|
|
104
114
|
} catch (error) {
|
|
@@ -116,28 +126,28 @@ async function validateAndLoadDatasourceFile(filePath) {
|
|
|
116
126
|
*/
|
|
117
127
|
async function setupDeploymentAuth(controllerUrl, environment, appKey) {
|
|
118
128
|
const { resolveDataplaneUrl } = require('../utils/dataplane-resolver');
|
|
119
|
-
logger.log(
|
|
129
|
+
logger.log(infoLine('ℹ Resolving authentication'));
|
|
120
130
|
const authConfig = await getDeploymentAuth(controllerUrl, environment, appKey);
|
|
121
|
-
logger.log(chalk.
|
|
131
|
+
logger.log(`${successGlyph()} ${chalk.white('Authentication ready')}`);
|
|
122
132
|
|
|
123
|
-
logger.log(
|
|
133
|
+
logger.log(infoLine('ℹ Resolving dataplane URL'));
|
|
124
134
|
let dataplaneUrl;
|
|
125
135
|
try {
|
|
126
136
|
dataplaneUrl = await resolveDataplaneUrl(controllerUrl, environment, authConfig);
|
|
127
|
-
logger.log(
|
|
137
|
+
logger.log(`${metadata('Dataplane:')} ${chalk.cyan(dataplaneUrl)}`);
|
|
128
138
|
} catch (error) {
|
|
129
|
-
logger.error(chalk.red('
|
|
130
|
-
logger.error(
|
|
131
|
-
logger.error(
|
|
132
|
-
logger.error(
|
|
139
|
+
logger.error(`${failureGlyph()} ${chalk.red('Failed to resolve dataplane URL:')} ${chalk.red(error.message)}`);
|
|
140
|
+
logger.error(metadata('The dataplane URL is automatically discovered from the controller.'));
|
|
141
|
+
logger.error(metadata('If discovery fails, ensure you are logged in and the controller is accessible:'));
|
|
142
|
+
logger.error(metadata('aifabrix login'));
|
|
133
143
|
throw error;
|
|
134
144
|
}
|
|
135
145
|
|
|
136
146
|
// Validate dataplane URL
|
|
137
147
|
if (!dataplaneUrl || !dataplaneUrl.trim()) {
|
|
138
|
-
logger.error(chalk.red('
|
|
139
|
-
logger.error(
|
|
140
|
-
logger.error(
|
|
148
|
+
logger.error(`${failureGlyph()} ${chalk.red('Dataplane URL is empty.')}`);
|
|
149
|
+
logger.error(metadata('The dataplane URL could not be discovered from the controller.'));
|
|
150
|
+
logger.error(metadata('Ensure the dataplane service is registered in the controller.'));
|
|
141
151
|
throw new Error('Dataplane URL is empty');
|
|
142
152
|
}
|
|
143
153
|
|
|
@@ -156,30 +166,32 @@ async function setupDeploymentAuth(controllerUrl, environment, appKey) {
|
|
|
156
166
|
*/
|
|
157
167
|
async function publishDatasourceToDataplane(dataplaneUrl, systemKey, authConfig, datasourceConfig) {
|
|
158
168
|
requireBearerForDataplanePipeline(authConfig);
|
|
159
|
-
logger.log(
|
|
169
|
+
logger.log('');
|
|
170
|
+
logger.log(sectionTitle('Publish'));
|
|
160
171
|
logDataplanePipelineWarning();
|
|
161
172
|
|
|
162
173
|
const publishResponse = await publishDatasourceViaPipeline(dataplaneUrl, systemKey, authConfig, datasourceConfig);
|
|
163
174
|
|
|
164
175
|
if (!publishResponse.success) {
|
|
165
176
|
const formattedError = publishResponse.formattedError || formatApiError(publishResponse);
|
|
166
|
-
logger.error(chalk.red('
|
|
167
|
-
logger.error(formattedError);
|
|
177
|
+
logger.error(`${failureGlyph()} ${chalk.red('Publish failed:')} ${chalk.red(formattedError)}`);
|
|
168
178
|
|
|
169
179
|
// Show dataplane URL and endpoint information
|
|
170
180
|
if (publishResponse.errorData && publishResponse.errorData.endpointUrl) {
|
|
171
|
-
logger.error(
|
|
181
|
+
logger.error(
|
|
182
|
+
`\n${metadata('Endpoint URL:')} ${chalk.cyan(publishResponse.errorData.endpointUrl)}`
|
|
183
|
+
);
|
|
172
184
|
} else if (dataplaneUrl) {
|
|
173
|
-
logger.error(
|
|
174
|
-
logger.error(
|
|
185
|
+
logger.error(`\n${metadata('Dataplane URL:')} ${chalk.cyan(dataplaneUrl)}`);
|
|
186
|
+
logger.error(headerKeyValue('System Key:', systemKey));
|
|
175
187
|
}
|
|
176
188
|
|
|
177
|
-
logger.error(
|
|
178
|
-
logger.error(
|
|
189
|
+
logger.error(metadata('\nFull response for debugging:'));
|
|
190
|
+
logger.error(metadata(JSON.stringify(publishResponse, null, 2)));
|
|
179
191
|
throw new Error(`Dataplane publish failed: ${formattedError}`);
|
|
180
192
|
}
|
|
181
193
|
|
|
182
|
-
logger.log(chalk.
|
|
194
|
+
logger.log(`${successGlyph()} ${chalk.white('Configuration published to dataplane.')}`);
|
|
183
195
|
return publishResponse;
|
|
184
196
|
}
|
|
185
197
|
|
|
@@ -190,9 +202,21 @@ async function publishDatasourceToDataplane(dataplaneUrl, systemKey, authConfig,
|
|
|
190
202
|
* @param {string} environment - Environment key
|
|
191
203
|
*/
|
|
192
204
|
function displayDeploymentResults(datasourceConfig, systemKey, environment) {
|
|
193
|
-
|
|
194
|
-
logger.log(
|
|
195
|
-
logger.log(
|
|
205
|
+
const datasourceLabel = datasourceConfig.key || datasourceConfig.displayName || '(unknown)';
|
|
206
|
+
logger.log('');
|
|
207
|
+
logger.log(sectionTitle('Result'));
|
|
208
|
+
logger.log(headerKeyValue('Datasource:', datasourceLabel));
|
|
209
|
+
logger.log(headerKeyValue('System:', systemKey));
|
|
210
|
+
logger.log(headerKeyValue('Environment:', environment));
|
|
211
|
+
logger.log('');
|
|
212
|
+
logger.log(formatStatusKeyValue('ok', '✔'));
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function logDatasourceUploadSectionHeader() {
|
|
216
|
+
logger.log('');
|
|
217
|
+
logger.log(sectionTitle('Datasource upload'));
|
|
218
|
+
logger.log(metadata('Publish one datasource JSON to the dataplane'));
|
|
219
|
+
logger.log('');
|
|
196
220
|
}
|
|
197
221
|
|
|
198
222
|
/**
|
|
@@ -201,18 +225,17 @@ function displayDeploymentResults(datasourceConfig, systemKey, environment) {
|
|
|
201
225
|
*
|
|
202
226
|
* @async
|
|
203
227
|
* @function deployDatasource
|
|
204
|
-
* @param {string}
|
|
205
|
-
* @param {string} filePath - Path to datasource JSON file
|
|
228
|
+
* @param {string} fileOrKey - Path to datasource JSON file, or datasource `key` under integration/<app>/ (same resolution as `datasource validate`)
|
|
206
229
|
* @param {Object} [_options] - Deployment options (reserved)
|
|
207
230
|
* @returns {Promise<Object>} Deployment result
|
|
208
231
|
* @throws {Error} If deployment fails
|
|
209
232
|
*/
|
|
210
|
-
async function deployDatasource(
|
|
233
|
+
async function deployDatasource(fileOrKey, _options) {
|
|
211
234
|
const { resolveControllerUrl } = require('../utils/controller-url');
|
|
212
235
|
const { resolveEnvironment } = require('../core/config');
|
|
213
236
|
const { displayCommandHeader } = require('../utils/command-header');
|
|
214
237
|
|
|
215
|
-
|
|
238
|
+
validateDeployFileOrKeyInput(fileOrKey);
|
|
216
239
|
|
|
217
240
|
// Resolve controller and environment from config
|
|
218
241
|
const controllerUrl = await resolveControllerUrl();
|
|
@@ -220,13 +243,12 @@ async function deployDatasource(appKey, filePath, _options) {
|
|
|
220
243
|
|
|
221
244
|
// Display command header
|
|
222
245
|
displayCommandHeader(controllerUrl, environment);
|
|
246
|
+
logDatasourceUploadSectionHeader();
|
|
223
247
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
// Validate and load datasource file
|
|
227
|
-
const datasourceConfig = await validateAndLoadDatasourceFile(filePath);
|
|
248
|
+
// Validate and load datasource file (resolves key → path like validate)
|
|
249
|
+
const datasourceConfig = await validateAndLoadDatasourceFile(fileOrKey.trim());
|
|
228
250
|
|
|
229
|
-
// Extract systemKey
|
|
251
|
+
// Extract systemKey (required in JSON; also used as controller app key for external systems)
|
|
230
252
|
const systemKey = datasourceConfig.systemKey;
|
|
231
253
|
if (!systemKey) {
|
|
232
254
|
throw new Error('systemKey is required in datasource configuration');
|
|
@@ -237,8 +259,8 @@ async function deployDatasource(appKey, filePath, _options) {
|
|
|
237
259
|
resolveConfigurationValues(datasourceConfig.configuration, envMap, secrets, systemKey);
|
|
238
260
|
}
|
|
239
261
|
|
|
240
|
-
// Setup authentication and get dataplane URL
|
|
241
|
-
const { authConfig, dataplaneUrl } = await setupDeploymentAuth(controllerUrl, environment,
|
|
262
|
+
// Setup authentication and get dataplane URL (application key matches systemKey for external integrations)
|
|
263
|
+
const { authConfig, dataplaneUrl } = await setupDeploymentAuth(controllerUrl, environment, systemKey);
|
|
242
264
|
|
|
243
265
|
// Publish to dataplane
|
|
244
266
|
await publishDatasourceToDataplane(dataplaneUrl, systemKey, authConfig, datasourceConfig);
|