@aifabrix/builder 2.31.0 → 2.32.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/README.md +9 -9
- package/integration/hubspot/README.md +2 -2
- package/integration/hubspot/hubspot-deploy-company.json +17 -14
- package/integration/hubspot/hubspot-deploy-contact.json +19 -16
- package/integration/hubspot/hubspot-deploy-deal.json +21 -18
- package/lib/api/types/datasources.types.js +31 -5
- package/lib/api/types/wizard.types.js +142 -0
- package/lib/api/wizard.api.js +177 -0
- package/lib/{app-config.js → app/config.js} +4 -4
- package/lib/{app-deploy.js → app/deploy.js} +8 -8
- package/lib/app/display.js +90 -0
- package/lib/{app-dockerfile.js → app/dockerfile.js} +4 -4
- package/lib/{app-down.js → app/down.js} +4 -4
- package/lib/app/helpers.js +218 -0
- package/lib/app/index.js +298 -0
- package/lib/{app-list.js → app/list.js} +6 -6
- package/lib/{app-push.js → app/push.js} +4 -4
- package/lib/{app-readme.js → app/readme.js} +34 -13
- package/lib/{app-register.js → app/register.js} +9 -9
- package/lib/{app-rotate-secret.js → app/rotate-secret.js} +123 -37
- package/lib/{app-run-helpers.js → app/run-helpers.js} +10 -10
- package/lib/{app-run.js → app/run.js} +6 -6
- package/lib/{build.js → build/index.js} +59 -32
- package/lib/build/package.json +7 -0
- package/lib/cli.js +245 -179
- package/lib/commands/app.js +3 -3
- package/lib/commands/datasource.js +4 -4
- package/lib/commands/login-credentials.js +209 -0
- package/lib/commands/login-device.js +254 -0
- package/lib/commands/login.js +67 -378
- package/lib/commands/logout.js +1 -1
- package/lib/commands/secrets-set.js +1 -1
- package/lib/commands/secure.js +2 -2
- package/lib/commands/wizard.js +498 -0
- package/lib/{audit-logger.js → core/audit-logger.js} +1 -1
- package/lib/{config.js → core/config.js} +28 -26
- package/lib/{diff.js → core/diff.js} +157 -72
- package/lib/{secrets.js → core/secrets.js} +86 -49
- package/lib/{templates.js → core/templates-env.js} +14 -222
- package/lib/core/templates.js +279 -0
- package/lib/{datasource-deploy.js → datasource/deploy.js} +6 -6
- package/lib/{datasource-diff.js → datasource/diff.js} +2 -2
- package/lib/datasource/list.js +223 -0
- package/lib/{datasource-validate.js → datasource/validate.js} +2 -2
- package/lib/{deployer.js → deployment/deployer.js} +48 -18
- package/lib/{environment-deploy.js → deployment/environment.js} +163 -84
- package/lib/{push.js → deployment/push.js} +1 -1
- package/lib/external-system/deploy-helpers.js +145 -0
- package/lib/{external-system-deploy.js → external-system/deploy.js} +156 -111
- package/lib/external-system/download-helpers.js +114 -0
- package/lib/{external-system-download.js → external-system/download.js} +92 -135
- package/lib/{external-system-generator.js → external-system/generator.js} +15 -11
- package/lib/external-system/test-auth.js +40 -0
- package/lib/external-system/test-execution.js +84 -0
- package/lib/external-system/test-helpers.js +109 -0
- package/lib/{external-system-test.js → external-system/test.js} +174 -192
- package/lib/{generator-builders.js → generator/builders.js} +87 -10
- package/lib/{generator-external.js → generator/external.js} +115 -52
- package/lib/{github-generator.js → generator/github.js} +116 -15
- package/lib/{generator-helpers.js → generator/helpers.js} +92 -42
- package/lib/{generator.js → generator/index.js} +49 -22
- package/lib/{generator-split.js → generator/split.js} +108 -55
- package/lib/generator/wizard-prompts.js +357 -0
- package/lib/generator/wizard.js +490 -0
- package/lib/{infra.js → infrastructure/index.js} +49 -22
- package/lib/schema/external-datasource.schema.json +145 -133
- package/lib/schema/external-system.schema.json +42 -0
- package/lib/utils/api.js +9 -5
- package/lib/utils/app-register-api.js +60 -32
- package/lib/utils/app-register-auth.js +172 -47
- package/lib/utils/app-register-config.js +130 -59
- package/lib/utils/app-run-containers.js +29 -8
- package/lib/utils/build-helpers.js +1 -1
- package/lib/utils/cli-utils.js +78 -30
- package/lib/utils/compose-generator.js +145 -65
- package/lib/utils/config-paths.js +2 -0
- package/lib/utils/deployment-errors.js +1 -1
- package/lib/utils/device-code.js +99 -41
- package/lib/utils/env-config-loader.js +1 -1
- package/lib/utils/env-copy.js +21 -18
- package/lib/utils/env-endpoints.js +115 -67
- package/lib/utils/env-map.js +13 -14
- package/lib/utils/env-ports.js +45 -25
- package/lib/utils/env-template.js +84 -42
- package/lib/utils/error-formatter.js +26 -9
- package/lib/utils/error-formatters/error-parser.js +90 -4
- package/lib/utils/error-formatters/http-status-errors.js +54 -17
- package/lib/utils/error-formatters/network-errors.js +103 -26
- package/lib/utils/external-system-display.js +184 -90
- package/lib/utils/external-system-validators.js +164 -42
- package/lib/utils/file-upload.js +109 -0
- package/lib/utils/health-check.js +199 -83
- package/lib/utils/infra-containers.js +1 -1
- package/lib/utils/infra-status.js +66 -15
- package/lib/utils/local-secrets.js +45 -25
- package/lib/utils/paths.js +45 -33
- package/lib/utils/schema-loader.js +42 -25
- package/lib/utils/schema-resolver.js +123 -74
- package/lib/utils/secrets-encryption.js +62 -25
- package/lib/utils/secrets-helpers.js +126 -63
- package/lib/utils/secrets-path.js +1 -1
- package/lib/utils/secrets-url.js +1 -1
- package/lib/utils/token-manager-refresh.js +181 -0
- package/lib/utils/token-manager.js +76 -123
- package/lib/utils/variable-transformer.js +154 -77
- package/lib/utils/yaml-preserve.js +41 -47
- package/lib/{template-validator.js → validation/template.js} +54 -23
- package/lib/{validate.js → validation/validate.js} +205 -125
- package/lib/{validator.js → validation/validator.js} +58 -39
- package/package.json +34 -3
- package/scripts/install-local.js +210 -0
- package/templates/external-system/deploy.ps1.hbs +34 -0
- package/templates/external-system/deploy.sh.hbs +34 -0
- package/templates/external-system/external-datasource.json.hbs +31 -12
- package/lib/app.js +0 -467
- package/lib/datasource-list.js +0 -141
- /package/lib/{app-prompts.js → app/prompts.js} +0 -0
- /package/lib/{env-reader.js → core/env-reader.js} +0 -0
- /package/lib/{key-generator.js → core/key-generator.js} +0 -0
|
@@ -1,136 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Environment Template Generation
|
|
3
3
|
*
|
|
4
|
-
* Generates
|
|
5
|
-
*
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Generate variables.yaml content for an application
|
|
12
|
-
* Matches application-schema.json structure
|
|
13
|
-
* @param {string} appName - Application name
|
|
14
|
-
* @param {Object} config - Configuration options
|
|
15
|
-
* @returns {string} YAML content
|
|
4
|
+
* Generates env.template content with conditional variables
|
|
5
|
+
*
|
|
6
|
+
* @fileoverview Environment template generation for AI Fabrix Builder
|
|
7
|
+
* @author AI Fabrix Team
|
|
8
|
+
* @version 2.0.0
|
|
16
9
|
*/
|
|
17
|
-
function generateVariablesYaml(appName, config) {
|
|
18
|
-
const displayName = appName.replace(/-/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
|
|
19
|
-
const appType = config.type || 'webapp';
|
|
20
|
-
|
|
21
|
-
// For external type, create minimal variables.yaml
|
|
22
|
-
if (appType === 'external') {
|
|
23
|
-
// Use config values if provided, otherwise use defaults consistent with prompts
|
|
24
|
-
const systemKey = config.systemKey || appName;
|
|
25
|
-
const systemDisplayName = config.systemDisplayName || displayName;
|
|
26
|
-
const systemDescription = config.systemDescription || `External system integration for ${appName}`;
|
|
27
|
-
|
|
28
|
-
const variables = {
|
|
29
|
-
app: {
|
|
30
|
-
key: systemKey,
|
|
31
|
-
displayName: systemDisplayName,
|
|
32
|
-
description: systemDescription,
|
|
33
|
-
type: 'external'
|
|
34
|
-
},
|
|
35
|
-
deployment: {
|
|
36
|
-
controllerUrl: '',
|
|
37
|
-
environment: 'dev'
|
|
38
|
-
},
|
|
39
|
-
externalIntegration: {
|
|
40
|
-
schemaBasePath: './',
|
|
41
|
-
systems: [],
|
|
42
|
-
dataSources: [],
|
|
43
|
-
autopublish: true,
|
|
44
|
-
version: '1.0.0'
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
return yaml.dump(variables, {
|
|
49
|
-
indent: 2,
|
|
50
|
-
lineWidth: 120,
|
|
51
|
-
noRefs: true,
|
|
52
|
-
sortKeys: false
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Parse image name to separate name and tag
|
|
57
|
-
let imageName = appName;
|
|
58
|
-
let imageTag = 'latest';
|
|
59
|
-
const imageNameWithTag = `${appName}:latest`;
|
|
60
|
-
const colonIndex = imageNameWithTag.lastIndexOf(':');
|
|
61
|
-
if (colonIndex !== -1) {
|
|
62
|
-
imageName = imageNameWithTag.substring(0, colonIndex);
|
|
63
|
-
imageTag = imageNameWithTag.substring(colonIndex + 1);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const variables = {
|
|
67
|
-
app: {
|
|
68
|
-
key: appName,
|
|
69
|
-
displayName: displayName,
|
|
70
|
-
description: `${appName.replace(/-/g, ' ')} application`,
|
|
71
|
-
type: appType
|
|
72
|
-
},
|
|
73
|
-
image: {
|
|
74
|
-
name: imageName,
|
|
75
|
-
tag: imageTag,
|
|
76
|
-
registry: '',
|
|
77
|
-
registryMode: 'external'
|
|
78
|
-
},
|
|
79
|
-
port: parseInt(config.port, 10) || 3000,
|
|
80
|
-
requires: {
|
|
81
|
-
database: config.database || false,
|
|
82
|
-
redis: config.redis || false,
|
|
83
|
-
storage: config.storage || false
|
|
84
|
-
},
|
|
85
|
-
build: {
|
|
86
|
-
language: config.language || 'typescript',
|
|
87
|
-
envOutputPath: null,
|
|
88
|
-
context: null, // Defaults to dev directory in build process
|
|
89
|
-
dockerfile: ''
|
|
90
|
-
},
|
|
91
|
-
repository: {
|
|
92
|
-
enabled: false,
|
|
93
|
-
repositoryUrl: ''
|
|
94
|
-
},
|
|
95
|
-
deployment: {
|
|
96
|
-
controllerUrl: '',
|
|
97
|
-
environment: 'dev'
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
// Add databases array when database is enabled
|
|
102
|
-
if (config.database) {
|
|
103
|
-
// Database names must match schema pattern: ^[a-z0-9_]+$ (no hyphens)
|
|
104
|
-
const dbName = appName.replace(/-/g, '_');
|
|
105
|
-
variables.requires.databases = [
|
|
106
|
-
{ name: dbName }
|
|
107
|
-
];
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Add optional healthCheck at top level
|
|
111
|
-
if (config.healthCheck !== false) {
|
|
112
|
-
variables.healthCheck = {
|
|
113
|
-
path: '/health',
|
|
114
|
-
interval: 30
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Add optional authentication at top level
|
|
119
|
-
if (config.authentication) {
|
|
120
|
-
variables.authentication = {
|
|
121
|
-
type: 'azure',
|
|
122
|
-
enableSSO: true,
|
|
123
|
-
requiredRoles: ['aifabrix-user']
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return yaml.dump(variables, {
|
|
128
|
-
indent: 2,
|
|
129
|
-
lineWidth: 120,
|
|
130
|
-
noRefs: true,
|
|
131
|
-
sortKeys: false
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
10
|
|
|
135
11
|
/**
|
|
136
12
|
* Builds core application environment variables
|
|
@@ -401,98 +277,14 @@ function generateEnvTemplate(config, existingEnv = {}) {
|
|
|
401
277
|
return lines.join('\n');
|
|
402
278
|
}
|
|
403
279
|
|
|
404
|
-
function generateRbacYaml(appName, config) {
|
|
405
|
-
if (!config.authentication) {
|
|
406
|
-
return null;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
// Format roles with name, value, and description
|
|
410
|
-
const roles = [
|
|
411
|
-
{
|
|
412
|
-
name: 'AI Fabrix Admin',
|
|
413
|
-
value: 'aifabrix-admin',
|
|
414
|
-
description: 'Full access to all application features and configurations'
|
|
415
|
-
},
|
|
416
|
-
{
|
|
417
|
-
name: 'AI Fabrix User',
|
|
418
|
-
value: 'aifabrix-user',
|
|
419
|
-
description: 'Basic user access to the application'
|
|
420
|
-
},
|
|
421
|
-
{
|
|
422
|
-
name: 'AI Fabrix Developer',
|
|
423
|
-
value: 'aifabrix-developer',
|
|
424
|
-
description: 'Developer access for testing and debugging'
|
|
425
|
-
}
|
|
426
|
-
];
|
|
427
|
-
|
|
428
|
-
// Format permissions with name, roles array, and description
|
|
429
|
-
const permissions = [
|
|
430
|
-
{
|
|
431
|
-
name: `${appName}:read`,
|
|
432
|
-
roles: ['aifabrix-user', 'aifabrix-admin', 'aifabrix-developer'],
|
|
433
|
-
description: 'Read access to application data'
|
|
434
|
-
},
|
|
435
|
-
{
|
|
436
|
-
name: `${appName}:write`,
|
|
437
|
-
roles: ['aifabrix-admin', 'aifabrix-developer'],
|
|
438
|
-
description: 'Create and edit application data'
|
|
439
|
-
},
|
|
440
|
-
{
|
|
441
|
-
name: `${appName}:delete`,
|
|
442
|
-
roles: ['aifabrix-admin'],
|
|
443
|
-
description: 'Delete application data'
|
|
444
|
-
},
|
|
445
|
-
{
|
|
446
|
-
name: `${appName}:admin`,
|
|
447
|
-
roles: ['aifabrix-admin'],
|
|
448
|
-
description: 'Administrative access to application configuration'
|
|
449
|
-
}
|
|
450
|
-
];
|
|
451
|
-
|
|
452
|
-
const rbac = {
|
|
453
|
-
roles: roles,
|
|
454
|
-
permissions: permissions
|
|
455
|
-
};
|
|
456
|
-
|
|
457
|
-
return yaml.dump(rbac, {
|
|
458
|
-
indent: 2,
|
|
459
|
-
lineWidth: 120,
|
|
460
|
-
noRefs: true,
|
|
461
|
-
sortKeys: false
|
|
462
|
-
});
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
function generateSecretsYaml(config, existingSecrets = {}) {
|
|
466
|
-
const secrets = {
|
|
467
|
-
apiVersion: 'v1',
|
|
468
|
-
kind: 'Secret',
|
|
469
|
-
metadata: { name: 'app-secrets', namespace: 'default' },
|
|
470
|
-
type: 'Opaque',
|
|
471
|
-
data: {}
|
|
472
|
-
};
|
|
473
|
-
if (config.database) {
|
|
474
|
-
secrets.data['database-password'] = 'base64-encoded-password';
|
|
475
|
-
secrets.data['database-user'] = 'base64-encoded-user';
|
|
476
|
-
}
|
|
477
|
-
if (config.redis) {
|
|
478
|
-
secrets.data['redis-passwordKeyVault'] = 'base64-encoded-redis-password';
|
|
479
|
-
}
|
|
480
|
-
if (config.storage) {
|
|
481
|
-
secrets.data['storage-key'] = 'base64-encoded-storage-key';
|
|
482
|
-
secrets.data['storage-secret'] = 'base64-encoded-storage-secret';
|
|
483
|
-
}
|
|
484
|
-
if (config.authentication) {
|
|
485
|
-
secrets.data['miso-controller-jwt-secretKeyVault'] = 'base64-encoded-miso-controller-jwt-secretKeyVault';
|
|
486
|
-
}
|
|
487
|
-
Object.entries(existingSecrets).forEach(([key, value]) => {
|
|
488
|
-
secrets.data[key] = Buffer.from(value).toString('base64');
|
|
489
|
-
});
|
|
490
|
-
return yaml.dump(secrets, { indent: 2, lineWidth: 120, noRefs: true, sortKeys: false });
|
|
491
|
-
}
|
|
492
|
-
|
|
493
280
|
module.exports = {
|
|
494
|
-
generateVariablesYaml,
|
|
495
281
|
generateEnvTemplate,
|
|
496
|
-
|
|
497
|
-
|
|
282
|
+
buildCoreEnv,
|
|
283
|
+
buildPythonEnv,
|
|
284
|
+
buildDatabaseEnv,
|
|
285
|
+
buildRedisEnv,
|
|
286
|
+
buildStorageEnv,
|
|
287
|
+
buildAuthEnv,
|
|
288
|
+
buildMonitoringEnv
|
|
498
289
|
};
|
|
290
|
+
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* YAML Template Generation Module
|
|
3
|
+
*
|
|
4
|
+
* Generates configuration files for AI Fabrix applications
|
|
5
|
+
* following ISO 27001 security standards
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const yaml = require('js-yaml');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Generate variables.yaml content for an application
|
|
12
|
+
* Matches application-schema.json structure
|
|
13
|
+
* @param {string} appName - Application name
|
|
14
|
+
* @param {Object} config - Configuration options
|
|
15
|
+
* @returns {string} YAML content
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Generates external system variables
|
|
19
|
+
* @function generateExternalSystemVariables
|
|
20
|
+
* @param {string} appName - Application name
|
|
21
|
+
* @param {string} displayName - Display name
|
|
22
|
+
* @param {Object} config - Configuration
|
|
23
|
+
* @returns {Object} Variables object
|
|
24
|
+
*/
|
|
25
|
+
function generateExternalSystemVariables(appName, displayName, config) {
|
|
26
|
+
const systemKey = config.systemKey || appName;
|
|
27
|
+
const systemDisplayName = config.systemDisplayName || displayName;
|
|
28
|
+
const systemDescription = config.systemDescription || `External system integration for ${appName}`;
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
app: {
|
|
32
|
+
key: systemKey,
|
|
33
|
+
displayName: systemDisplayName,
|
|
34
|
+
description: systemDescription,
|
|
35
|
+
type: 'external'
|
|
36
|
+
},
|
|
37
|
+
deployment: {
|
|
38
|
+
controllerUrl: '',
|
|
39
|
+
environment: 'dev'
|
|
40
|
+
},
|
|
41
|
+
externalIntegration: {
|
|
42
|
+
schemaBasePath: './',
|
|
43
|
+
systems: [],
|
|
44
|
+
dataSources: [],
|
|
45
|
+
autopublish: true,
|
|
46
|
+
version: '1.0.0'
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Parses image name and tag
|
|
53
|
+
* @function parseImageNameAndTag
|
|
54
|
+
* @param {string} appName - Application name
|
|
55
|
+
* @returns {Object} Object with imageName and imageTag
|
|
56
|
+
*/
|
|
57
|
+
function parseImageNameAndTag(appName) {
|
|
58
|
+
const imageNameWithTag = `${appName}:latest`;
|
|
59
|
+
const colonIndex = imageNameWithTag.lastIndexOf(':');
|
|
60
|
+
if (colonIndex !== -1) {
|
|
61
|
+
return {
|
|
62
|
+
imageName: imageNameWithTag.substring(0, colonIndex),
|
|
63
|
+
imageTag: imageNameWithTag.substring(colonIndex + 1)
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return { imageName: appName, imageTag: 'latest' };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Builds base variables object for webapp
|
|
71
|
+
* @function buildWebappVariables
|
|
72
|
+
* @param {string} appName - Application name
|
|
73
|
+
* @param {string} displayName - Display name
|
|
74
|
+
* @param {Object} config - Configuration
|
|
75
|
+
* @param {string} imageName - Image name
|
|
76
|
+
* @param {string} imageTag - Image tag
|
|
77
|
+
* @returns {Object} Variables object
|
|
78
|
+
*/
|
|
79
|
+
function buildWebappVariables(appName, displayName, config, imageName, imageTag) {
|
|
80
|
+
const appType = config.type || 'webapp';
|
|
81
|
+
return {
|
|
82
|
+
app: {
|
|
83
|
+
key: appName,
|
|
84
|
+
displayName: displayName,
|
|
85
|
+
description: `${appName.replace(/-/g, ' ')} application`,
|
|
86
|
+
type: appType
|
|
87
|
+
},
|
|
88
|
+
image: {
|
|
89
|
+
name: imageName,
|
|
90
|
+
tag: imageTag,
|
|
91
|
+
registry: '',
|
|
92
|
+
registryMode: 'external'
|
|
93
|
+
},
|
|
94
|
+
port: parseInt(config.port, 10) || 3000,
|
|
95
|
+
requires: {
|
|
96
|
+
database: config.database || false,
|
|
97
|
+
redis: config.redis || false,
|
|
98
|
+
storage: config.storage || false
|
|
99
|
+
},
|
|
100
|
+
build: {
|
|
101
|
+
language: config.language || 'typescript',
|
|
102
|
+
envOutputPath: null,
|
|
103
|
+
context: null, // Defaults to dev directory in build process
|
|
104
|
+
dockerfile: ''
|
|
105
|
+
},
|
|
106
|
+
repository: {
|
|
107
|
+
enabled: false,
|
|
108
|
+
repositoryUrl: ''
|
|
109
|
+
},
|
|
110
|
+
deployment: {
|
|
111
|
+
controllerUrl: '',
|
|
112
|
+
environment: 'dev'
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Adds optional fields to variables
|
|
119
|
+
* @function addOptionalFieldsToVariables
|
|
120
|
+
* @param {Object} variables - Variables object
|
|
121
|
+
* @param {Object} config - Configuration
|
|
122
|
+
* @param {string} appName - Application name
|
|
123
|
+
*/
|
|
124
|
+
function addOptionalFieldsToVariables(variables, config, appName) {
|
|
125
|
+
// Add databases array when database is enabled
|
|
126
|
+
if (config.database) {
|
|
127
|
+
// Database names must match schema pattern: ^[a-z0-9_]+$ (no hyphens)
|
|
128
|
+
const dbName = appName.replace(/-/g, '_');
|
|
129
|
+
variables.requires.databases = [{ name: dbName }];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Add optional healthCheck at top level
|
|
133
|
+
if (config.healthCheck !== false) {
|
|
134
|
+
variables.healthCheck = {
|
|
135
|
+
path: '/health',
|
|
136
|
+
interval: 30
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Add optional authentication at top level
|
|
141
|
+
if (config.authentication) {
|
|
142
|
+
variables.authentication = {
|
|
143
|
+
type: 'azure',
|
|
144
|
+
enableSSO: true,
|
|
145
|
+
requiredRoles: ['aifabrix-user']
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Dumps variables to YAML string
|
|
152
|
+
* @function dumpVariablesToYaml
|
|
153
|
+
* @param {Object} variables - Variables object
|
|
154
|
+
* @returns {string} YAML string
|
|
155
|
+
*/
|
|
156
|
+
function dumpVariablesToYaml(variables) {
|
|
157
|
+
return yaml.dump(variables, {
|
|
158
|
+
indent: 2,
|
|
159
|
+
lineWidth: 120,
|
|
160
|
+
noRefs: true,
|
|
161
|
+
sortKeys: false
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function generateVariablesYaml(appName, config) {
|
|
166
|
+
const displayName = appName.replace(/-/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
|
|
167
|
+
const appType = config.type || 'webapp';
|
|
168
|
+
|
|
169
|
+
// For external type, create minimal variables.yaml
|
|
170
|
+
if (appType === 'external') {
|
|
171
|
+
const variables = generateExternalSystemVariables(appName, displayName, config);
|
|
172
|
+
return dumpVariablesToYaml(variables);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Parse image name to separate name and tag
|
|
176
|
+
const { imageName, imageTag } = parseImageNameAndTag(appName);
|
|
177
|
+
const variables = buildWebappVariables(appName, displayName, config, imageName, imageTag);
|
|
178
|
+
addOptionalFieldsToVariables(variables, config, appName);
|
|
179
|
+
|
|
180
|
+
return dumpVariablesToYaml(variables);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const { generateEnvTemplate } = require('./templates-env');
|
|
184
|
+
|
|
185
|
+
function generateRbacYaml(appName, config) {
|
|
186
|
+
if (!config.authentication) {
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Format roles with name, value, and description
|
|
191
|
+
const roles = [
|
|
192
|
+
{
|
|
193
|
+
name: 'AI Fabrix Admin',
|
|
194
|
+
value: 'aifabrix-admin',
|
|
195
|
+
description: 'Full access to all application features and configurations'
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
name: 'AI Fabrix User',
|
|
199
|
+
value: 'aifabrix-user',
|
|
200
|
+
description: 'Basic user access to the application'
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
name: 'AI Fabrix Developer',
|
|
204
|
+
value: 'aifabrix-developer',
|
|
205
|
+
description: 'Developer access for testing and debugging'
|
|
206
|
+
}
|
|
207
|
+
];
|
|
208
|
+
|
|
209
|
+
// Format permissions with name, roles array, and description
|
|
210
|
+
const permissions = [
|
|
211
|
+
{
|
|
212
|
+
name: `${appName}:read`,
|
|
213
|
+
roles: ['aifabrix-user', 'aifabrix-admin', 'aifabrix-developer'],
|
|
214
|
+
description: 'Read access to application data'
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
name: `${appName}:write`,
|
|
218
|
+
roles: ['aifabrix-admin', 'aifabrix-developer'],
|
|
219
|
+
description: 'Create and edit application data'
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
name: `${appName}:delete`,
|
|
223
|
+
roles: ['aifabrix-admin'],
|
|
224
|
+
description: 'Delete application data'
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
name: `${appName}:admin`,
|
|
228
|
+
roles: ['aifabrix-admin'],
|
|
229
|
+
description: 'Administrative access to application configuration'
|
|
230
|
+
}
|
|
231
|
+
];
|
|
232
|
+
|
|
233
|
+
const rbac = {
|
|
234
|
+
roles: roles,
|
|
235
|
+
permissions: permissions
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
return yaml.dump(rbac, {
|
|
239
|
+
indent: 2,
|
|
240
|
+
lineWidth: 120,
|
|
241
|
+
noRefs: true,
|
|
242
|
+
sortKeys: false
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function generateSecretsYaml(config, existingSecrets = {}) {
|
|
247
|
+
const secrets = {
|
|
248
|
+
apiVersion: 'v1',
|
|
249
|
+
kind: 'Secret',
|
|
250
|
+
metadata: { name: 'app-secrets', namespace: 'default' },
|
|
251
|
+
type: 'Opaque',
|
|
252
|
+
data: {}
|
|
253
|
+
};
|
|
254
|
+
if (config.database) {
|
|
255
|
+
secrets.data['database-password'] = 'base64-encoded-password';
|
|
256
|
+
secrets.data['database-user'] = 'base64-encoded-user';
|
|
257
|
+
}
|
|
258
|
+
if (config.redis) {
|
|
259
|
+
secrets.data['redis-passwordKeyVault'] = 'base64-encoded-redis-password';
|
|
260
|
+
}
|
|
261
|
+
if (config.storage) {
|
|
262
|
+
secrets.data['storage-key'] = 'base64-encoded-storage-key';
|
|
263
|
+
secrets.data['storage-secret'] = 'base64-encoded-storage-secret';
|
|
264
|
+
}
|
|
265
|
+
if (config.authentication) {
|
|
266
|
+
secrets.data['miso-controller-jwt-secretKeyVault'] = 'base64-encoded-miso-controller-jwt-secretKeyVault';
|
|
267
|
+
}
|
|
268
|
+
Object.entries(existingSecrets).forEach(([key, value]) => {
|
|
269
|
+
secrets.data[key] = Buffer.from(value).toString('base64');
|
|
270
|
+
});
|
|
271
|
+
return yaml.dump(secrets, { indent: 2, lineWidth: 120, noRefs: true, sortKeys: false });
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
module.exports = {
|
|
275
|
+
generateVariablesYaml,
|
|
276
|
+
generateEnvTemplate,
|
|
277
|
+
generateRbacYaml,
|
|
278
|
+
generateSecretsYaml
|
|
279
|
+
};
|
|
@@ -11,12 +11,12 @@
|
|
|
11
11
|
|
|
12
12
|
const fs = require('fs');
|
|
13
13
|
const chalk = require('chalk');
|
|
14
|
-
const { getDeploymentAuth } = require('
|
|
15
|
-
const { getEnvironmentApplication } = require('
|
|
16
|
-
const { publishDatasourceViaPipeline } = require('
|
|
17
|
-
const { formatApiError } = require('
|
|
18
|
-
const logger = require('
|
|
19
|
-
const { validateDatasourceFile } = require('./
|
|
14
|
+
const { getDeploymentAuth } = require('../utils/token-manager');
|
|
15
|
+
const { getEnvironmentApplication } = require('../api/environments.api');
|
|
16
|
+
const { publishDatasourceViaPipeline } = require('../api/pipeline.api');
|
|
17
|
+
const { formatApiError } = require('../utils/api-error-handler');
|
|
18
|
+
const logger = require('../utils/logger');
|
|
19
|
+
const { validateDatasourceFile } = require('./validate');
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Gets dataplane URL from controller by fetching application details
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
const chalk = require('chalk');
|
|
13
|
-
const { compareFiles, formatDiffOutput } = require('
|
|
14
|
-
const logger = require('
|
|
13
|
+
const { compareFiles, formatDiffOutput } = require('../core/diff');
|
|
14
|
+
const logger = require('../utils/logger');
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Compares two datasource files with focus on dataplane-relevant fields
|