@aifabrix/builder 2.44.6 → 2.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/cli-layout.mdc +7 -3
- package/jest.projects.js +56 -0
- 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/infra-guided.js +42 -27
- package/lib/cli/installation-log-command.js +73 -0
- package/lib/cli/setup-app.js +11 -1
- package/lib/cli/setup-auth.js +94 -49
- 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-resolve.js +132 -0
- package/lib/cli/setup-utility.js +65 -51
- package/lib/commands/app-logs.js +81 -33
- package/lib/commands/auth-config.js +116 -18
- 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/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 +5 -3
- package/lib/core/audit-logger.js +1 -34
- package/lib/core/config-admin-email.js +56 -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/external-system/deploy.js +5 -1
- package/lib/internal/node-fs.js +2 -0
- package/lib/schema/application-schema.json +4 -0
- package/lib/schema/infra.parameter.yaml +10 -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/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/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/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 +162 -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/system-builder-root.js +10 -2
- 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/package.json +3 -1
- package/templates/applications/dataplane/application.yaml +4 -0
- package/templates/applications/miso-controller/application.yaml +2 -0
- package/templates/applications/miso-controller/env.template +27 -29
- package/.npmrc.token +0 -1
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `aifabrix up-dataplane` action body (keeps setup-infra.js under size limits).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview up-dataplane CLI action
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 2.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const chalk = require('chalk');
|
|
12
|
+
const logger = require('../utils/logger');
|
|
13
|
+
const { formatProgress } = require('../utils/cli-test-layout-chalk');
|
|
14
|
+
const { handleCommandError, isAuthenticationError } = require('../utils/cli-utils');
|
|
15
|
+
const { resolveControllerUrl } = require('../utils/controller-url');
|
|
16
|
+
const { handleLogin } = require('../commands/login');
|
|
17
|
+
const { handleUpDataplane } = require('../commands/up-dataplane');
|
|
18
|
+
const { cleanBuilderAppDirs } = require('../commands/up-common');
|
|
19
|
+
const { runGuidedUpDataplane } = require('./infra-guided');
|
|
20
|
+
const { recordInfraInstallationCommand } = require('./installation-log-command');
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {Object} options
|
|
24
|
+
* @returns {Promise<string[]>}
|
|
25
|
+
*/
|
|
26
|
+
async function runUpDataplaneWork(options) {
|
|
27
|
+
let cleanedAppKeys = [];
|
|
28
|
+
if (options.force) {
|
|
29
|
+
const c = await cleanBuilderAppDirs(['dataplane']);
|
|
30
|
+
cleanedAppKeys = Array.isArray(c) ? c : [];
|
|
31
|
+
}
|
|
32
|
+
if (!options.verbose) {
|
|
33
|
+
await runGuidedUpDataplane(options, handleUpDataplane);
|
|
34
|
+
} else {
|
|
35
|
+
await handleUpDataplane(options);
|
|
36
|
+
}
|
|
37
|
+
return cleanedAppKeys;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @param {Object} params
|
|
42
|
+
* @returns {Promise<void>}
|
|
43
|
+
*/
|
|
44
|
+
async function logDataplaneOutcome(params) {
|
|
45
|
+
const { options, startedAt, outcome, error, cleanedAppKeys } = params;
|
|
46
|
+
await recordInfraInstallationCommand({
|
|
47
|
+
command: 'up-dataplane',
|
|
48
|
+
options,
|
|
49
|
+
startedAt,
|
|
50
|
+
outcome,
|
|
51
|
+
error,
|
|
52
|
+
platformAppList: ['dataplane'],
|
|
53
|
+
cleanup: cleanedAppKeys.length > 0 ? { cleanedAppKeys } : undefined
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @param {Object} options
|
|
59
|
+
* @param {Date} startedAt
|
|
60
|
+
* @param {string[]} cleanedAppKeys
|
|
61
|
+
* @param {string} controllerUrl
|
|
62
|
+
* @returns {Promise<void>}
|
|
63
|
+
*/
|
|
64
|
+
async function runDataplaneAuthRecovery(options, startedAt, cleanedAppKeys, controllerUrl) {
|
|
65
|
+
if (!options.verbose) {
|
|
66
|
+
logger.log(formatProgress('Authenticating...'));
|
|
67
|
+
} else {
|
|
68
|
+
logger.log(chalk.blue('\nAuthentication required. Running aifabrix login...\n'));
|
|
69
|
+
}
|
|
70
|
+
await handleLogin({ method: 'device', controller: controllerUrl, compact: !options.verbose });
|
|
71
|
+
await handleUpDataplane(options);
|
|
72
|
+
await logDataplaneOutcome({ options, startedAt, outcome: 'success', cleanedAppKeys });
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @param {Object} options
|
|
77
|
+
* @returns {Promise<void>}
|
|
78
|
+
*/
|
|
79
|
+
async function handleUpDataplaneCliAction(options) {
|
|
80
|
+
const startedAt = new Date();
|
|
81
|
+
let cleanedAppKeys = [];
|
|
82
|
+
try {
|
|
83
|
+
cleanedAppKeys = await runUpDataplaneWork(options);
|
|
84
|
+
await logDataplaneOutcome({ options, startedAt, outcome: 'success', cleanedAppKeys });
|
|
85
|
+
} catch (error) {
|
|
86
|
+
if (isAuthenticationError(error)) {
|
|
87
|
+
const controllerUrl = error.controllerUrl || await resolveControllerUrl();
|
|
88
|
+
try {
|
|
89
|
+
await runDataplaneAuthRecovery(options, startedAt, cleanedAppKeys, controllerUrl);
|
|
90
|
+
return;
|
|
91
|
+
} catch (loginOrRetryError) {
|
|
92
|
+
await logDataplaneOutcome({
|
|
93
|
+
options,
|
|
94
|
+
startedAt,
|
|
95
|
+
outcome: 'failure',
|
|
96
|
+
error: loginOrRetryError,
|
|
97
|
+
cleanedAppKeys
|
|
98
|
+
});
|
|
99
|
+
handleCommandError(loginOrRetryError, 'up-dataplane');
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
await logDataplaneOutcome({ options, startedAt, outcome: 'failure', error, cleanedAppKeys });
|
|
104
|
+
handleCommandError(error, 'up-dataplane');
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
module.exports = {
|
|
110
|
+
handleUpDataplaneCliAction
|
|
111
|
+
};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `aifabrix up-platform` action body (keeps setup-infra.js under size limits).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview up-platform CLI action
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 2.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const chalk = require('chalk');
|
|
12
|
+
const logger = require('../utils/logger');
|
|
13
|
+
const { formatProgress } = require('../utils/cli-test-layout-chalk');
|
|
14
|
+
const { handleCommandError, isAuthenticationError } = require('../utils/cli-utils');
|
|
15
|
+
const { resolveControllerUrl } = require('../utils/controller-url');
|
|
16
|
+
const { handleLogin } = require('../commands/login');
|
|
17
|
+
const { handleUpMiso } = require('../commands/up-miso');
|
|
18
|
+
const { handleUpDataplane } = require('../commands/up-dataplane');
|
|
19
|
+
const {
|
|
20
|
+
applyUpPlatformForceConfig,
|
|
21
|
+
cleanBuilderAppDirs,
|
|
22
|
+
prepareUrlsLocalRegistryForUpPlatform
|
|
23
|
+
} = require('../commands/up-common');
|
|
24
|
+
const { runGuidedUpPlatform } = require('./infra-guided');
|
|
25
|
+
const { recordInfraInstallationCommand } = require('./installation-log-command');
|
|
26
|
+
|
|
27
|
+
const PLATFORM_APPS = ['keycloak', 'miso-controller', 'dataplane'];
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {Object} options
|
|
31
|
+
* @returns {Promise<string[]>}
|
|
32
|
+
*/
|
|
33
|
+
async function runUpPlatformWork(options) {
|
|
34
|
+
let cleanedAppKeys = [];
|
|
35
|
+
let platformForceCleanSummary = null;
|
|
36
|
+
if (options.force) {
|
|
37
|
+
const forceSummary = await applyUpPlatformForceConfig({ silent: !options.verbose });
|
|
38
|
+
const cleanedApps = await cleanBuilderAppDirs(PLATFORM_APPS, {
|
|
39
|
+
silent: !options.verbose
|
|
40
|
+
});
|
|
41
|
+
cleanedAppKeys = Array.isArray(cleanedApps) ? cleanedApps : [];
|
|
42
|
+
if (!options.verbose) {
|
|
43
|
+
platformForceCleanSummary = { forceSummary, cleanedApps: cleanedAppKeys };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (!options.verbose) {
|
|
48
|
+
await runGuidedUpPlatform(
|
|
49
|
+
options,
|
|
50
|
+
handleUpMiso,
|
|
51
|
+
handleUpDataplane,
|
|
52
|
+
handleLogin,
|
|
53
|
+
platformForceCleanSummary
|
|
54
|
+
);
|
|
55
|
+
} else {
|
|
56
|
+
await prepareUrlsLocalRegistryForUpPlatform();
|
|
57
|
+
await handleUpMiso(options);
|
|
58
|
+
await handleUpDataplane(options);
|
|
59
|
+
}
|
|
60
|
+
return cleanedAppKeys;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @param {Object} params
|
|
65
|
+
* @returns {Promise<void>}
|
|
66
|
+
*/
|
|
67
|
+
async function logUpPlatformOutcome(params) {
|
|
68
|
+
const { options, startedAt, outcome, error, cleanedAppKeys } = params;
|
|
69
|
+
await recordInfraInstallationCommand({
|
|
70
|
+
command: 'up-platform',
|
|
71
|
+
options,
|
|
72
|
+
startedAt,
|
|
73
|
+
outcome,
|
|
74
|
+
error,
|
|
75
|
+
platformAppList: PLATFORM_APPS,
|
|
76
|
+
cleanup: cleanedAppKeys.length > 0 ? { cleanedAppKeys } : undefined,
|
|
77
|
+
upPlatformForce: options.force === true
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async function maybeHandleUpPlatformAuthRetry(error, options) {
|
|
82
|
+
if (!isAuthenticationError(error)) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
const controllerUrl = error.controllerUrl || await resolveControllerUrl();
|
|
86
|
+
if (!options.verbose) {
|
|
87
|
+
logger.log(formatProgress('Authenticating...'));
|
|
88
|
+
} else {
|
|
89
|
+
logger.log(chalk.blue('\nAuthentication required. Running aifabrix login...\n'));
|
|
90
|
+
}
|
|
91
|
+
await handleLogin({ method: 'device', controller: controllerUrl, compact: !options.verbose });
|
|
92
|
+
await handleUpDataplane(options);
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @param {Object} options
|
|
98
|
+
* @returns {Promise<void>}
|
|
99
|
+
*/
|
|
100
|
+
async function handleUpPlatformCliAction(options) {
|
|
101
|
+
const startedAt = new Date();
|
|
102
|
+
let cleanedAppKeys = [];
|
|
103
|
+
try {
|
|
104
|
+
cleanedAppKeys = await runUpPlatformWork(options);
|
|
105
|
+
await logUpPlatformOutcome({ options, startedAt, outcome: 'success', cleanedAppKeys });
|
|
106
|
+
} catch (error) {
|
|
107
|
+
try {
|
|
108
|
+
if (await maybeHandleUpPlatformAuthRetry(error, options)) {
|
|
109
|
+
await logUpPlatformOutcome({ options, startedAt, outcome: 'success', cleanedAppKeys });
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
} catch (loginOrRetryError) {
|
|
113
|
+
await logUpPlatformOutcome({
|
|
114
|
+
options,
|
|
115
|
+
startedAt,
|
|
116
|
+
outcome: 'failure',
|
|
117
|
+
error: loginOrRetryError,
|
|
118
|
+
cleanedAppKeys
|
|
119
|
+
});
|
|
120
|
+
handleCommandError(loginOrRetryError, 'up-platform');
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
await logUpPlatformOutcome({ options, startedAt, outcome: 'failure', error, cleanedAppKeys });
|
|
124
|
+
handleCommandError(error, 'up-platform');
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
module.exports = {
|
|
130
|
+
handleUpPlatformCliAction
|
|
131
|
+
};
|
package/lib/cli/setup-infra.js
CHANGED
|
@@ -12,22 +12,14 @@ const {
|
|
|
12
12
|
* @version 2.0.0
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
const chalk = require('chalk');
|
|
16
15
|
const infra = require('../infrastructure');
|
|
17
16
|
const appLib = require('../app');
|
|
18
17
|
const config = require('../core/config');
|
|
19
18
|
const logger = require('../utils/logger');
|
|
20
|
-
const { handleCommandError
|
|
21
|
-
const { resolveControllerUrl } = require('../utils/controller-url');
|
|
22
|
-
const { handleLogin } = require('../commands/login');
|
|
19
|
+
const { handleCommandError } = require('../utils/cli-utils');
|
|
23
20
|
const { handleUpMiso } = require('../commands/up-miso');
|
|
24
|
-
const {
|
|
25
|
-
const {
|
|
26
|
-
applyUpPlatformForceConfig,
|
|
27
|
-
cleanBuilderAppDirs,
|
|
28
|
-
prepareUrlsLocalRegistryForUpPlatform
|
|
29
|
-
} = require('../commands/up-common');
|
|
30
|
-
const { runGuidedUpInfra, runGuidedUpMiso, runGuidedUpDataplane, runGuidedUpPlatform, runGuidedDownInfra } = require('./infra-guided');
|
|
21
|
+
const { cleanBuilderAppDirs } = require('../commands/up-common');
|
|
22
|
+
const { runGuidedUpInfra, runGuidedUpMiso, runGuidedDownInfra } = require('./infra-guided');
|
|
31
23
|
const {
|
|
32
24
|
loadInfraStatusSummary,
|
|
33
25
|
formatInfraStatusTitleLine,
|
|
@@ -40,6 +32,11 @@ const {
|
|
|
40
32
|
buildRestartInfraHelpLines
|
|
41
33
|
} = require('../constants/infra-compose-service-names');
|
|
42
34
|
|
|
35
|
+
const {
|
|
36
|
+
computeEffectiveInfraOptionalFlags,
|
|
37
|
+
persistMissingInfraOptionalServiceFlags
|
|
38
|
+
} = require('../utils/infra-optional-service-flags');
|
|
39
|
+
|
|
43
40
|
const UP_INFRA_HELP_AFTER = `
|
|
44
41
|
Typical sequence:
|
|
45
42
|
$ aifabrix up-infra
|
|
@@ -83,19 +80,6 @@ async function persistTlsEnabledFlag(cfg, value) {
|
|
|
83
80
|
));
|
|
84
81
|
}
|
|
85
82
|
|
|
86
|
-
/**
|
|
87
|
-
* Resolves effective boolean from option vs config.
|
|
88
|
-
* @param {*} optValue - options.traefik | options.pgAdmin | options.redisAdmin
|
|
89
|
-
* @param {*} cfgValue - cfg.traefik | cfg.pgadmin | cfg.redisCommander
|
|
90
|
-
* @param {boolean} defaultWhenUndef - Default when config value is undefined
|
|
91
|
-
* @returns {boolean}
|
|
92
|
-
*/
|
|
93
|
-
function resolveFlag(optValue, cfgValue, defaultWhenUndef = true) {
|
|
94
|
-
if (optValue === true) return true;
|
|
95
|
-
if (optValue === false) return false;
|
|
96
|
-
return cfgValue !== false && (cfgValue === true || defaultWhenUndef);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
83
|
/**
|
|
100
84
|
* @param {Object} options - Commander options
|
|
101
85
|
* @returns {Promise<number|null>} Developer ID or null
|
|
@@ -152,31 +136,18 @@ async function runUpInfraCommand(options) {
|
|
|
152
136
|
await maybePersistTlsFromUpInfra(options, cfg);
|
|
153
137
|
const adminPass = options.adminPassword || options.adminPwd;
|
|
154
138
|
const tlsEnabledEffective = cfg.tlsEnabled === true;
|
|
139
|
+
const effective = computeEffectiveInfraOptionalFlags(cfg, options);
|
|
155
140
|
await infra.startInfra(developerId, {
|
|
156
|
-
traefik:
|
|
157
|
-
pgadmin:
|
|
158
|
-
redisCommander:
|
|
141
|
+
traefik: effective.traefik,
|
|
142
|
+
pgadmin: effective.pgadmin,
|
|
143
|
+
redisCommander: effective.redisCommander,
|
|
159
144
|
adminPassword: adminPass,
|
|
160
145
|
adminPwd: adminPass,
|
|
161
146
|
adminEmail: options.adminEmail,
|
|
162
147
|
userPassword: options.userPassword,
|
|
163
148
|
tlsEnabled: tlsEnabledEffective
|
|
164
149
|
});
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
async function maybeHandleUpPlatformAuthRetry(error, options) {
|
|
168
|
-
if (!isAuthenticationError(error)) {
|
|
169
|
-
return false;
|
|
170
|
-
}
|
|
171
|
-
const controllerUrl = error.controllerUrl || await resolveControllerUrl();
|
|
172
|
-
if (!options.verbose) {
|
|
173
|
-
logger.log(formatProgress('Authenticating...'));
|
|
174
|
-
} else {
|
|
175
|
-
logger.log(chalk.blue('\nAuthentication required. Running aifabrix login...\n'));
|
|
176
|
-
}
|
|
177
|
-
await handleLogin({ method: 'device', controller: controllerUrl, compact: !options.verbose });
|
|
178
|
-
await handleUpDataplane(options);
|
|
179
|
-
return true;
|
|
150
|
+
await persistMissingInfraOptionalServiceFlags(cfg, effective);
|
|
180
151
|
}
|
|
181
152
|
|
|
182
153
|
function setupUpInfraCommand(program) {
|
|
@@ -197,14 +168,28 @@ function setupUpInfraCommand(program) {
|
|
|
197
168
|
.option('--tls', 'Enable TLS mode; save tlsEnabled (${TLS_ENABLED}=true, ${HTTP_ENABLED}=false in application.yaml)')
|
|
198
169
|
.option('--no-tls', 'Disable TLS mode (${TLS_ENABLED}=false, ${HTTP_ENABLED}=true)')
|
|
199
170
|
.action(async(options) => {
|
|
171
|
+
const startedAt = new Date();
|
|
172
|
+
const { recordInfraInstallationCommand } = require('./installation-log-command');
|
|
200
173
|
try {
|
|
201
174
|
if (!options.verbose) {
|
|
202
175
|
await runGuidedUpInfra(options, runUpInfraCommand);
|
|
203
|
-
|
|
176
|
+
} else {
|
|
177
|
+
await runUpInfraCommand(options);
|
|
204
178
|
}
|
|
205
|
-
|
|
206
|
-
|
|
179
|
+
await recordInfraInstallationCommand({
|
|
180
|
+
command: 'up-infra',
|
|
181
|
+
options,
|
|
182
|
+
startedAt,
|
|
183
|
+
outcome: 'success'
|
|
184
|
+
});
|
|
207
185
|
} catch (error) {
|
|
186
|
+
await recordInfraInstallationCommand({
|
|
187
|
+
command: 'up-infra',
|
|
188
|
+
options,
|
|
189
|
+
startedAt,
|
|
190
|
+
outcome: 'failure',
|
|
191
|
+
error
|
|
192
|
+
});
|
|
208
193
|
handleCommandError(error, 'up-infra');
|
|
209
194
|
process.exit(1);
|
|
210
195
|
}
|
|
@@ -223,45 +208,9 @@ function setupUpPlatformCommand(program) {
|
|
|
223
208
|
'-f, --force',
|
|
224
209
|
'Reset CLI auth (clear all device/client tokens, set environment to dev, set default controller URL from developer-id), clean builder/keycloak, builder/miso-controller, builder/dataplane, then re-fetch from templates'
|
|
225
210
|
)
|
|
226
|
-
.action(
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
if (options.force) {
|
|
230
|
-
const forceSummary = await applyUpPlatformForceConfig({ silent: !options.verbose });
|
|
231
|
-
const cleanedApps = await cleanBuilderAppDirs(['keycloak', 'miso-controller', 'dataplane'], {
|
|
232
|
-
silent: !options.verbose
|
|
233
|
-
});
|
|
234
|
-
if (!options.verbose) {
|
|
235
|
-
platformForceCleanSummary = { forceSummary, cleanedApps };
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
if (!options.verbose) {
|
|
240
|
-
await runGuidedUpPlatform(
|
|
241
|
-
options,
|
|
242
|
-
handleUpMiso,
|
|
243
|
-
handleUpDataplane,
|
|
244
|
-
handleLogin,
|
|
245
|
-
platformForceCleanSummary
|
|
246
|
-
);
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
await prepareUrlsLocalRegistryForUpPlatform();
|
|
251
|
-
await handleUpMiso(options);
|
|
252
|
-
await handleUpDataplane(options);
|
|
253
|
-
} catch (error) {
|
|
254
|
-
try {
|
|
255
|
-
if (await maybeHandleUpPlatformAuthRetry(error, options)) {
|
|
256
|
-
return;
|
|
257
|
-
}
|
|
258
|
-
} catch (loginOrRetryError) {
|
|
259
|
-
handleCommandError(loginOrRetryError, 'up-platform');
|
|
260
|
-
process.exit(1);
|
|
261
|
-
}
|
|
262
|
-
handleCommandError(error, 'up-platform');
|
|
263
|
-
process.exit(1);
|
|
264
|
-
}
|
|
211
|
+
.action((options) => {
|
|
212
|
+
const { handleUpPlatformCliAction } = require('./setup-infra-up-platform-action');
|
|
213
|
+
return handleUpPlatformCliAction(options);
|
|
265
214
|
});
|
|
266
215
|
}
|
|
267
216
|
|
|
@@ -275,17 +224,37 @@ function setupUpMisoCommand(program) {
|
|
|
275
224
|
.option('-f, --force', 'Clean builder/keycloak and builder/miso-controller and re-fetch from templates')
|
|
276
225
|
.option('--verbose', 'Show full orchestration output (default is guided summary)')
|
|
277
226
|
.action(async(options) => {
|
|
227
|
+
const startedAt = new Date();
|
|
228
|
+
const { recordInfraInstallationCommand } = require('./installation-log-command');
|
|
229
|
+
let cleanedAppKeys = [];
|
|
278
230
|
try {
|
|
279
231
|
if (options.force) {
|
|
280
|
-
await cleanBuilderAppDirs(['keycloak', 'miso-controller']);
|
|
232
|
+
const c = await cleanBuilderAppDirs(['keycloak', 'miso-controller']);
|
|
233
|
+
cleanedAppKeys = Array.isArray(c) ? c : [];
|
|
281
234
|
}
|
|
282
235
|
if (!options.verbose) {
|
|
283
236
|
await runGuidedUpMiso(options, handleUpMiso);
|
|
284
|
-
|
|
237
|
+
} else {
|
|
238
|
+
await handleUpMiso(options);
|
|
285
239
|
}
|
|
286
|
-
|
|
287
|
-
|
|
240
|
+
await recordInfraInstallationCommand({
|
|
241
|
+
command: 'up-miso',
|
|
242
|
+
options,
|
|
243
|
+
startedAt,
|
|
244
|
+
outcome: 'success',
|
|
245
|
+
platformAppList: ['keycloak', 'miso-controller'],
|
|
246
|
+
cleanup: cleanedAppKeys.length > 0 ? { cleanedAppKeys } : undefined
|
|
247
|
+
});
|
|
288
248
|
} catch (error) {
|
|
249
|
+
await recordInfraInstallationCommand({
|
|
250
|
+
command: 'up-miso',
|
|
251
|
+
options,
|
|
252
|
+
startedAt,
|
|
253
|
+
outcome: 'failure',
|
|
254
|
+
error,
|
|
255
|
+
platformAppList: ['keycloak', 'miso-controller'],
|
|
256
|
+
cleanup: cleanedAppKeys.length > 0 ? { cleanedAppKeys } : undefined
|
|
257
|
+
});
|
|
289
258
|
handleCommandError(error, 'up-miso');
|
|
290
259
|
process.exit(1);
|
|
291
260
|
}
|
|
@@ -301,37 +270,9 @@ function setupUpDataplaneCommand(program) {
|
|
|
301
270
|
.option('--base', 'Resolve dataplane image from manifest only when running locally (default: true)', true)
|
|
302
271
|
.option('-f, --force', 'Clean builder/dataplane and re-fetch from templates')
|
|
303
272
|
.option('--verbose', 'Show full orchestration output (default is guided summary)')
|
|
304
|
-
.action(
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
await cleanBuilderAppDirs(['dataplane']);
|
|
308
|
-
}
|
|
309
|
-
if (!options.verbose) {
|
|
310
|
-
await runGuidedUpDataplane(options, handleUpDataplane);
|
|
311
|
-
return;
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
await handleUpDataplane(options);
|
|
315
|
-
} catch (error) {
|
|
316
|
-
if (isAuthenticationError(error)) {
|
|
317
|
-
const controllerUrl = error.controllerUrl || await resolveControllerUrl();
|
|
318
|
-
if (!options.verbose) {
|
|
319
|
-
logger.log(formatProgress('Authenticating...'));
|
|
320
|
-
} else {
|
|
321
|
-
logger.log(chalk.blue('\nAuthentication required. Running aifabrix login...\n'));
|
|
322
|
-
}
|
|
323
|
-
try {
|
|
324
|
-
await handleLogin({ method: 'device', controller: controllerUrl, compact: !options.verbose });
|
|
325
|
-
await handleUpDataplane(options);
|
|
326
|
-
return;
|
|
327
|
-
} catch (loginOrRetryError) {
|
|
328
|
-
handleCommandError(loginOrRetryError, 'up-dataplane');
|
|
329
|
-
process.exit(1);
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
handleCommandError(error, 'up-dataplane');
|
|
333
|
-
process.exit(1);
|
|
334
|
-
}
|
|
273
|
+
.action((options) => {
|
|
274
|
+
const { handleUpDataplaneCliAction } = require('./setup-infra-up-dataplane-action');
|
|
275
|
+
return handleUpDataplaneCliAction(options);
|
|
335
276
|
});
|
|
336
277
|
}
|
|
337
278
|
|
|
@@ -23,7 +23,7 @@ const { handleTeardown } = require('../commands/teardown');
|
|
|
23
23
|
|
|
24
24
|
const SETUP_HELP_AFTER = `
|
|
25
25
|
What this command does:
|
|
26
|
-
- With no infra running: prompts for admin email/password (used for Postgres, pgAdmin, Keycloak)
|
|
26
|
+
- With no infra running: prompts for admin email/password (used for Postgres, pgAdmin, Keycloak). The email is saved as adminEmail in config.yaml so the next setup can show it as the default (you can still change it). Prompts for an AI tool (OpenAI or Azure OpenAI) only when keys are not already set, then runs up-infra and up-platform.
|
|
27
27
|
- With infra running: shows a mode menu:
|
|
28
28
|
1) Re-install — stop infra and remove all volumes, then up-infra + up-platform --force.
|
|
29
29
|
2) Wipe data — drop every database and DB user, then up-infra + up-platform --force.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `aifabrix resolve <app>` command wiring (split from setup-utility for file/function size limits).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Resolve CLI command
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const chalk = require('chalk');
|
|
12
|
+
const secrets = require('../core/secrets');
|
|
13
|
+
const logger = require('../utils/logger');
|
|
14
|
+
const { handleCommandError } = require('../utils/cli-utils');
|
|
15
|
+
const coreConfig = require('../core/config');
|
|
16
|
+
const { resolvePreferLocalEnvOutputPathFlag } = require('../utils/applications-config-defaults');
|
|
17
|
+
const { getResolveAppPath } = require('../utils/paths');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {string} appName
|
|
21
|
+
* @param {string} appPath
|
|
22
|
+
* @param {boolean} envOnly
|
|
23
|
+
* @param {string} envPath
|
|
24
|
+
* @param {{ skipValidation?: boolean }} options
|
|
25
|
+
* @param {{ getManifestSourcePayload: function }} manifestEmit
|
|
26
|
+
* @returns {Promise<void>}
|
|
27
|
+
*/
|
|
28
|
+
async function runResolveJsonOutput(appName, appPath, envOnly, envPath, options, manifestEmit) {
|
|
29
|
+
/** @type {Record<string, unknown>} */
|
|
30
|
+
const payload = {
|
|
31
|
+
app: appName,
|
|
32
|
+
appPath,
|
|
33
|
+
envOnly,
|
|
34
|
+
envPath,
|
|
35
|
+
manifestSource: envOnly ? null : manifestEmit.getManifestSourcePayload(appName, appPath)
|
|
36
|
+
};
|
|
37
|
+
if (!envOnly && !options.skipValidation) {
|
|
38
|
+
const validate = require('../validation/validate');
|
|
39
|
+
payload.validation = await validate.validateAppOrFile(appName);
|
|
40
|
+
}
|
|
41
|
+
logger.log(JSON.stringify(payload, null, 2));
|
|
42
|
+
const v = payload.validation;
|
|
43
|
+
if (v && typeof v === 'object' && v.valid === false) {
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @param {string} appName
|
|
50
|
+
* @param {string} envPath
|
|
51
|
+
* @param {boolean} envOnly
|
|
52
|
+
* @param {{ skipValidation?: boolean }} options
|
|
53
|
+
* @returns {Promise<void>}
|
|
54
|
+
*/
|
|
55
|
+
async function runResolveHumanOutput(appName, envPath, envOnly, options) {
|
|
56
|
+
logger.log(`✔ Generated .env file: ${envPath}`);
|
|
57
|
+
logger.log(chalk.gray(' Note: up-platform / up-miso / up-dataplane / register / build resolve secrets in memory only.'));
|
|
58
|
+
logger.log(chalk.gray(` Re-run "aifabrix resolve ${appName}" whenever you need an on-disk .env again.`));
|
|
59
|
+
if (envOnly) {
|
|
60
|
+
logger.log(chalk.gray(' (env-only mode: validation skipped; no application config file)'));
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (options.skipValidation) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const validate = require('../validation/validate');
|
|
67
|
+
const result = await validate.validateAppOrFile(appName);
|
|
68
|
+
validate.displayValidationResults(result);
|
|
69
|
+
if (!result.valid) {
|
|
70
|
+
logger.log(chalk.yellow('\n⚠ Validation found errors. Fix them before deploying.'));
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @param {string} appName
|
|
77
|
+
* @param {{ force?: boolean, skipValidation?: boolean, json?: boolean }} options
|
|
78
|
+
* @returns {Promise<void>}
|
|
79
|
+
*/
|
|
80
|
+
async function runResolveAppAction(appName, options) {
|
|
81
|
+
const jsonMode = options.json === true;
|
|
82
|
+
const { appPath, envOnly } = await getResolveAppPath(appName);
|
|
83
|
+
const manifestEmit = require('../utils/manifest-source-emit');
|
|
84
|
+
manifestEmit.emitManifestMetadataLineIfTTY(logger, {
|
|
85
|
+
appKey: appName,
|
|
86
|
+
appPath,
|
|
87
|
+
envOnly,
|
|
88
|
+
json: jsonMode
|
|
89
|
+
});
|
|
90
|
+
const userCfg = await coreConfig.getConfig();
|
|
91
|
+
const preferLocalEnvOutputPath = await resolvePreferLocalEnvOutputPathFlag(userCfg, appName);
|
|
92
|
+
const envPath = await secrets.generateEnvFile(
|
|
93
|
+
appName,
|
|
94
|
+
undefined,
|
|
95
|
+
'docker',
|
|
96
|
+
options.force,
|
|
97
|
+
{
|
|
98
|
+
appPath,
|
|
99
|
+
envOnly,
|
|
100
|
+
skipOutputPath: false,
|
|
101
|
+
preserveFromPath: null,
|
|
102
|
+
preferLocalEnvOutputPath
|
|
103
|
+
}
|
|
104
|
+
);
|
|
105
|
+
if (jsonMode) {
|
|
106
|
+
await runResolveJsonOutput(appName, appPath, envOnly, envPath, options, manifestEmit);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
await runResolveHumanOutput(appName, envPath, envOnly, options);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @param {import('commander').Command} program
|
|
114
|
+
* @returns {void}
|
|
115
|
+
*/
|
|
116
|
+
function setupResolveCommand(program) {
|
|
117
|
+
program.command('resolve <app>')
|
|
118
|
+
.description('Generate .env from template; optional validate after')
|
|
119
|
+
.option('-f, --force', 'Generate missing secret keys in secrets file')
|
|
120
|
+
.option('--skip-validation', 'Skip file validation after generating .env')
|
|
121
|
+
.option('--json', 'Print JSON summary (envPath, manifestSource, optional validation)')
|
|
122
|
+
.action(async(appName, options) => {
|
|
123
|
+
try {
|
|
124
|
+
await runResolveAppAction(appName, options);
|
|
125
|
+
} catch (error) {
|
|
126
|
+
handleCommandError(error, 'resolve');
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
module.exports = { setupResolveCommand };
|