@aifabrix/builder 2.44.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/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/jest.projects.js +15 -2
- package/lib/api/certificates.api.js +62 -0
- package/lib/api/index.js +11 -2
- package/lib/api/types/certificates.types.js +48 -0
- package/lib/api/validation-run.api.js +16 -4
- package/lib/api/validation-runner.js +13 -3
- package/lib/app/certification-show-enrich.js +129 -0
- package/lib/app/certification-verify-rows.js +60 -0
- package/lib/app/show-display.js +43 -0
- package/lib/app/show.js +92 -8
- 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/setup-app.js +4 -0
- package/lib/cli/setup-app.test-commands.js +24 -8
- package/lib/cli/setup-external-system.js +22 -1
- package/lib/cli/setup-secrets.js +34 -13
- package/lib/cli/setup-utility.js +18 -2
- package/lib/commands/app.js +10 -1
- package/lib/commands/datasource-unified-test-cli.js +50 -117
- package/lib/commands/datasource-unified-test-cli.options.js +44 -2
- package/lib/commands/datasource-unified-test-e2e-cli-helpers.js +106 -0
- package/lib/commands/datasource-validation-cli.js +15 -1
- package/lib/commands/datasource.js +25 -2
- package/lib/commands/upload.js +17 -6
- package/lib/datasource/log-viewer.js +105 -14
- package/lib/datasource/test-e2e.js +35 -17
- package/lib/datasource/unified-validation-run-body.js +3 -0
- package/lib/datasource/unified-validation-run.js +2 -1
- package/lib/external-system/deploy.js +53 -18
- package/lib/infrastructure/compose.js +12 -3
- package/lib/infrastructure/helpers-docker-check.js +67 -0
- package/lib/infrastructure/helpers.js +47 -58
- package/lib/infrastructure/index.js +3 -1
- package/lib/infrastructure/services.js +4 -56
- package/lib/schema/external-system.schema.json +25 -3
- package/lib/schema/type/document-storage.json +15 -2
- package/lib/utils/api.js +28 -3
- package/lib/utils/configuration-env-resolver.js +11 -8
- package/lib/utils/credential-secrets-env.js +5 -5
- package/lib/utils/datasource-test-run-certificate-tty.js +82 -0
- package/lib/utils/datasource-test-run-display.js +19 -2
- package/lib/utils/datasource-test-run-exit.js +25 -0
- package/lib/utils/external-system-display.js +8 -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/paths.js +14 -0
- package/lib/utils/validation-run-poll.js +28 -5
- package/lib/utils/validation-run-post-retry.js +20 -8
- package/lib/utils/validation-run-request.js +18 -0
- package/lib/validation/validate-external-cert-sync.js +23 -0
- package/lib/validation/validate.js +4 -1
- package/package.json +4 -3
- package/scripts/install-local.js +4 -1
- package/scripts/pnpm-global-remove.js +48 -0
- package/templates/applications/dataplane/env.template +4 -0
- package/templates/infra/compose.yaml.hbs +15 -14
- package/templates/infra/servers.json.hbs +3 -1
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* @version 2.0.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
const chalk = require('chalk');
|
|
8
|
+
const logger = require('./logger');
|
|
7
9
|
const { getValidationRunWithTransportRetry } = require('./validation-run-post-retry');
|
|
8
10
|
|
|
9
11
|
const INITIAL_INTERVAL_MS = 2000;
|
|
@@ -23,6 +25,19 @@ function sleep(ms) {
|
|
|
23
25
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
24
26
|
}
|
|
25
27
|
|
|
28
|
+
function maybeLogPollProgress(envelope, verbosePoll, lastProgressLogAtRef) {
|
|
29
|
+
if (!verbosePoll || !envelope || typeof envelope !== 'object') return;
|
|
30
|
+
const now = Date.now();
|
|
31
|
+
if (now - lastProgressLogAtRef[0] < 5000) return;
|
|
32
|
+
lastProgressLogAtRef[0] = now;
|
|
33
|
+
const st = envelope.status !== undefined && envelope.status !== null ? String(envelope.status) : '?';
|
|
34
|
+
const c =
|
|
35
|
+
envelope.reportCompleteness !== undefined && envelope.reportCompleteness !== null
|
|
36
|
+
? String(envelope.reportCompleteness)
|
|
37
|
+
: '?';
|
|
38
|
+
logger.log(chalk.gray(` Polling validation run… completeness=${c} status=${st}`));
|
|
39
|
+
}
|
|
40
|
+
|
|
26
41
|
/**
|
|
27
42
|
* Whether polling should stop on this envelope.
|
|
28
43
|
* @param {Object} envelope - DatasourceTestRun-like
|
|
@@ -42,6 +57,8 @@ function isTerminalReportCompleteness(envelope) {
|
|
|
42
57
|
* @param {string} opts.testRunId
|
|
43
58
|
* @param {number} opts.budgetMs - Remaining wall-clock budget for polls only (POST excluded)
|
|
44
59
|
* @param {typeof getValidationRunWithTransportRetry} [opts.fetchRun] - Inject for tests (default: GET with transport retry)
|
|
60
|
+
* @param {boolean} [opts.verbosePoll] - Log throttled progress (plan §3.13)
|
|
61
|
+
* @param {number} [opts.pollRequestTimeoutMs] - Per-GET HTTP timeout (match validation aggregate budget)
|
|
45
62
|
* @returns {Promise<{ envelope: Object|null, timedOut: boolean, lastApiResult: Object|null }>}
|
|
46
63
|
*/
|
|
47
64
|
async function pollValidationRunUntilComplete(opts) {
|
|
@@ -50,18 +67,22 @@ async function pollValidationRunUntilComplete(opts) {
|
|
|
50
67
|
authConfig,
|
|
51
68
|
testRunId,
|
|
52
69
|
budgetMs,
|
|
53
|
-
fetchRun = getValidationRunWithTransportRetry
|
|
70
|
+
fetchRun = getValidationRunWithTransportRetry,
|
|
71
|
+
verbosePoll = false,
|
|
72
|
+
pollRequestTimeoutMs
|
|
54
73
|
} = opts;
|
|
74
|
+
const pollTransportOpts =
|
|
75
|
+
Number.isFinite(pollRequestTimeoutMs) && pollRequestTimeoutMs > 0
|
|
76
|
+
? { timeoutMs: pollRequestTimeoutMs }
|
|
77
|
+
: {};
|
|
55
78
|
const deadline = Date.now() + Math.max(0, budgetMs);
|
|
56
79
|
let attempt = 0;
|
|
57
80
|
let lastApiResult = null;
|
|
58
81
|
let envelope = null;
|
|
82
|
+
const lastProgressLogAtRef = [0];
|
|
59
83
|
|
|
60
84
|
while (Date.now() < deadline) {
|
|
61
|
-
|
|
62
|
-
if (remaining <= 0) break;
|
|
63
|
-
|
|
64
|
-
lastApiResult = await fetchRun(dataplaneUrl, authConfig, testRunId);
|
|
85
|
+
lastApiResult = await fetchRun(dataplaneUrl, authConfig, testRunId, pollTransportOpts);
|
|
65
86
|
if (!lastApiResult.success) {
|
|
66
87
|
return { envelope: null, timedOut: false, lastApiResult };
|
|
67
88
|
}
|
|
@@ -70,6 +91,8 @@ async function pollValidationRunUntilComplete(opts) {
|
|
|
70
91
|
return { envelope, timedOut: false, lastApiResult };
|
|
71
92
|
}
|
|
72
93
|
|
|
94
|
+
maybeLogPollProgress(envelope, verbosePoll, lastProgressLogAtRef);
|
|
95
|
+
|
|
73
96
|
const delay = Math.min(nextPollDelayMs(attempt), Math.max(0, deadline - Date.now()));
|
|
74
97
|
attempt += 1;
|
|
75
98
|
if (delay > 0) {
|
|
@@ -33,18 +33,24 @@ function sleep(ms) {
|
|
|
33
33
|
* @param {string} dataplaneUrl
|
|
34
34
|
* @param {Object} authConfig
|
|
35
35
|
* @param {Object} body
|
|
36
|
+
* @param {Object} [transportOpts] - forwarded to ``postValidationRun`` (e.g. ``timeoutMs``)
|
|
36
37
|
* @returns {Promise<Object>}
|
|
37
38
|
*/
|
|
38
|
-
async function postValidationRunWithTransportRetry(
|
|
39
|
-
|
|
39
|
+
async function postValidationRunWithTransportRetry(
|
|
40
|
+
dataplaneUrl,
|
|
41
|
+
authConfig,
|
|
42
|
+
body,
|
|
43
|
+
transportOpts = {}
|
|
44
|
+
) {
|
|
45
|
+
let last = await postValidationRun(dataplaneUrl, authConfig, body, transportOpts);
|
|
40
46
|
if (last.success || !isRetryablePostFailure(last)) return last;
|
|
41
47
|
|
|
42
48
|
await sleep(1000);
|
|
43
|
-
last = await postValidationRun(dataplaneUrl, authConfig, body);
|
|
49
|
+
last = await postValidationRun(dataplaneUrl, authConfig, body, transportOpts);
|
|
44
50
|
if (last.success || !isRetryablePostFailure(last)) return last;
|
|
45
51
|
|
|
46
52
|
await sleep(2000);
|
|
47
|
-
return postValidationRun(dataplaneUrl, authConfig, body);
|
|
53
|
+
return postValidationRun(dataplaneUrl, authConfig, body, transportOpts);
|
|
48
54
|
}
|
|
49
55
|
|
|
50
56
|
/**
|
|
@@ -52,18 +58,24 @@ async function postValidationRunWithTransportRetry(dataplaneUrl, authConfig, bod
|
|
|
52
58
|
* @param {string} dataplaneUrl
|
|
53
59
|
* @param {Object} authConfig
|
|
54
60
|
* @param {string} testRunId
|
|
61
|
+
* @param {Object} [transportOpts] - forwarded to ``getValidationRun`` (e.g. ``timeoutMs``)
|
|
55
62
|
* @returns {Promise<Object>}
|
|
56
63
|
*/
|
|
57
|
-
async function getValidationRunWithTransportRetry(
|
|
58
|
-
|
|
64
|
+
async function getValidationRunWithTransportRetry(
|
|
65
|
+
dataplaneUrl,
|
|
66
|
+
authConfig,
|
|
67
|
+
testRunId,
|
|
68
|
+
transportOpts = {}
|
|
69
|
+
) {
|
|
70
|
+
let last = await getValidationRun(dataplaneUrl, authConfig, testRunId, transportOpts);
|
|
59
71
|
if (last.success || !isRetryablePostFailure(last)) return last;
|
|
60
72
|
|
|
61
73
|
await sleep(1000);
|
|
62
|
-
last = await getValidationRun(dataplaneUrl, authConfig, testRunId);
|
|
74
|
+
last = await getValidationRun(dataplaneUrl, authConfig, testRunId, transportOpts);
|
|
63
75
|
if (last.success || !isRetryablePostFailure(last)) return last;
|
|
64
76
|
|
|
65
77
|
await sleep(2000);
|
|
66
|
-
return getValidationRun(dataplaneUrl, authConfig, testRunId);
|
|
78
|
+
return getValidationRun(dataplaneUrl, authConfig, testRunId, transportOpts);
|
|
67
79
|
}
|
|
68
80
|
|
|
69
81
|
module.exports = {
|
|
@@ -16,6 +16,21 @@ function includeDebugForRequest(debugOpt) {
|
|
|
16
16
|
return true;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* @param {Object} e2e
|
|
21
|
+
* @param {string} key
|
|
22
|
+
* @param {*} raw
|
|
23
|
+
*/
|
|
24
|
+
function assignOptionalNonNegativeInt(e2e, key, raw) {
|
|
25
|
+
if (raw === undefined || raw === null || raw === '') {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const n = Number(raw);
|
|
29
|
+
if (Number.isFinite(n) && n >= 0) {
|
|
30
|
+
e2e[key] = n;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
19
34
|
/**
|
|
20
35
|
* Merge E2E options from CLI flags into e2eOptions for ExternalDataSourceE2ETestRequest (dataplane).
|
|
21
36
|
* @param {Object} options - CLI-derived options
|
|
@@ -41,6 +56,9 @@ function buildE2eOptionsFromCli(options = {}) {
|
|
|
41
56
|
if (options.primaryKeyValue !== undefined && options.primaryKeyValue !== null) {
|
|
42
57
|
e2e.primaryKeyValue = options.primaryKeyValue;
|
|
43
58
|
}
|
|
59
|
+
assignOptionalNonNegativeInt(e2e, 'minVectorHits', options.minVectorHits);
|
|
60
|
+
assignOptionalNonNegativeInt(e2e, 'minProcessed', options.minProcessed);
|
|
61
|
+
assignOptionalNonNegativeInt(e2e, 'minRecordCount', options.minRecordCount);
|
|
44
62
|
if (options.e2eOptionsExtra && typeof options.e2eOptionsExtra === 'object') {
|
|
45
63
|
Object.assign(e2e, options.e2eOptionsExtra);
|
|
46
64
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Optional certification sync after external validate (keeps validate.js under max-lines).
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 2.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {string} appName
|
|
11
|
+
* @param {Object} options
|
|
12
|
+
* @param {function(string, Object): Promise<Object>} validateExternalSystemComplete
|
|
13
|
+
*/
|
|
14
|
+
async function runExternalValidateWithOptionalCertSync(appName, options, validateExternalSystemComplete) {
|
|
15
|
+
const result = await validateExternalSystemComplete(appName, options);
|
|
16
|
+
if (result.valid && options.certSync === true) {
|
|
17
|
+
const { trySyncCertificationFromDataplaneForExternalApp } = require('../certification/sync-after-external-command');
|
|
18
|
+
await trySyncCertificationFromDataplaneForExternalApp(appName, 'validate');
|
|
19
|
+
}
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = { runExternalValidateWithOptionalCertSync };
|
|
@@ -28,6 +28,7 @@ const {
|
|
|
28
28
|
validateOAuth2GrantTypeAndAuthorizationUrl,
|
|
29
29
|
validateConfigurationNoStandardAuthVariables
|
|
30
30
|
} = require('./external-system-auth-rules');
|
|
31
|
+
const { runExternalValidateWithOptionalCertSync } = require('./validate-external-cert-sync');
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
34
|
* Validates a file path (detects type and validates)
|
|
@@ -462,7 +463,9 @@ async function validateAppOrFile(appOrFile, options = {}) {
|
|
|
462
463
|
const { appPath, isExternal } = await detectAppType(appName);
|
|
463
464
|
logOfflinePathWhenType(appPath);
|
|
464
465
|
|
|
465
|
-
if (isExternal)
|
|
466
|
+
if (isExternal) {
|
|
467
|
+
return await runExternalValidateWithOptionalCertSync(appName, options, validateExternalSystemComplete);
|
|
468
|
+
}
|
|
466
469
|
|
|
467
470
|
const appValidation = await validator.validateApplication(appName, options);
|
|
468
471
|
const rbacValidation = await validateRbacForExternalSystem(isExternal, appName);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aifabrix/builder",
|
|
3
|
-
"version": "2.44.
|
|
3
|
+
"version": "2.44.1",
|
|
4
4
|
"description": "AI Fabrix Local Fabric & Deployment SDK",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"lint:ci": "eslint . --ext .js --format json --output-file eslint-report.json",
|
|
30
30
|
"dev": "node bin/aifabrix.js",
|
|
31
31
|
"build": "npm run lint && npm run test",
|
|
32
|
-
"build:ci": "npm run lint && npm run test:ci",
|
|
32
|
+
"build:ci": "npm run lint && npm run check:schema-sync && npm run check:flags && npm run test:ci",
|
|
33
33
|
"pack": "npm run build && npm pack",
|
|
34
34
|
"validate": "npm run build",
|
|
35
35
|
"prepublishOnly": "npm run validate",
|
|
@@ -37,7 +37,8 @@
|
|
|
37
37
|
"install:local": "node scripts/install-local.js && which aifabrix && which af",
|
|
38
38
|
"uninstall:local": "node scripts/install-local.js uninstall && which aifabrix && which af",
|
|
39
39
|
"diagnose:cli": "node scripts/diagnose-cli.js",
|
|
40
|
-
"check:schema-sync": "node scripts/check-datasource-test-run-schema-sync.js"
|
|
40
|
+
"check:schema-sync": "node scripts/check-datasource-test-run-schema-sync.js",
|
|
41
|
+
"check:flags": "jest tests/lib/schema/flag-map-validation-run.test.js --runInBand --config jest.config.default.js"
|
|
41
42
|
},
|
|
42
43
|
"keywords": [
|
|
43
44
|
"aifabrix",
|
package/scripts/install-local.js
CHANGED
|
@@ -15,6 +15,8 @@ const fs = require('fs');
|
|
|
15
15
|
const os = require('os');
|
|
16
16
|
const path = require('path');
|
|
17
17
|
|
|
18
|
+
const { runPnpmGlobalRemove } = require('./pnpm-global-remove');
|
|
19
|
+
|
|
18
20
|
const PACKAGE_NAME = '@aifabrix/builder';
|
|
19
21
|
/** Primary CLI name used for “current version” before link */
|
|
20
22
|
const PRIMARY_BIN = 'aifabrix';
|
|
@@ -465,7 +467,8 @@ function uninstallLocal() {
|
|
|
465
467
|
|
|
466
468
|
try {
|
|
467
469
|
if (pm === 'pnpm') {
|
|
468
|
-
|
|
470
|
+
const env = { ...pnpmEnv(), CI: 'true' };
|
|
471
|
+
runPnpmGlobalRemove(env, PACKAGE_NAME);
|
|
469
472
|
displayUninstallSuccess(pm, currentVersion);
|
|
470
473
|
} else {
|
|
471
474
|
execSync(`npm unlink -g ${PACKAGE_NAME}`, { stdio: 'inherit' });
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* eslint-disable no-console */
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* pnpm global remove with virtual-store repair retry (pnpm 9+ global layout).
|
|
6
|
+
* @fileoverview Used by install-local.js uninstall path
|
|
7
|
+
* @author AI Fabrix Team
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { execSync } = require('child_process');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @param {unknown} error - Thrown from execSync
|
|
14
|
+
* @returns {boolean} True when `pnpm i -g` repair may fix the failure
|
|
15
|
+
*/
|
|
16
|
+
function isPnpmUnexpectedVirtualStoreError(error) {
|
|
17
|
+
const msg =
|
|
18
|
+
error && typeof error === 'object' && 'message' in error ? String(error.message) : String(error);
|
|
19
|
+
return msg.includes('ERR_PNPM_UNEXPECTED_VIRTUAL_STORE');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {NodeJS.ProcessEnv} env - Environment
|
|
24
|
+
* @returns {void} Nothing
|
|
25
|
+
*/
|
|
26
|
+
function repairPnpmGlobalInstall(env) {
|
|
27
|
+
execSync('pnpm i -g', { stdio: 'inherit', env });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {NodeJS.ProcessEnv} env - pnpm env (e.g. pnpmEnv + CI)
|
|
32
|
+
* @param {string} packageName - Scoped package name to remove globally
|
|
33
|
+
* @returns {void} Nothing
|
|
34
|
+
*/
|
|
35
|
+
function runPnpmGlobalRemove(env, packageName) {
|
|
36
|
+
try {
|
|
37
|
+
execSync(`pnpm remove -g ${packageName}`, { stdio: 'inherit', env });
|
|
38
|
+
} catch (firstError) {
|
|
39
|
+
if (!isPnpmUnexpectedVirtualStoreError(firstError)) throw firstError;
|
|
40
|
+
console.log(
|
|
41
|
+
'\n⚠️ pnpm global virtual store layout mismatch. Running `pnpm i -g` to repair, then retrying remove...\n'
|
|
42
|
+
);
|
|
43
|
+
repairPnpmGlobalInstall(env);
|
|
44
|
+
execSync(`pnpm remove -g ${packageName}`, { stdio: 'inherit', env });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
module.exports = { runPnpmGlobalRemove };
|
|
@@ -185,6 +185,10 @@ CERTIFICATE_PUBLIC_KEY=
|
|
|
185
185
|
# Optional public key identifier for issued certificates; default if unset: dataplane-signing-key
|
|
186
186
|
CERTIFICATE_PUBLIC_KEY_ID=
|
|
187
187
|
|
|
188
|
+
# After a successful POST /api/v1/validation/run (validation engine with certification passed, or E2E success),
|
|
189
|
+
# persist an active integration certificate without a separate issue call. Set false to require explicit issue only.
|
|
190
|
+
VALIDATION_AUTO_ISSUE_INTEGRATION_CERTIFICATE=true
|
|
191
|
+
|
|
188
192
|
# =============================================================================
|
|
189
193
|
# CIP EXECUTION CONFIGURATION
|
|
190
194
|
# =============================================================================
|
|
@@ -56,28 +56,29 @@ services:
|
|
|
56
56
|
PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL}
|
|
57
57
|
PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD}
|
|
58
58
|
PGADMIN_CONFIG_SERVER_MODE: 'False'
|
|
59
|
+
# Docker has no OS password store; without this pgAdmin prompts for a master password on each restart.
|
|
60
|
+
PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED: 'False'
|
|
61
|
+
# load-servers runs without --user in desktop mode; servers attach to DESKTOP_USER (default pgadmin4@pgadmin.org).
|
|
62
|
+
# Must match PGADMIN_DEFAULT_EMAIL or the tree stays empty after login.
|
|
63
|
+
PGADMIN_CONFIG_DESKTOP_USER: "'${PGADMIN_DEFAULT_EMAIL}'"
|
|
59
64
|
PGADMIN_SERVER_JSON_FILE: /pgadmin4/servers.json
|
|
60
65
|
PGADMIN_REPLACE_SERVERS_ON_STARTUP: 'True'
|
|
61
|
-
PGPASS_FILE: /pgpass
|
|
66
|
+
PGPASS_FILE: /pgadmin4/bootstrap.pgpass
|
|
62
67
|
ports:
|
|
63
68
|
- "{{pgadminPort}}:80"
|
|
64
69
|
volumes:
|
|
65
70
|
- {{#if (eq devId 0)}}pgadmin_data{{else}}dev{{devId}}_pgadmin_data{{/if}}:/var/lib/pgadmin
|
|
71
|
+
# File binds under /pgadmin4 (image paths). pgpass must exist before first entrypoint run.
|
|
66
72
|
- type: bind
|
|
67
|
-
source: "{{
|
|
68
|
-
target: /
|
|
73
|
+
source: "{{serversJsonBind}}"
|
|
74
|
+
target: /pgadmin4/servers.json
|
|
69
75
|
read_only: true
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
cp /host-config/pgpass /pgpass;
|
|
77
|
-
chmod 600 /pgpass;
|
|
78
|
-
fi &&
|
|
79
|
-
/entrypoint.sh
|
|
80
|
-
"
|
|
76
|
+
{{#if pgadmin.pgpassBootstrapBind}}
|
|
77
|
+
- type: bind
|
|
78
|
+
source: "{{pgadmin.pgpassBootstrapBind}}"
|
|
79
|
+
target: /pgadmin4/bootstrap.pgpass
|
|
80
|
+
read_only: true
|
|
81
|
+
{{/if}}
|
|
81
82
|
restart: unless-stopped
|
|
82
83
|
depends_on:
|
|
83
84
|
postgres:
|
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
"Port": 5432,
|
|
8
8
|
"MaintenanceDB": "postgres",
|
|
9
9
|
"Username": "pgadmin",
|
|
10
|
-
"PassFile": "/pgpass",
|
|
11
10
|
"SSLMode": "prefer",
|
|
11
|
+
"ConnectionParameters": {
|
|
12
|
+
"passfile": "/pgadmin4/bootstrap.pgpass"
|
|
13
|
+
},
|
|
12
14
|
"Comment": "Auto-registered PostgreSQL server with pgvector extension"
|
|
13
15
|
}
|
|
14
16
|
}
|