@aifabrix/builder 2.44.6 → 2.45.5
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/cli-layout.mdc +7 -3
- package/.cursor/rules/docs-rules.mdc +3 -1
- package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +1 -1
- package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.yaml +1 -1
- package/integration/hubspot-test/wizard-hubspot-e2e.yaml +1 -1
- package/jest.projects.js +100 -1
- package/lib/api/agent-metadata-validation.api.js +93 -0
- package/lib/api/audit-api-helpers.js +68 -0
- package/lib/api/audit.api.js +119 -0
- package/lib/api/auth-cache.api.js +44 -0
- package/lib/api/certificates.api.js +4 -4
- package/lib/api/credential.api.js +2 -2
- package/lib/api/dataplane-health.api.js +137 -0
- package/lib/api/dataplane-sync.api.js +27 -0
- package/lib/api/datasources-core.api.js +21 -18
- package/lib/api/datasources-extended.api.js +22 -22
- package/lib/api/dimensions.api.js +3 -0
- package/lib/api/external-systems.api.js +13 -13
- package/lib/api/governance-scenarios.api.js +39 -0
- package/lib/api/groups.api.js +79 -0
- package/lib/api/index.js +45 -2
- package/lib/api/pipeline.api.js +4 -4
- package/lib/api/protection.api.js +157 -0
- package/lib/api/records-bulk.api.js +30 -0
- package/lib/api/records-search-parse.js +49 -0
- package/lib/api/records-search.api.js +29 -0
- package/lib/api/types/agent-metadata-validation.types.js +67 -0
- package/lib/api/types/audit.types.js +72 -0
- package/lib/api/types/dataplane-health.types.js +27 -0
- package/lib/api/types/dimensions.types.js +2 -0
- package/lib/api/types/governance-scenarios.types.js +39 -0
- package/lib/api/types/protection.types.js +69 -0
- package/lib/api/types/records-bulk.types.js +35 -0
- package/lib/api/types/records-search.types.js +28 -0
- package/lib/api/user-groups.api.js +50 -0
- package/lib/api/users.api.js +95 -0
- package/lib/api/validation-run.api.js +3 -3
- package/lib/api/validation-runner.js +3 -3
- package/lib/api/wizard-platform.api.js +3 -3
- package/lib/api/wizard.api.js +21 -21
- package/lib/app/deploy.js +34 -19
- package/lib/app/helpers.js +3 -3
- package/lib/app/index.js +3 -3
- package/lib/app/register.js +7 -6
- package/lib/app/restart-display.js +52 -21
- package/lib/app/rotate-secret.js +7 -6
- package/lib/app/run-helpers.js +15 -8
- package/lib/app/run.js +57 -9
- package/lib/app/show-display.js +7 -0
- package/lib/app/show.js +87 -5
- package/lib/build/index.js +9 -5
- package/lib/cli/index.js +4 -2
- package/lib/cli/infra-guided.js +62 -28
- package/lib/cli/installation-log-command.js +73 -0
- package/lib/cli/setup-app.help.js +50 -2
- package/lib/cli/setup-app.js +44 -25
- package/lib/cli/setup-app.test-commands.js +80 -21
- package/lib/cli/setup-auth.js +124 -52
- package/lib/cli/setup-external-system.js +37 -3
- package/lib/cli/setup-infra-up-dataplane-action.js +111 -0
- package/lib/cli/setup-infra-up-platform-action.js +131 -0
- package/lib/cli/setup-infra.js +60 -119
- package/lib/cli/setup-platform.js +1 -1
- package/lib/cli/setup-utility-help-after.js +45 -0
- package/lib/cli/setup-utility-resolve.js +132 -0
- package/lib/cli/setup-utility.js +148 -116
- package/lib/commands/app-logs.js +81 -33
- package/lib/commands/auth-config.js +116 -18
- package/lib/commands/auth-status-dataplane-version.js +231 -0
- package/lib/commands/auth-status-display.js +94 -0
- package/lib/commands/auth-status.js +70 -6
- package/lib/commands/credential-push.js +10 -5
- package/lib/commands/datasource-load-export-cli.js +178 -0
- package/lib/commands/datasource-test-trust-cli.js +114 -0
- package/lib/commands/datasource-unified-test-cli.js +25 -17
- package/lib/commands/datasource-unified-test-cli.options.js +18 -3
- package/lib/commands/datasource-unified-test-e2e-cli-helpers.js +5 -5
- package/lib/commands/datasource-verify-audit-cli.js +96 -0
- package/lib/commands/datasource.js +68 -1
- package/lib/commands/dimension-value.js +43 -13
- package/lib/commands/dimension.js +38 -7
- package/lib/commands/identity-apply-sync.js +131 -0
- package/lib/commands/identity-group-cli.js +146 -0
- package/lib/commands/identity-membership-role-cache.js +175 -0
- package/lib/commands/identity-shared.js +94 -0
- package/lib/commands/identity-user-cli.js +158 -0
- package/lib/commands/identity.js +43 -0
- package/lib/commands/login.js +46 -16
- package/lib/commands/protection-cli-leaves.js +286 -0
- package/lib/commands/protection.js +50 -0
- package/lib/commands/repair.js +13 -3
- package/lib/commands/setup-modes.js +19 -6
- package/lib/commands/setup-prompts.js +41 -8
- package/lib/commands/setup.js +114 -9
- package/lib/commands/teardown.js +54 -5
- package/lib/commands/test-e2e-external.js +40 -9
- package/lib/commands/test-governance-cli-options.js +47 -0
- package/lib/commands/test-governance-command-action.js +55 -0
- package/lib/commands/test-governance-external.js +88 -0
- package/lib/commands/test-trust-cli-options.js +32 -0
- package/lib/commands/test-trust-command-action.js +118 -0
- package/lib/commands/test-trust-external.js +127 -0
- package/lib/commands/up-common.js +48 -14
- package/lib/commands/up-dataplane.js +21 -18
- package/lib/commands/up-miso.js +12 -8
- package/lib/commands/upload.js +38 -15
- package/lib/commands/wizard-core.js +3 -0
- package/lib/core/audit-logger.js +1 -34
- package/lib/core/config-admin-email.js +56 -0
- package/lib/core/config-device-dataplane.js +185 -0
- package/lib/core/config-normalize.js +60 -0
- package/lib/core/config-registered-controller-urls.js +54 -0
- package/lib/core/config.js +33 -50
- package/lib/core/secrets-ensure-infra.js +1 -1
- package/lib/core/secrets-env-content.js +86 -90
- package/lib/core/secrets-env-declarative-expand.js +170 -0
- package/lib/core/secrets-env-write.js +2 -0
- package/lib/core/secrets-load.js +106 -102
- package/lib/datasource/agent-trust-debug-log.js +45 -0
- package/lib/datasource/agent-trust-fetch.js +115 -0
- package/lib/datasource/agent-trust-map.js +101 -0
- package/lib/datasource/agent-trust-mock.js +44 -0
- package/lib/datasource/agent-trust-run.js +93 -0
- package/lib/datasource/agent-trust-timeout.js +25 -0
- package/lib/datasource/audit-evidence-display.js +80 -0
- package/lib/datasource/audit-evidence-extract-debug.js +103 -0
- package/lib/datasource/audit-evidence-extract.js +177 -0
- package/lib/datasource/audit-evidence-matrix-rows.js +158 -0
- package/lib/datasource/audit-evidence-operation-aliases.js +63 -0
- package/lib/datasource/audit-evidence-poll.js +109 -0
- package/lib/datasource/audit-evidence-run.js +177 -0
- package/lib/datasource/audit-evidence-verify-helpers.js +167 -0
- package/lib/datasource/audit-evidence-verify-matrix.js +177 -0
- package/lib/datasource/audit-evidence-verify.js +108 -0
- package/lib/datasource/bulk-loader-run-batches.js +88 -0
- package/lib/datasource/bulk-loader-service-retry.js +52 -0
- package/lib/datasource/bulk-loader-service.js +127 -0
- package/lib/datasource/capability/run-capability-dimension.js +2 -1
- package/lib/datasource/datasource-exporter-resolve.js +82 -0
- package/lib/datasource/datasource-exporter-service.js +144 -0
- package/lib/datasource/datasource-identifier.js +148 -0
- package/lib/datasource/datasource-load-export-context.js +92 -0
- package/lib/datasource/integration-context.js +6 -4
- package/lib/datasource/local-data-paths.js +145 -0
- package/lib/datasource/log-cleaner.js +241 -0
- package/lib/datasource/log-viewer.js +111 -6
- package/lib/datasource/record-file-parser.js +85 -0
- package/lib/datasource/record-mapper.js +129 -0
- package/lib/datasource/resolve-app.js +74 -55
- package/lib/datasource/test-e2e.js +26 -2
- package/lib/datasource/unified-validation-run-resolve.js +45 -12
- package/lib/datasource/unified-validation-run.js +43 -17
- package/lib/datasource/validate.js +37 -20
- package/lib/external-system/deploy.js +5 -1
- package/lib/external-system/test-system-level.js +25 -4
- package/lib/external-system/test.js +3 -1
- package/lib/governance/governance-pack-loader.js +70 -0
- package/lib/governance/governance-run-display.js +119 -0
- package/lib/identity/identity-apply-core.js +108 -0
- package/lib/identity/identity-apply-phases.js +244 -0
- package/lib/identity/identity-apply-service.js +77 -0
- package/lib/identity/identity-csv-parser.js +114 -0
- package/lib/internal/fs-real-sync.js +29 -1
- package/lib/internal/node-fs.js +2 -0
- package/lib/protection/auth-context.js +45 -0
- package/lib/protection/convert-batch.js +90 -0
- package/lib/protection/load.js +41 -0
- package/lib/protection/paths.js +158 -0
- package/lib/protection/preflight-datasource-ready.js +46 -0
- package/lib/protection/protection-create-probe-lines.js +142 -0
- package/lib/protection/protection-create-probes.js +95 -0
- package/lib/protection/protection-create-scaffold.js +281 -0
- package/lib/protection/protection-display-helpers.js +445 -0
- package/lib/protection/protection-display.js +215 -0
- package/lib/protection/protection-preset-registry.js +97 -0
- package/lib/protection/report-exit.js +62 -0
- package/lib/protection/resolve.js +202 -0
- package/lib/protection/run-commands-validate.js +130 -0
- package/lib/protection/run-commands.js +216 -0
- package/lib/protection/run-protection-create-helpers.js +134 -0
- package/lib/protection/run-protection-create-probes-flow.js +43 -0
- package/lib/protection/run-protection-create.js +191 -0
- package/lib/protection/scope.js +22 -0
- package/lib/protection/sync-after-upload.js +64 -0
- package/lib/protection/upload-batch.js +127 -0
- package/lib/protection/validate-batch.js +113 -0
- package/lib/protection/validate-local.js +65 -0
- package/lib/resolvers/dimension-file.js +29 -4
- package/lib/schema/application-schema.json +4 -0
- package/lib/schema/external-datasource.schema.json +47 -13
- package/lib/schema/flag-map-validation-run.json +2 -2
- package/lib/schema/infra.parameter.yaml +10 -0
- package/lib/schema/protection.schema.json +374 -0
- package/lib/schema/type/credential-field-registry.json +636 -0
- package/lib/schema/wizard-config.schema.json +1 -1
- package/lib/utils/agent-trust-run-display.js +231 -0
- package/lib/utils/agent-trust-run-exit.js +59 -0
- package/lib/utils/agent-trust-wait-ui.js +94 -0
- package/lib/utils/app-config-resolver.js +24 -1
- package/lib/utils/applications-config-defaults.js +206 -0
- package/lib/utils/auth-config-validator.js +2 -12
- package/lib/utils/bash-secret-env.js +1 -1
- package/lib/utils/cli-exit-codes.js +30 -0
- package/lib/utils/cli-sync-options.js +33 -0
- package/lib/utils/compose-generate-docker-compose.js +111 -6
- package/lib/utils/compose-generator.js +17 -8
- package/lib/utils/controller-url.js +50 -7
- package/lib/utils/credential-push-ui.js +90 -0
- package/lib/utils/dataplane-cli-version-gate.js +202 -0
- package/lib/utils/dataplane-cli-version-help.js +74 -0
- package/lib/utils/datasource-export-display.js +137 -0
- package/lib/utils/datasource-load-display.js +174 -0
- package/lib/utils/datasource-load-export-ui.js +120 -0
- package/lib/utils/datasource-test-run-capability-scope.js +3 -3
- package/lib/utils/datasource-test-run-display.js +3 -3
- package/lib/utils/datasource-test-run-tty-log.js +5 -1
- package/lib/utils/env-copy.js +99 -14
- package/lib/utils/env-template.js +5 -1
- package/lib/utils/health-check-url.js +18 -15
- package/lib/utils/health-check.js +7 -5
- package/lib/utils/help-builder.js +30 -24
- package/lib/utils/infra-optional-service-flags.js +69 -0
- package/lib/utils/installation-log-core.js +282 -0
- package/lib/utils/installation-log-record.js +237 -0
- package/lib/utils/installation-log.js +123 -0
- package/lib/utils/log-redaction.js +105 -0
- package/lib/utils/manifest-location.js +164 -0
- package/lib/utils/manifest-source-emit.js +184 -0
- package/lib/utils/paths.js +238 -89
- package/lib/utils/remote-secrets-loader.js +7 -1
- package/lib/utils/run-cli-flags.js +29 -0
- package/lib/utils/secrets-canonical.js +10 -3
- package/lib/utils/secrets-path.js +3 -4
- package/lib/utils/secrets-utils.js +20 -10
- package/lib/utils/semver-compare.js +127 -0
- package/lib/utils/system-builder-root.js +10 -2
- package/lib/utils/upload-pipeline-ui.js +91 -0
- package/lib/utils/url-declarative-public-base.js +80 -12
- package/lib/utils/url-declarative-resolve-build-urls.js +238 -0
- package/lib/utils/url-declarative-resolve-build.js +24 -393
- package/lib/utils/url-declarative-resolve-expand-token.js +189 -0
- package/lib/utils/url-declarative-resolve-load-doc.js +12 -3
- package/lib/utils/url-declarative-resolve-surface-state.js +102 -0
- package/lib/utils/url-declarative-resolve.js +47 -7
- package/lib/utils/url-declarative-runtime-base-path.js +21 -1
- package/lib/utils/urls-local-registry-scan.js +103 -0
- package/lib/utils/urls-local-registry.js +161 -90
- package/lib/utils/validation-poll-ui.js +14 -7
- package/lib/validation/wizard-config-validator.js +58 -19
- package/package.json +3 -1
- package/templates/applications/dataplane/application.yaml +4 -0
- package/templates/applications/dataplane/env.template +13 -1
- package/templates/applications/dataplane/rbac.yaml +4 -0
- package/templates/applications/miso-controller/application.yaml +2 -0
- package/templates/applications/miso-controller/env.template +27 -29
- package/templates/external-system/README.md.hbs +56 -8
- package/.npmrc.token +0 -1
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Protection subcommand registration (keeps setupProtectionCommands under line limit).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const logger = require('../utils/logger');
|
|
8
|
+
const { resolveProtectionArgument } = require('../protection/resolve');
|
|
9
|
+
const {
|
|
10
|
+
runProtectionValidate,
|
|
11
|
+
runProtectionUpload,
|
|
12
|
+
runProtectionList,
|
|
13
|
+
runProtectionShow,
|
|
14
|
+
runProtectionDelete
|
|
15
|
+
} = require('../protection/run-commands');
|
|
16
|
+
const { runProtectionCreate } = require('../protection/run-protection-create');
|
|
17
|
+
|
|
18
|
+
const SHARED_OPTS = [
|
|
19
|
+
['-e, --env <environment>', 'Environment key'],
|
|
20
|
+
['-v, --verbose', 'Verbose output']
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
const PROTECTION_CREATE_HELP_AFTER = `
|
|
24
|
+
|
|
25
|
+
Examples:
|
|
26
|
+
$ aifabrix protection create hubspot-companies --type country-sales
|
|
27
|
+
$ aifabrix protection create hr-persons --type department-manager
|
|
28
|
+
$ aifabrix protection create erp-projects --type project-team
|
|
29
|
+
$ aifabrix protection create hubspot-companies --dimension-key country --dry-run
|
|
30
|
+
$ aifabrix protection create hubspot-companies --type country-sales --force
|
|
31
|
+
|
|
32
|
+
Preset types:
|
|
33
|
+
country-sales, department-manager, customer-team, project-team, static-region, owner-direct
|
|
34
|
+
`;
|
|
35
|
+
|
|
36
|
+
const PROTECTION_VALIDATE_HELP_AFTER = `
|
|
37
|
+
|
|
38
|
+
Examples:
|
|
39
|
+
$ aifabrix protection validate hubspot-companies
|
|
40
|
+
$ aifabrix protection validate hubspot-companies --simulate
|
|
41
|
+
$ aifabrix protection validate hubspot-companies --warnings-as-errors
|
|
42
|
+
$ aifabrix protection validate hubspot-companies --json
|
|
43
|
+
`;
|
|
44
|
+
|
|
45
|
+
const PROTECTION_UPLOAD_HELP_AFTER = `
|
|
46
|
+
|
|
47
|
+
Examples:
|
|
48
|
+
$ aifabrix protection upload hubspot-companies
|
|
49
|
+
$ aifabrix protection upload hubspot-companies --dry-run
|
|
50
|
+
$ aifabrix protection upload hubspot-companies --no-sync
|
|
51
|
+
`;
|
|
52
|
+
|
|
53
|
+
const PROTECTION_LIST_HELP_AFTER = `
|
|
54
|
+
|
|
55
|
+
Examples:
|
|
56
|
+
$ aifabrix protection list
|
|
57
|
+
$ aifabrix protection list --page 1 --page-size 50
|
|
58
|
+
$ aifabrix protection list --filter enabled:eq:true
|
|
59
|
+
$ aifabrix protection list --json
|
|
60
|
+
`;
|
|
61
|
+
|
|
62
|
+
const PROTECTION_SHOW_HELP_AFTER = `
|
|
63
|
+
|
|
64
|
+
Examples:
|
|
65
|
+
$ aifabrix protection show hubspot-companies
|
|
66
|
+
$ aifabrix protection show hubspot-companies -v
|
|
67
|
+
$ aifabrix protection show hubspot-companies --json
|
|
68
|
+
`;
|
|
69
|
+
|
|
70
|
+
const PROTECTION_DELETE_HELP_AFTER = `
|
|
71
|
+
|
|
72
|
+
Examples:
|
|
73
|
+
$ aifabrix protection delete hubspot-companies
|
|
74
|
+
$ aifabrix protection delete hubspot-companies --yes
|
|
75
|
+
`;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @param {import('commander').Command} cmd
|
|
79
|
+
* @param {string} name
|
|
80
|
+
* @param {string} description
|
|
81
|
+
* @param {Function} action
|
|
82
|
+
* @param {Array<[string, string]>} extraOpts
|
|
83
|
+
* @param {string} helpAfter
|
|
84
|
+
*/
|
|
85
|
+
function addProtectionLeaf(cmd, name, description, action, extraOpts = [], helpAfter = '') {
|
|
86
|
+
const leaf = cmd.command(name).description(description);
|
|
87
|
+
for (const [flags, desc] of [...SHARED_OPTS, ...extraOpts]) {
|
|
88
|
+
leaf.option(flags, desc);
|
|
89
|
+
}
|
|
90
|
+
if (helpAfter) {
|
|
91
|
+
leaf.addHelpText('after', helpAfter);
|
|
92
|
+
}
|
|
93
|
+
leaf.action(async(datasourceKey, options) => {
|
|
94
|
+
try {
|
|
95
|
+
const code = await action(datasourceKey, options);
|
|
96
|
+
if (code && code !== 0) process.exit(code);
|
|
97
|
+
} catch (err) {
|
|
98
|
+
const { formatBlockingError } = require('../utils/cli-test-layout-chalk');
|
|
99
|
+
logger.error(formatBlockingError(err.message || String(err)));
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* @param {import('commander').Command} protection
|
|
107
|
+
*/
|
|
108
|
+
function registerProtectionCreate(protection) {
|
|
109
|
+
const leaf = protection
|
|
110
|
+
.command('create <datasourceKey>')
|
|
111
|
+
.description(
|
|
112
|
+
'Probe dataplane datasource + Controller dimension, then scaffold under integration/.protection/'
|
|
113
|
+
);
|
|
114
|
+
for (const [flags, desc] of SHARED_OPTS) {
|
|
115
|
+
leaf.option(flags, desc);
|
|
116
|
+
}
|
|
117
|
+
leaf
|
|
118
|
+
.option('--type <type>', 'Preset type (country-sales, department-manager, customer-team, project-team, static-region, owner-direct)')
|
|
119
|
+
.option('--dimension-key <key>', 'Dimension catalog key (inferred from --type when omitted)')
|
|
120
|
+
.option('--field <name>', 'Metadata field used by preset value templates when needed')
|
|
121
|
+
.option('--fk-name <name>', 'FK binding name in expressions (default: same as dimension key)')
|
|
122
|
+
.option('--protection-key <key>', 'metadata.key (default: <datasource>-<dimension>-access)')
|
|
123
|
+
.option('--display-name <text>', 'metadata.displayName')
|
|
124
|
+
.option('--rule-key <key>', 'Rule key inside spec.rules[0]')
|
|
125
|
+
.option('--principal-expression <expr>', 'Group principal expression (default: Sales {{fk.<fk>.metadata.iso3}} Users)')
|
|
126
|
+
.option('--value-expression <expr>', 'Grant valueExpression (default: {{fk.<fk>.metadata.iso2}})')
|
|
127
|
+
.option('--dry-run', 'Print YAML to stdout; do not write file')
|
|
128
|
+
.option('--force', 'Overwrite existing integration/.protection/<datasourceKey> manifest')
|
|
129
|
+
.option('--disabled', 'Set spec.enabled to false', false)
|
|
130
|
+
.addHelpText('after', PROTECTION_CREATE_HELP_AFTER)
|
|
131
|
+
.action(async(datasourceKey, options) => {
|
|
132
|
+
try {
|
|
133
|
+
const code = await runProtectionCreate(datasourceKey, {
|
|
134
|
+
...options,
|
|
135
|
+
dryRun: options.dryRun === true,
|
|
136
|
+
force: options.force === true,
|
|
137
|
+
verbose: options.verbose === true,
|
|
138
|
+
disabled: options.disabled === true
|
|
139
|
+
}, logger);
|
|
140
|
+
if (code && code !== 0) process.exit(code);
|
|
141
|
+
} catch (err) {
|
|
142
|
+
const { formatBlockingError } = require('../utils/cli-test-layout-chalk');
|
|
143
|
+
if (Array.isArray(err.probeLines)) {
|
|
144
|
+
for (const line of err.probeLines) {
|
|
145
|
+
logger.log(line);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
logger.error(formatBlockingError(err.message || String(err)));
|
|
149
|
+
process.exit(1);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* @param {import('commander').Command} protection
|
|
156
|
+
*/
|
|
157
|
+
function registerProtectionValidate(protection) {
|
|
158
|
+
addProtectionLeaf(
|
|
159
|
+
protection,
|
|
160
|
+
'validate <datasourceKey>',
|
|
161
|
+
'Validate protection manifest (local schema + dataplane)',
|
|
162
|
+
async(datasourceKey, options) => {
|
|
163
|
+
const resolved = resolveProtectionArgument(datasourceKey);
|
|
164
|
+
return runProtectionValidate(resolved.datasourceKey, resolved.manifest, {
|
|
165
|
+
...options,
|
|
166
|
+
manifestPath: resolved.manifestPath,
|
|
167
|
+
warningsAsErrors: options.warningsAsErrors === true,
|
|
168
|
+
simulate: options.simulate === true,
|
|
169
|
+
json: options.json === true,
|
|
170
|
+
verbose: options.verbose === true
|
|
171
|
+
}, logger);
|
|
172
|
+
},
|
|
173
|
+
[
|
|
174
|
+
['--json', 'Output dataplane report as JSON'],
|
|
175
|
+
['--warnings-as-errors', 'Pass strict=true to dataplane validate'],
|
|
176
|
+
['--simulate', 'Run simulate after validate passes']
|
|
177
|
+
],
|
|
178
|
+
PROTECTION_VALIDATE_HELP_AFTER
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* @param {import('commander').Command} protection
|
|
184
|
+
*/
|
|
185
|
+
function registerProtectionUpload(protection) {
|
|
186
|
+
addProtectionLeaf(
|
|
187
|
+
protection,
|
|
188
|
+
'upload <datasourceKey>',
|
|
189
|
+
'Validate and upload protection manifest to dataplane',
|
|
190
|
+
async(datasourceKey, options) => {
|
|
191
|
+
const resolved = resolveProtectionArgument(datasourceKey);
|
|
192
|
+
return runProtectionUpload(resolved.datasourceKey, resolved.manifest, {
|
|
193
|
+
...options,
|
|
194
|
+
manifestPath: resolved.manifestPath,
|
|
195
|
+
warningsAsErrors: options.warningsAsErrors === true,
|
|
196
|
+
dryRun: options.dryRun === true,
|
|
197
|
+
noSync: options.noSync === true,
|
|
198
|
+
verbose: options.verbose === true
|
|
199
|
+
}, logger);
|
|
200
|
+
},
|
|
201
|
+
[
|
|
202
|
+
['--dry-run', 'Validate only; no upload or sync'],
|
|
203
|
+
['--no-sync', 'Skip datasource sync after upload']
|
|
204
|
+
],
|
|
205
|
+
PROTECTION_UPLOAD_HELP_AFTER
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* @param {import('commander').Command} protection
|
|
211
|
+
*/
|
|
212
|
+
function registerProtectionList(protection) {
|
|
213
|
+
const leaf = protection.command('list').description('List deployed protection manifests on dataplane');
|
|
214
|
+
for (const [flags, desc] of SHARED_OPTS) {
|
|
215
|
+
leaf.option(flags, desc);
|
|
216
|
+
}
|
|
217
|
+
leaf
|
|
218
|
+
.option('--json', 'Output paginated list as JSON')
|
|
219
|
+
.option('--page <n>', 'Page (1-based)', (v) => parseInt(v, 10))
|
|
220
|
+
.option('--page-size <n>', 'Page size', (v) => parseInt(v, 10))
|
|
221
|
+
.option('--filter <expr>', 'Filter (e.g. enabled:eq:true)')
|
|
222
|
+
.addHelpText('after', PROTECTION_LIST_HELP_AFTER)
|
|
223
|
+
.action(async(options) => {
|
|
224
|
+
try {
|
|
225
|
+
const code = await runProtectionList(
|
|
226
|
+
{
|
|
227
|
+
...options,
|
|
228
|
+
json: options.json === true,
|
|
229
|
+
verbose: options.verbose === true
|
|
230
|
+
},
|
|
231
|
+
logger
|
|
232
|
+
);
|
|
233
|
+
if (code && code !== 0) process.exit(code);
|
|
234
|
+
} catch (err) {
|
|
235
|
+
const { formatBlockingError } = require('../utils/cli-test-layout-chalk');
|
|
236
|
+
logger.error(formatBlockingError(err.message || String(err)));
|
|
237
|
+
process.exit(1);
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* @param {import('commander').Command} protection
|
|
244
|
+
*/
|
|
245
|
+
function registerProtectionShow(protection) {
|
|
246
|
+
addProtectionLeaf(
|
|
247
|
+
protection,
|
|
248
|
+
'show <datasourceKey>',
|
|
249
|
+
'Show deployed protection state from dataplane',
|
|
250
|
+
async(datasourceKey, options) =>
|
|
251
|
+
runProtectionShow(datasourceKey, {
|
|
252
|
+
...options,
|
|
253
|
+
json: options.json === true,
|
|
254
|
+
verbose: options.verbose === true
|
|
255
|
+
}, logger),
|
|
256
|
+
[['--json', 'Output merged manifest + status as JSON']],
|
|
257
|
+
PROTECTION_SHOW_HELP_AFTER
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* @param {import('commander').Command} protection
|
|
263
|
+
*/
|
|
264
|
+
function registerProtectionDelete(protection) {
|
|
265
|
+
addProtectionLeaf(
|
|
266
|
+
protection,
|
|
267
|
+
'delete <datasourceKey>',
|
|
268
|
+
'Delete deployed protection for datasource',
|
|
269
|
+
async(datasourceKey, options) =>
|
|
270
|
+
runProtectionDelete(datasourceKey, {
|
|
271
|
+
...options,
|
|
272
|
+
yes: options.yes === true
|
|
273
|
+
}, logger),
|
|
274
|
+
[['--yes', 'Skip confirmation prompt']],
|
|
275
|
+
PROTECTION_DELETE_HELP_AFTER
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
module.exports = {
|
|
280
|
+
registerProtectionCreate,
|
|
281
|
+
registerProtectionValidate,
|
|
282
|
+
registerProtectionUpload,
|
|
283
|
+
registerProtectionList,
|
|
284
|
+
registerProtectionShow,
|
|
285
|
+
registerProtectionDelete
|
|
286
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Protection manifest CLI commands.
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const {
|
|
10
|
+
registerProtectionCreate,
|
|
11
|
+
registerProtectionValidate,
|
|
12
|
+
registerProtectionUpload,
|
|
13
|
+
registerProtectionList,
|
|
14
|
+
registerProtectionShow,
|
|
15
|
+
registerProtectionDelete
|
|
16
|
+
} = require('./protection-cli-leaves');
|
|
17
|
+
|
|
18
|
+
const PROTECTION_HELP_AFTER = `
|
|
19
|
+
|
|
20
|
+
Examples:
|
|
21
|
+
$ aifabrix protection create hubspot-companies --type country-sales
|
|
22
|
+
$ aifabrix protection validate hubspot-companies --simulate
|
|
23
|
+
$ aifabrix protection upload hubspot-companies --dry-run
|
|
24
|
+
$ aifabrix protection list
|
|
25
|
+
$ aifabrix protection show hubspot-companies
|
|
26
|
+
$ aifabrix protection delete hubspot-companies --yes
|
|
27
|
+
|
|
28
|
+
Per-command help: aifabrix protection <command> --help
|
|
29
|
+
`;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {import('commander').Command} program
|
|
33
|
+
*/
|
|
34
|
+
function setupProtectionCommands(program) {
|
|
35
|
+
const protection = program
|
|
36
|
+
.command('protection')
|
|
37
|
+
.description('Manage protection manifests in integration/.protection/ (repo root)')
|
|
38
|
+
.addHelpText('after', PROTECTION_HELP_AFTER);
|
|
39
|
+
|
|
40
|
+
registerProtectionCreate(protection);
|
|
41
|
+
registerProtectionValidate(protection);
|
|
42
|
+
registerProtectionUpload(protection);
|
|
43
|
+
registerProtectionList(protection);
|
|
44
|
+
registerProtectionShow(protection);
|
|
45
|
+
registerProtectionDelete(protection);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
module.exports = {
|
|
49
|
+
setupProtectionCommands
|
|
50
|
+
};
|
package/lib/commands/repair.js
CHANGED
|
@@ -125,11 +125,21 @@ function applyAuthMethod(ctx) {
|
|
|
125
125
|
const existingAuth = ctx.systemParsed.authentication || ctx.systemParsed.auth || {};
|
|
126
126
|
const { buildAuthenticationFromMethod } = require('../external-system/generator');
|
|
127
127
|
const newAuth = buildAuthenticationFromMethod(ctx.systemKey, method);
|
|
128
|
-
const existingVars =
|
|
129
|
-
|
|
128
|
+
const existingVars =
|
|
129
|
+
existingAuth.variables && typeof existingAuth.variables === 'object'
|
|
130
|
+
? existingAuth.variables
|
|
131
|
+
: {};
|
|
132
|
+
// When switching auth method, keep only connectivity fields from the wizard draft.
|
|
133
|
+
// Do not let OAuth-era variables (tokenUrl, scope, headerName, …) override the new method.
|
|
134
|
+
const mergedVariables = { ...newAuth.variables };
|
|
135
|
+
for (const key of ['baseUrl', 'testEndpoint']) {
|
|
136
|
+
if (existingVars[key] !== undefined && existingVars[key] !== null) {
|
|
137
|
+
mergedVariables[key] = existingVars[key];
|
|
138
|
+
}
|
|
139
|
+
}
|
|
130
140
|
ctx.systemParsed.authentication = {
|
|
131
141
|
...newAuth,
|
|
132
|
-
variables:
|
|
142
|
+
variables: mergedVariables
|
|
133
143
|
};
|
|
134
144
|
if (existingAuth.displayName !== undefined) {
|
|
135
145
|
ctx.systemParsed.authentication.displayName = existingAuth.displayName;
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
* - {@link runUpdateImages} — Mode 4: docker pull infra + platform images, up-infra, up-platform.
|
|
10
10
|
*
|
|
11
11
|
* Every handler ends with `up-infra` (idempotent, reads flags from
|
|
12
|
-
* `config.yaml`) followed by `up-platform`.
|
|
12
|
+
* `config.yaml`) followed by `up-platform`. Optional service keys
|
|
13
|
+
* (`traefik`, `pgadmin`, `redisCommander`) are written when missing so the
|
|
14
|
+
* file matches effective compose defaults. Modes 1/2/3 also remove
|
|
13
15
|
* `secrets.local.yaml` so the next platform bootstrap re-resolves
|
|
14
16
|
* service secrets from the catalog and re-prompts the AI tool wizard.
|
|
15
17
|
*
|
|
@@ -49,6 +51,10 @@ const postgresWipe = require('../utils/postgres-wipe');
|
|
|
49
51
|
const setupPrompts = require('./setup-prompts');
|
|
50
52
|
const { handleLogin } = require('./login');
|
|
51
53
|
const infraGuided = require('../cli/infra-guided');
|
|
54
|
+
const {
|
|
55
|
+
computeEffectiveInfraOptionalFlags,
|
|
56
|
+
persistMissingInfraOptionalServiceFlags
|
|
57
|
+
} = require('../utils/infra-optional-service-flags');
|
|
52
58
|
|
|
53
59
|
/** Builder app keys touched by `up-platform --force`. */
|
|
54
60
|
const PLATFORM_APPS = ['keycloak', 'miso-controller', 'dataplane'];
|
|
@@ -203,7 +209,9 @@ function stopSpinnerSuccess(spinner, text) {
|
|
|
203
209
|
/**
|
|
204
210
|
* Start infrastructure using the developer's `config.yaml` flags.
|
|
205
211
|
* Mirrors the relevant slice of `runUpInfraCommand` from `lib/cli/setup-infra.js`
|
|
206
|
-
* without re-applying CLI flag persistence (
|
|
212
|
+
* without re-applying CLI flag persistence (setup passes no Commander flags).
|
|
213
|
+
* After a successful start, missing `traefik` / `pgadmin` / `redisCommander`
|
|
214
|
+
* keys are written to match effective {@link infra.startInfra} options.
|
|
207
215
|
*
|
|
208
216
|
* @async
|
|
209
217
|
* @param {Object} [overrides] - Optional admin overrides (fresh install only)
|
|
@@ -214,17 +222,22 @@ function stopSpinnerSuccess(spinner, text) {
|
|
|
214
222
|
async function startInfraFromConfig(overrides = {}) {
|
|
215
223
|
await config.ensureSecretsEncryptionKey();
|
|
216
224
|
const cfg = await config.getConfig();
|
|
225
|
+
const emailOverride = String(overrides.adminEmail || '').trim();
|
|
226
|
+
const emailFromConfig = typeof cfg.adminEmail === 'string' ? cfg.adminEmail.trim() : '';
|
|
227
|
+
const adminEmailMerged = emailOverride || emailFromConfig || undefined;
|
|
228
|
+
const effective = computeEffectiveInfraOptionalFlags(cfg, {});
|
|
217
229
|
await withMutedLogger(async() => {
|
|
218
230
|
await infra.startInfra(null, {
|
|
219
|
-
traefik:
|
|
220
|
-
pgadmin:
|
|
221
|
-
redisCommander:
|
|
231
|
+
traefik: effective.traefik,
|
|
232
|
+
pgadmin: effective.pgadmin,
|
|
233
|
+
redisCommander: effective.redisCommander,
|
|
222
234
|
adminPassword: overrides.adminPassword,
|
|
223
235
|
adminPwd: overrides.adminPassword,
|
|
224
|
-
adminEmail:
|
|
236
|
+
adminEmail: adminEmailMerged,
|
|
225
237
|
tlsEnabled: cfg.tlsEnabled === true
|
|
226
238
|
});
|
|
227
239
|
});
|
|
240
|
+
await persistMissingInfraOptionalServiceFlags(cfg, effective);
|
|
228
241
|
}
|
|
229
242
|
|
|
230
243
|
/**
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Three small prompt helpers:
|
|
5
5
|
* 1. {@link promptModeSelection} - Mode menu shown when infra is already up.
|
|
6
|
-
* 2. {@link promptAdminCredentials} - Admin email + password (fresh install only)
|
|
6
|
+
* 2. {@link promptAdminCredentials} - Admin email + password (fresh install only); email default
|
|
7
|
+
* from {@link module:lib/core/config.getAdminEmail} when `adminEmail` exists in config.yaml.
|
|
7
8
|
* 3. {@link promptAiTool} - AI tool provider + keys, only when the merged
|
|
8
9
|
* secret cascade (user-local + shared) does not already provide the keys.
|
|
9
10
|
*
|
|
@@ -23,9 +24,11 @@
|
|
|
23
24
|
|
|
24
25
|
'use strict';
|
|
25
26
|
|
|
27
|
+
const path = require('path');
|
|
26
28
|
const inquirer = require('inquirer');
|
|
27
29
|
const chalk = require('chalk');
|
|
28
30
|
const logger = require('../utils/logger');
|
|
31
|
+
const config = require('../core/config');
|
|
29
32
|
const secretsCore = require('../core/secrets');
|
|
30
33
|
const secretsEnsure = require('../core/secrets-ensure');
|
|
31
34
|
const { formatSuccessLine, infoLine } = require('../utils/cli-test-layout-chalk');
|
|
@@ -133,6 +136,8 @@ function validatePassword(input) {
|
|
|
133
136
|
|
|
134
137
|
/**
|
|
135
138
|
* Prompt for admin email + password (fresh install only).
|
|
139
|
+
* Reads {@link module:lib/core/config.getAdminEmail} so a previous `aifabrix setup` can prefill the
|
|
140
|
+
* email field (user may change it before continuing).
|
|
136
141
|
* Asks once for the password and once for confirmation; returns trimmed email
|
|
137
142
|
* and the verbatim password (never logged).
|
|
138
143
|
*
|
|
@@ -140,13 +145,24 @@ function validatePassword(input) {
|
|
|
140
145
|
* @returns {Promise<{ adminEmail: string, adminPassword: string }>}
|
|
141
146
|
*/
|
|
142
147
|
async function promptAdminCredentials() {
|
|
148
|
+
let defaultEmail;
|
|
149
|
+
try {
|
|
150
|
+
const saved = await config.getAdminEmail();
|
|
151
|
+
defaultEmail = saved && saved.trim() ? saved.trim() : undefined;
|
|
152
|
+
} catch {
|
|
153
|
+
defaultEmail = undefined;
|
|
154
|
+
}
|
|
155
|
+
const emailQuestion = {
|
|
156
|
+
type: 'input',
|
|
157
|
+
name: 'adminEmail',
|
|
158
|
+
message: 'Admin email (Keycloak / pgAdmin login):',
|
|
159
|
+
validate: validateEmail
|
|
160
|
+
};
|
|
161
|
+
if (defaultEmail !== undefined) {
|
|
162
|
+
emailQuestion.default = defaultEmail;
|
|
163
|
+
}
|
|
143
164
|
const answers = await inquirer.prompt([
|
|
144
|
-
|
|
145
|
-
type: 'input',
|
|
146
|
-
name: 'adminEmail',
|
|
147
|
-
message: 'Admin email (Keycloak / pgAdmin login):',
|
|
148
|
-
validate: validateEmail
|
|
149
|
-
},
|
|
165
|
+
emailQuestion,
|
|
150
166
|
{
|
|
151
167
|
type: 'password',
|
|
152
168
|
name: 'adminPassword',
|
|
@@ -323,6 +339,22 @@ async function promptAiTool(options = {}) {
|
|
|
323
339
|
);
|
|
324
340
|
}
|
|
325
341
|
|
|
342
|
+
/**
|
|
343
|
+
* Absolute directory paths (with trailing sep) shown when setup will replace platform apps.
|
|
344
|
+
*
|
|
345
|
+
* @param {string} builderRoot - Absolute or relative builder root
|
|
346
|
+
* @param {string[]} platformApps - App folder names (e.g. `keycloak`)
|
|
347
|
+
* @returns {string[]}
|
|
348
|
+
*/
|
|
349
|
+
function formatBuilderPlatformReplaceLines(builderRoot, platformApps) {
|
|
350
|
+
const root = builderRoot && typeof builderRoot === 'string' ? builderRoot : 'builder/';
|
|
351
|
+
const apps = Array.isArray(platformApps) ? platformApps : [];
|
|
352
|
+
return apps.map((a) => {
|
|
353
|
+
const full = path.resolve(path.join(root, a));
|
|
354
|
+
return full.endsWith(path.sep) ? full : `${full}${path.sep}`;
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
|
|
326
358
|
/**
|
|
327
359
|
* When `aifabrix setup` is about to run `up-platform --force`, it will wipe
|
|
328
360
|
* platform app directories under `builder/`. If the builder root already
|
|
@@ -356,7 +388,7 @@ async function promptBuilderDirConflict(info) {
|
|
|
356
388
|
systemNote +
|
|
357
389
|
'\n\n' +
|
|
358
390
|
'This setup path will REPLACE the platform app folders under:\n' +
|
|
359
|
-
` ${
|
|
391
|
+
` ${formatBuilderPlatformReplaceLines(builderRoot, platformApps).join('\n ')}`;
|
|
360
392
|
|
|
361
393
|
const { action } = await inquirer.prompt([
|
|
362
394
|
{
|
|
@@ -379,6 +411,7 @@ module.exports = {
|
|
|
379
411
|
MODE,
|
|
380
412
|
AI_KEYS,
|
|
381
413
|
BUILDER_DIR_ACTION,
|
|
414
|
+
formatBuilderPlatformReplaceLines,
|
|
382
415
|
promptModeSelection,
|
|
383
416
|
confirmDestructiveMode,
|
|
384
417
|
promptAdminCredentials,
|
package/lib/commands/setup.js
CHANGED
|
@@ -29,6 +29,7 @@ const {
|
|
|
29
29
|
|
|
30
30
|
const setupPrompts = require('./setup-prompts');
|
|
31
31
|
const setupModes = require('./setup-modes');
|
|
32
|
+
const installationLog = require('../utils/installation-log');
|
|
32
33
|
|
|
33
34
|
const MODE = setupPrompts.MODE;
|
|
34
35
|
|
|
@@ -57,19 +58,25 @@ async function runFreshInstallFlow(options) {
|
|
|
57
58
|
await maybePinDeveloperIdForFreshInstall(options.developer);
|
|
58
59
|
logger.log(infoLine('No infrastructure detected; starting fresh install.'));
|
|
59
60
|
const adminCreds = await setupPrompts.promptAdminCredentials();
|
|
61
|
+
await config.setAdminEmail(adminCreds.adminEmail);
|
|
60
62
|
await setupModes.runFreshInstall(adminCreds);
|
|
61
63
|
logger.log(formatSuccessParagraph('aifabrix setup complete (fresh install).'));
|
|
62
64
|
}
|
|
63
65
|
|
|
66
|
+
/**
|
|
67
|
+
* @param {boolean} assumeYes
|
|
68
|
+
* @returns {Promise<{ aborted: boolean, mode: string|null }>}
|
|
69
|
+
*/
|
|
64
70
|
async function runExistingInfraFlow(assumeYes) {
|
|
65
71
|
const mode = await setupPrompts.promptModeSelection();
|
|
66
72
|
const proceed = await setupPrompts.confirmDestructiveMode(mode, assumeYes);
|
|
67
73
|
if (!proceed) {
|
|
68
74
|
logger.log(chalk.yellow('Aborted by user.'));
|
|
69
|
-
return;
|
|
75
|
+
return { aborted: true, mode };
|
|
70
76
|
}
|
|
71
77
|
await dispatchMode(mode);
|
|
72
78
|
logger.log(formatSuccessParagraph(`aifabrix setup complete (mode: ${mode}).`));
|
|
79
|
+
return { aborted: false, mode };
|
|
73
80
|
}
|
|
74
81
|
|
|
75
82
|
/**
|
|
@@ -116,6 +123,89 @@ async function dispatchMode(mode) {
|
|
|
116
123
|
}
|
|
117
124
|
}
|
|
118
125
|
|
|
126
|
+
/**
|
|
127
|
+
* @param {Object} options
|
|
128
|
+
* @param {boolean} assumeYes
|
|
129
|
+
* @returns {Promise<{ outcome: string, setupMode: string|null }>}
|
|
130
|
+
*/
|
|
131
|
+
async function runSetupMainPath(options, assumeYes) {
|
|
132
|
+
logSetupHeader();
|
|
133
|
+
logger.log(formatProgress('Detecting current installation state...'));
|
|
134
|
+
const running = await isInfraRunning();
|
|
135
|
+
if (!running) {
|
|
136
|
+
await runFreshInstallFlow(options);
|
|
137
|
+
return { outcome: 'success', setupMode: 'fresh' };
|
|
138
|
+
}
|
|
139
|
+
const r = await runExistingInfraFlow(assumeYes);
|
|
140
|
+
const outcome = r.aborted ? 'aborted' : 'success';
|
|
141
|
+
return { outcome, setupMode: r.mode };
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async function readConfigSnapshotForSetupLog() {
|
|
145
|
+
try {
|
|
146
|
+
return await config.getConfig();
|
|
147
|
+
} catch {
|
|
148
|
+
return {};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function tryCollectPlatformImagesForLog(outcome) {
|
|
153
|
+
if (outcome !== 'success') return undefined;
|
|
154
|
+
try {
|
|
155
|
+
return installationLog.collectPlatformAppImages(['keycloak', 'miso-controller', 'dataplane'], {});
|
|
156
|
+
} catch {
|
|
157
|
+
return undefined;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async function readSetupLogUrlFields() {
|
|
162
|
+
let controllerUrl;
|
|
163
|
+
try {
|
|
164
|
+
controllerUrl = await installationLog.resolveControllerUrlForLog();
|
|
165
|
+
} catch {
|
|
166
|
+
controllerUrl = undefined;
|
|
167
|
+
}
|
|
168
|
+
let adminEmail;
|
|
169
|
+
try {
|
|
170
|
+
adminEmail = await installationLog.resolveAdminEmailPresence();
|
|
171
|
+
} catch {
|
|
172
|
+
adminEmail = 'unset';
|
|
173
|
+
}
|
|
174
|
+
return { controllerUrl, adminEmail };
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* @param {Object} payload
|
|
179
|
+
* @param {string} payload.outcome
|
|
180
|
+
* @param {Date} payload.startedAt
|
|
181
|
+
* @param {Date} payload.completedAt
|
|
182
|
+
* @param {Object} payload.options
|
|
183
|
+
* @param {string|null} payload.setupMode
|
|
184
|
+
* @param {Error|null} payload.err
|
|
185
|
+
*/
|
|
186
|
+
async function appendSetupInstallationRecord(payload) {
|
|
187
|
+
const cfg = await readConfigSnapshotForSetupLog();
|
|
188
|
+
const platformApps = tryCollectPlatformImagesForLog(payload.outcome);
|
|
189
|
+
const { controllerUrl, adminEmail } = await readSetupLogUrlFields();
|
|
190
|
+
try {
|
|
191
|
+
await installationLog.appendInstallationRecord({
|
|
192
|
+
command: 'setup',
|
|
193
|
+
outcome: payload.outcome,
|
|
194
|
+
startedAt: payload.startedAt,
|
|
195
|
+
completedAt: payload.completedAt,
|
|
196
|
+
options: payload.options,
|
|
197
|
+
setupMode: payload.setupMode || undefined,
|
|
198
|
+
infra: cfg && typeof cfg === 'object' ? { cfg, options: {} } : undefined,
|
|
199
|
+
platformApps,
|
|
200
|
+
configExtra: { controllerUrl, adminEmail },
|
|
201
|
+
error: payload.err || undefined,
|
|
202
|
+
errorCode: payload.err && payload.err.code ? String(payload.err.code) : undefined
|
|
203
|
+
});
|
|
204
|
+
} catch {
|
|
205
|
+
// never block setup on log failure
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
119
209
|
/**
|
|
120
210
|
* Run the setup wizard / dispatcher.
|
|
121
211
|
*
|
|
@@ -129,17 +219,32 @@ async function dispatchMode(mode) {
|
|
|
129
219
|
*/
|
|
130
220
|
async function handleSetup(options = {}) {
|
|
131
221
|
const assumeYes = options.yes === true || options.assumeYes === true;
|
|
222
|
+
const startedAt = new Date();
|
|
223
|
+
let outcome = 'success';
|
|
224
|
+
let setupMode = null;
|
|
225
|
+
let err = null;
|
|
132
226
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
227
|
+
try {
|
|
228
|
+
const main = await runSetupMainPath(options, assumeYes);
|
|
229
|
+
outcome = main.outcome;
|
|
230
|
+
setupMode = main.setupMode;
|
|
231
|
+
} catch (e) {
|
|
232
|
+
outcome = 'failure';
|
|
233
|
+
err = e;
|
|
234
|
+
} finally {
|
|
235
|
+
await appendSetupInstallationRecord({
|
|
236
|
+
outcome,
|
|
237
|
+
startedAt,
|
|
238
|
+
completedAt: new Date(),
|
|
239
|
+
options,
|
|
240
|
+
setupMode,
|
|
241
|
+
err
|
|
242
|
+
});
|
|
243
|
+
}
|
|
137
244
|
|
|
138
|
-
if (
|
|
139
|
-
|
|
140
|
-
return;
|
|
245
|
+
if (err) {
|
|
246
|
+
throw err;
|
|
141
247
|
}
|
|
142
|
-
await runExistingInfraFlow(assumeYes);
|
|
143
248
|
}
|
|
144
249
|
|
|
145
250
|
module.exports = {
|