@envsync-cloud/deploy-cli 0.8.8 → 0.8.10
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/dist/index.js +97 -6
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4334,6 +4334,7 @@ function domainMap(rootDomain) {
|
|
|
4334
4334
|
landing: rootDomain,
|
|
4335
4335
|
app: `app.${rootDomain}`,
|
|
4336
4336
|
api: `api.${rootDomain}`,
|
|
4337
|
+
manage_api: `manage-api.${rootDomain}`,
|
|
4337
4338
|
auth: `auth.${rootDomain}`,
|
|
4338
4339
|
obs: `obs.${rootDomain}`,
|
|
4339
4340
|
mail: `mail.${rootDomain}`,
|
|
@@ -4397,6 +4398,8 @@ function buildRuntimeEnv2(config, generated) {
|
|
|
4397
4398
|
const hosts = domainMap(config.domain.root_domain);
|
|
4398
4399
|
const bucketName = "envsync-bucket";
|
|
4399
4400
|
const oss = isOssConfig(config);
|
|
4401
|
+
const enterprise = !oss;
|
|
4402
|
+
const license = config.license ?? {};
|
|
4400
4403
|
return {
|
|
4401
4404
|
NODE_ENV: "production",
|
|
4402
4405
|
ENVSYNC_EDITION: oss ? "oss" : "enterprise",
|
|
@@ -4409,8 +4412,14 @@ function buildRuntimeEnv2(config, generated) {
|
|
|
4409
4412
|
ENVSYNC_LICENSE_CERT_PATH: oss ? "" : "/etc/envsync/license/enterprise-cert.pem",
|
|
4410
4413
|
ENVSYNC_LICENSE_KEY_PATH: oss ? "" : "/etc/envsync/license/enterprise-key.pem",
|
|
4411
4414
|
ENVSYNC_LICENSE_ROOT_CA_CERT_PATH: oss ? "" : "/etc/envsync/license/root-ca.pem",
|
|
4415
|
+
ENVSYNC_LICENSE_SERVER_URL: enterprise ? license.server_url ?? "" : "",
|
|
4416
|
+
ENVSYNC_LICENSE_KEY: enterprise ? license.key ?? "" : "",
|
|
4417
|
+
ENVSYNC_INSTALL_FINGERPRINT: enterprise ? license.install_fingerprint ?? "" : "",
|
|
4418
|
+
ENVSYNC_LICENSE_LEASE_TTL_SECONDS: String(license.lease_ttl_seconds ?? 300),
|
|
4419
|
+
ENVSYNC_STACK_NAME: config.services.stack_name,
|
|
4412
4420
|
DB_AUTO_MIGRATE: "false",
|
|
4413
4421
|
PORT: `${config.services.api_port}`,
|
|
4422
|
+
MANAGEMENT_API_PORT: `${config.services.management_api_port}`,
|
|
4414
4423
|
DATABASE_HOST: "postgres",
|
|
4415
4424
|
DATABASE_PORT: "5432",
|
|
4416
4425
|
DATABASE_USER: "postgres",
|
|
@@ -4452,6 +4461,7 @@ function buildRuntimeEnv2(config, generated) {
|
|
|
4452
4461
|
OPENFGA_STORE_ID: generated.openfga.store_id,
|
|
4453
4462
|
OPENFGA_MODEL_ID: generated.openfga.model_id,
|
|
4454
4463
|
OPENFGA_DB_PASSWORD: generated.secrets.openfga_db_password,
|
|
4464
|
+
MANAGEMENT_API_URL: oss ? "" : publicHttpsUrl(config, hosts.manage_api),
|
|
4455
4465
|
CLICKSTACK_OPERATOR_EMAIL: generated.clickstack.operator_email,
|
|
4456
4466
|
CLICKSTACK_OPERATOR_PASSWORD: generated.clickstack.operator_password,
|
|
4457
4467
|
CLICKSTACK_ACCESS_KEY: generated.clickstack.access_key,
|
|
@@ -4541,6 +4551,7 @@ function renderTraefikDynamicConfig(config, generated) {
|
|
|
4541
4551
|
const activeSlot = generated.deployment.active_slot;
|
|
4542
4552
|
const apiServiceName = generated.deployment.maintenance_mode ? "envsync-api-maintenance" : "envsync-api";
|
|
4543
4553
|
const landingEnabled = !isOssConfig(config);
|
|
4554
|
+
const managementEnabled = !isOssConfig(config);
|
|
4544
4555
|
const otelAllowedOrigins = [
|
|
4545
4556
|
...landingEnabled ? publicHttpsOriginVariants(config, hosts.landing) : [],
|
|
4546
4557
|
...publicHttpsOriginVariants(config, hosts.app)
|
|
@@ -4602,6 +4613,16 @@ function renderTraefikDynamicConfig(config, generated) {
|
|
|
4602
4613
|
" loadBalancer:",
|
|
4603
4614
|
" servers:",
|
|
4604
4615
|
" - url: http://api_maintenance:8080",
|
|
4616
|
+
...managementEnabled ? [
|
|
4617
|
+
" envsync-management-api:",
|
|
4618
|
+
" loadBalancer:",
|
|
4619
|
+
" healthCheck:",
|
|
4620
|
+
" path: /health",
|
|
4621
|
+
" interval: 5s",
|
|
4622
|
+
" timeout: 3s",
|
|
4623
|
+
" servers:",
|
|
4624
|
+
` - url: http://envsync-management-api:${config.services.management_api_port}`
|
|
4625
|
+
] : [],
|
|
4605
4626
|
...landingEnabled ? [
|
|
4606
4627
|
" landing:",
|
|
4607
4628
|
" loadBalancer:",
|
|
@@ -4629,6 +4650,14 @@ function renderTraefikDynamicConfig(config, generated) {
|
|
|
4629
4650
|
" tls:",
|
|
4630
4651
|
" certResolver: letsencrypt"
|
|
4631
4652
|
] : [],
|
|
4653
|
+
...managementEnabled ? [
|
|
4654
|
+
" management-api-router:",
|
|
4655
|
+
` rule: Host(\`${hosts.manage_api}\`)`,
|
|
4656
|
+
" service: envsync-management-api",
|
|
4657
|
+
" entryPoints: [websecure]",
|
|
4658
|
+
" tls:",
|
|
4659
|
+
" certResolver: letsencrypt"
|
|
4660
|
+
] : [],
|
|
4632
4661
|
" web-router:",
|
|
4633
4662
|
` rule: Host(\`${hosts.app}\`)`,
|
|
4634
4663
|
" service: web",
|
|
@@ -4707,10 +4736,12 @@ function renderFrontendRuntimeConfig(config, generated) {
|
|
|
4707
4736
|
const hosts = domainMap(config.domain.root_domain);
|
|
4708
4737
|
const otelEndpoint = publicHttpsUrl(config, hosts.obs);
|
|
4709
4738
|
const activeReleaseVersion = generated.deployment.slots[generated.deployment.active_slot].release_version || config.release.version;
|
|
4739
|
+
const managementApiUrl = config.edition === "enterprise" ? publicHttpsUrl(config, hosts.manage_api) : "";
|
|
4710
4740
|
return `window.__ENVSYNC_RUNTIME_CONFIG__ = ${JSON.stringify({
|
|
4711
4741
|
apiBaseUrl: publicHttpsUrl(config, hosts.api),
|
|
4712
4742
|
appBaseUrl: publicHttpsUrl(config, hosts.app),
|
|
4713
4743
|
authBaseUrl: publicHttpsUrl(config, hosts.auth),
|
|
4744
|
+
managementApiUrl,
|
|
4714
4745
|
keycloakRealm: config.auth.keycloak_realm,
|
|
4715
4746
|
webClientId: config.auth.web_client_id,
|
|
4716
4747
|
apiDocsUrl: publicHttpsUrl(config, hosts.api, "/docs"),
|
|
@@ -4772,6 +4803,7 @@ function renderStack(config, runtimeEnv, generated, mode, paths) {
|
|
|
4772
4803
|
const includeRuntimeInfra = mode !== "base";
|
|
4773
4804
|
const includeAppServices = mode === "full";
|
|
4774
4805
|
const landingEnabled = !isOssConfig(config);
|
|
4806
|
+
const managementEnabled = !isOssConfig(config);
|
|
4775
4807
|
const apiLicenseVolume = landingEnabled ? "\n volumes:\n - /etc/envsync/license:/etc/envsync/license:ro" : "";
|
|
4776
4808
|
const deployment = createSteadyApiDeploymentState(config, generated);
|
|
4777
4809
|
const stackName = config.services.stack_name;
|
|
@@ -4983,6 +5015,17 @@ ${renderEnvList({
|
|
|
4983
5015
|
- source: otel_agent_conf
|
|
4984
5016
|
target: /etc/otel-agent.yaml
|
|
4985
5017
|
networks: [envsync]
|
|
5018
|
+
${includeRuntimeInfra && managementEnabled ? `
|
|
5019
|
+
|
|
5020
|
+
envsync-management-api:
|
|
5021
|
+
image: ${config.images.management_api}
|
|
5022
|
+
environment:
|
|
5023
|
+
${renderEnvList({
|
|
5024
|
+
...apiEnvironment,
|
|
5025
|
+
PORT: `${config.services.management_api_port}`
|
|
5026
|
+
})}
|
|
5027
|
+
${apiLicenseVolume}
|
|
5028
|
+
networks: [envsync]` : ""}
|
|
4986
5029
|
${includeAppServices ? `
|
|
4987
5030
|
|
|
4988
5031
|
api_maintenance:
|
|
@@ -5117,6 +5160,8 @@ var LICENSE_BUNDLE_FILE = path3.join(LICENSE_ROOT, "enterprise-license-bundle.js
|
|
|
5117
5160
|
var LICENSE_CERT_FILE = path3.join(LICENSE_ROOT, "enterprise-cert.pem");
|
|
5118
5161
|
var LICENSE_KEY_FILE = path3.join(LICENSE_ROOT, "enterprise-key.pem");
|
|
5119
5162
|
var LICENSE_ROOT_CA_FILE = path3.join(LICENSE_ROOT, "root-ca.pem");
|
|
5163
|
+
var LICENSE_FILE_MODE = 420;
|
|
5164
|
+
var LICENSE_DIR_MODE = 493;
|
|
5120
5165
|
var VERSIONS_LOCK = path3.join(DEPLOY_ROOT, "versions.lock.json");
|
|
5121
5166
|
var STACK_FILE = path3.join(DEPLOY_ROOT, "docker-stack.yaml");
|
|
5122
5167
|
var BOOTSTRAP_BASE_STACK_FILE = path3.join(DEPLOY_ROOT, "docker-stack.bootstrap.base.yaml");
|
|
@@ -5218,6 +5263,7 @@ var DEFAULT_SOURCE_REPO_URL = "https://github.com/EnvSync-Cloud/envsync.git";
|
|
|
5218
5263
|
var DEFAULT_ENTERPRISE_LICENSE_SERVER_URL = "https://license.envsync.cloud";
|
|
5219
5264
|
var MANAGED_VERSIONED_IMAGE_PREFIXES = {
|
|
5220
5265
|
api: "ghcr.io/envsync-cloud/envsync-api:",
|
|
5266
|
+
management_api: "ghcr.io/envsync-cloud/envsync-management-api:",
|
|
5221
5267
|
keycloak: "envsync-keycloak:",
|
|
5222
5268
|
web: "ghcr.io/envsync-cloud/envsync-web-static:",
|
|
5223
5269
|
landing: "ghcr.io/envsync-cloud/envsync-landing-static:"
|
|
@@ -5333,6 +5379,27 @@ function writeFileMaybe(target, content, mode) {
|
|
|
5333
5379
|
}
|
|
5334
5380
|
writeFile(target, content, mode);
|
|
5335
5381
|
}
|
|
5382
|
+
function ensureEnterpriseLicenseFilesReadable() {
|
|
5383
|
+
if (exists2(LICENSE_ROOT)) {
|
|
5384
|
+
try {
|
|
5385
|
+
fs3.chmodSync(LICENSE_ROOT, LICENSE_DIR_MODE);
|
|
5386
|
+
} catch {
|
|
5387
|
+
throw new Error(
|
|
5388
|
+
`Cannot update directory mode for ${LICENSE_ROOT}. Fix by running: chmod ${LICENSE_DIR_MODE.toString(8)} ${LICENSE_ROOT}`
|
|
5389
|
+
);
|
|
5390
|
+
}
|
|
5391
|
+
}
|
|
5392
|
+
for (const filePath of [LICENSE_BUNDLE_FILE, LICENSE_CERT_FILE, LICENSE_KEY_FILE, LICENSE_ROOT_CA_FILE]) {
|
|
5393
|
+
if (!exists2(filePath)) continue;
|
|
5394
|
+
try {
|
|
5395
|
+
fs3.chmodSync(filePath, LICENSE_FILE_MODE);
|
|
5396
|
+
} catch {
|
|
5397
|
+
throw new Error(
|
|
5398
|
+
`Cannot update file mode for ${filePath}. Fix by running: chmod ${LICENSE_FILE_MODE.toString(8)} ${filePath}`
|
|
5399
|
+
);
|
|
5400
|
+
}
|
|
5401
|
+
}
|
|
5402
|
+
}
|
|
5336
5403
|
function exists2(target) {
|
|
5337
5404
|
return fs3.existsSync(target);
|
|
5338
5405
|
}
|
|
@@ -5424,6 +5491,7 @@ function domainMap2(rootDomain) {
|
|
|
5424
5491
|
landing: rootDomain,
|
|
5425
5492
|
app: `app.${rootDomain}`,
|
|
5426
5493
|
api: `api.${rootDomain}`,
|
|
5494
|
+
manage_api: `manage-api.${rootDomain}`,
|
|
5427
5495
|
auth: `auth.${rootDomain}`,
|
|
5428
5496
|
obs: `obs.${rootDomain}`,
|
|
5429
5497
|
mail: `mail.${rootDomain}`,
|
|
@@ -5599,6 +5667,7 @@ function versionedImages(version) {
|
|
|
5599
5667
|
assertSemverVersion(version);
|
|
5600
5668
|
return {
|
|
5601
5669
|
api: `ghcr.io/envsync-cloud/envsync-api:${version}`,
|
|
5670
|
+
management_api: `ghcr.io/envsync-cloud/envsync-management-api:${version}`,
|
|
5602
5671
|
keycloak: `envsync-keycloak:${version}`,
|
|
5603
5672
|
web: `ghcr.io/envsync-cloud/envsync-web-static:${version}`,
|
|
5604
5673
|
landing: `ghcr.io/envsync-cloud/envsync-landing-static:${version}`
|
|
@@ -5664,6 +5733,7 @@ function normalizeConfig(raw) {
|
|
|
5664
5733
|
},
|
|
5665
5734
|
images: {
|
|
5666
5735
|
api: !raw.images?.api || isManagedVersionedImage(raw.images.api, "api") ? derivedImages.api : raw.images.api,
|
|
5736
|
+
management_api: !raw.images?.management_api || isManagedVersionedImage(raw.images.management_api, "management_api") ? derivedImages.management_api : raw.images.management_api,
|
|
5667
5737
|
keycloak: !raw.images?.keycloak || isManagedVersionedImage(raw.images.keycloak, "keycloak") ? derivedImages.keycloak : raw.images.keycloak,
|
|
5668
5738
|
web: !raw.images?.web || isManagedVersionedImage(raw.images.web, "web") ? derivedImages.web : raw.images.web,
|
|
5669
5739
|
landing: !raw.images?.landing || isManagedVersionedImage(raw.images.landing, "landing") ? derivedImages.landing : raw.images.landing,
|
|
@@ -5674,6 +5744,7 @@ function normalizeConfig(raw) {
|
|
|
5674
5744
|
services: {
|
|
5675
5745
|
stack_name: stackName,
|
|
5676
5746
|
api_port: requireDefined(raw.services?.api_port, "services.api_port"),
|
|
5747
|
+
management_api_port: raw.services?.management_api_port ?? 4001,
|
|
5677
5748
|
public_http_port: raw.services?.public_http_port ?? 80,
|
|
5678
5749
|
public_https_port: raw.services?.public_https_port ?? 443,
|
|
5679
5750
|
clickstack_ui_port: requireDefined(raw.services?.clickstack_ui_port, "services.clickstack_ui_port"),
|
|
@@ -5726,6 +5797,7 @@ function normalizeConfig(raw) {
|
|
|
5726
5797
|
key: raw.license.key,
|
|
5727
5798
|
install_fingerprint: raw.license.install_fingerprint ?? deterministicInstallFingerprint(rootDomain, stackName),
|
|
5728
5799
|
certificate_bundle_file: raw.license.certificate_bundle_file,
|
|
5800
|
+
lease_ttl_seconds: raw.license.lease_ttl_seconds,
|
|
5729
5801
|
certificate_validity_days: raw.license.certificate_validity_days
|
|
5730
5802
|
} : raw.edition === "oss" ? void 0 : {
|
|
5731
5803
|
install_fingerprint: deterministicInstallFingerprint(rootDomain, stackName),
|
|
@@ -7148,6 +7220,7 @@ async function cmdSetup() {
|
|
|
7148
7220
|
domain: { root_domain: rootDomain, acme_email: acmeEmail },
|
|
7149
7221
|
images: {
|
|
7150
7222
|
api: releaseImages.api,
|
|
7223
|
+
management_api: releaseImages.management_api,
|
|
7151
7224
|
keycloak: releaseImages.keycloak,
|
|
7152
7225
|
web: releaseImages.web,
|
|
7153
7226
|
landing: releaseImages.landing,
|
|
@@ -7158,6 +7231,7 @@ async function cmdSetup() {
|
|
|
7158
7231
|
services: {
|
|
7159
7232
|
stack_name: "envsync",
|
|
7160
7233
|
api_port: 4e3,
|
|
7234
|
+
management_api_port: 4001,
|
|
7161
7235
|
public_http_port: 80,
|
|
7162
7236
|
public_https_port: 443,
|
|
7163
7237
|
clickstack_ui_port: 8080,
|
|
@@ -7308,6 +7382,9 @@ async function cmdDeploy() {
|
|
|
7308
7382
|
logSection("Deploy");
|
|
7309
7383
|
const { config, generated } = loadState();
|
|
7310
7384
|
logReleaseContext(config);
|
|
7385
|
+
if (!isOssConfig2(config)) {
|
|
7386
|
+
ensureEnterpriseLicenseFilesReadable();
|
|
7387
|
+
}
|
|
7311
7388
|
assertSwarmManager();
|
|
7312
7389
|
assertBootstrapState(generated);
|
|
7313
7390
|
if (!currentOptions.dryRun) {
|
|
@@ -7658,6 +7735,9 @@ async function cmdUpgrade(targetVersion) {
|
|
|
7658
7735
|
ref: `v${desiredVersion}`
|
|
7659
7736
|
};
|
|
7660
7737
|
logReleaseContext(config);
|
|
7738
|
+
if (!isOssConfig2(config) && !currentOptions.dryRun) {
|
|
7739
|
+
ensureEnterpriseLicenseFilesReadable();
|
|
7740
|
+
}
|
|
7661
7741
|
config.images = {
|
|
7662
7742
|
...config.images,
|
|
7663
7743
|
...versionedImages(desiredVersion)
|
|
@@ -7749,16 +7829,25 @@ async function requestEnterpriseLicenseCertificate(config, route) {
|
|
|
7749
7829
|
return parseEnterpriseLicenseBundle(body.bundle);
|
|
7750
7830
|
}
|
|
7751
7831
|
function writeEnterpriseLicenseBundle(bundle) {
|
|
7752
|
-
writeFileMaybe(LICENSE_BUNDLE_FILE, JSON.stringify(bundle, null, 2) + "\n",
|
|
7753
|
-
writeFileMaybe(
|
|
7754
|
-
|
|
7755
|
-
|
|
7756
|
-
`,
|
|
7832
|
+
writeFileMaybe(LICENSE_BUNDLE_FILE, JSON.stringify(bundle, null, 2) + "\n", LICENSE_FILE_MODE);
|
|
7833
|
+
writeFileMaybe(
|
|
7834
|
+
LICENSE_CERT_FILE,
|
|
7835
|
+
bundle.certificate_pem.endsWith("\n") ? bundle.certificate_pem : `${bundle.certificate_pem}
|
|
7836
|
+
`,
|
|
7837
|
+
LICENSE_FILE_MODE
|
|
7838
|
+
);
|
|
7839
|
+
writeFileMaybe(
|
|
7840
|
+
LICENSE_KEY_FILE,
|
|
7841
|
+
bundle.private_key_pem.endsWith("\n") ? bundle.private_key_pem : `${bundle.private_key_pem}
|
|
7842
|
+
`,
|
|
7843
|
+
LICENSE_FILE_MODE
|
|
7844
|
+
);
|
|
7757
7845
|
writeFileMaybe(LICENSE_ROOT_CA_FILE, bundle.root_ca_pem.endsWith("\n") ? bundle.root_ca_pem : `${bundle.root_ca_pem}
|
|
7758
|
-
`,
|
|
7846
|
+
`, LICENSE_FILE_MODE);
|
|
7759
7847
|
}
|
|
7760
7848
|
async function ensureEnterpriseCertificateBundle(config) {
|
|
7761
7849
|
if (isOssConfig2(config)) return;
|
|
7850
|
+
ensureEnterpriseLicenseFilesReadable();
|
|
7762
7851
|
if (exists2(LICENSE_BUNDLE_FILE) && exists2(LICENSE_CERT_FILE) && exists2(LICENSE_KEY_FILE) && exists2(LICENSE_ROOT_CA_FILE)) {
|
|
7763
7852
|
validateEnterpriseLicenseBundleFiles(config, false);
|
|
7764
7853
|
return;
|
|
@@ -7817,6 +7906,7 @@ async function cmdLicense(action = "validate-cert") {
|
|
|
7817
7906
|
logInfo("OSS deployments do not require license verification.");
|
|
7818
7907
|
return;
|
|
7819
7908
|
}
|
|
7909
|
+
ensureEnterpriseLicenseFilesReadable();
|
|
7820
7910
|
if (action === "issue-cert" || action === "renew-cert") {
|
|
7821
7911
|
const route = action === "renew-cert" ? "renew" : "issue";
|
|
7822
7912
|
if (currentOptions.dryRun) {
|
|
@@ -8058,6 +8148,7 @@ async function cmdRestore(archivePath, autoDeploy = false) {
|
|
|
8058
8148
|
if (exists2(restoredLicenseRoot)) {
|
|
8059
8149
|
fs3.rmSync(LICENSE_ROOT, { recursive: true, force: true });
|
|
8060
8150
|
fs3.cpSync(restoredLicenseRoot, LICENSE_ROOT, { recursive: true });
|
|
8151
|
+
ensureEnterpriseLicenseFilesReadable();
|
|
8061
8152
|
}
|
|
8062
8153
|
const config = loadConfig();
|
|
8063
8154
|
for (const volume of STACK_VOLUMES) {
|