@geekmidas/cli 10.0.0-alpha.80 → 10.0.0-alpha.81
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/{add-CIxT-Iq6.mjs → add-Bn1bqt0c.mjs} +2 -2
- package/dist/{add-CIxT-Iq6.mjs.map → add-Bn1bqt0c.mjs.map} +1 -1
- package/dist/{add-DJ0VE-y-.cjs → add-DF9IHQov.cjs} +2 -2
- package/dist/{add-DJ0VE-y-.cjs.map → add-DF9IHQov.cjs.map} +1 -1
- package/dist/{bundler-D4pl87A5.mjs → bundler-Ba_LoFXI.mjs} +3 -3
- package/dist/{bundler-D4pl87A5.mjs.map → bundler-Ba_LoFXI.mjs.map} +1 -1
- package/dist/{bundler-BlbSLFLn.cjs → bundler-DeIVbloM.cjs} +3 -3
- package/dist/{bundler-BlbSLFLn.cjs.map → bundler-DeIVbloM.cjs.map} +1 -1
- package/dist/{cli-BkNZBe_-.cjs → cli-BB1KOkfo.cjs} +3 -3
- package/dist/{cli-BkNZBe_-.cjs.map → cli-BB1KOkfo.cjs.map} +1 -1
- package/dist/{cli-7aLfgIGt.mjs → cli-CznHL-4-.mjs} +3 -3
- package/dist/{cli-7aLfgIGt.mjs.map → cli-CznHL-4-.mjs.map} +1 -1
- package/dist/{compose-Bn4OJONR.cjs → compose-76ho0pUg.cjs} +99 -367
- package/dist/compose-76ho0pUg.cjs.map +1 -0
- package/dist/{compose-n7K8H5j8.mjs → compose-BxIsChn5.mjs} +81 -349
- package/dist/compose-BxIsChn5.mjs.map +1 -0
- package/dist/deploy/public.cjs +5 -5
- package/dist/deploy/public.mjs +5 -5
- package/dist/{deploy-DK4Y6ev4.mjs → deploy-BRUx9hiA.mjs} +3 -3
- package/dist/{deploy-DK4Y6ev4.mjs.map → deploy-BRUx9hiA.mjs.map} +1 -1
- package/dist/{deploy-Ppnh8MHS.cjs → deploy-DuHRWNeJ.cjs} +3 -3
- package/dist/{deploy-Ppnh8MHS.cjs.map → deploy-DuHRWNeJ.cjs.map} +1 -1
- package/dist/{dokploy-Bjq05wkw.mjs → dokploy-BTO37Co8.mjs} +2 -2
- package/dist/{dokploy-Bjq05wkw.mjs.map → dokploy-BTO37Co8.mjs.map} +1 -1
- package/dist/{dokploy-CJvdoNc3.cjs → dokploy-Q4iYDmls.cjs} +2 -2
- package/dist/{dokploy-CJvdoNc3.cjs.map → dokploy-Q4iYDmls.cjs.map} +1 -1
- package/dist/{encryption-CAyR6D7B.cjs → encryption-9YA5ThNl.cjs} +2 -2
- package/dist/{encryption-CAyR6D7B.cjs.map → encryption-9YA5ThNl.cjs.map} +1 -1
- package/dist/{encryption-BrsOJFFz.mjs → encryption-BESGvjHD.mjs} +2 -2
- package/dist/{encryption-BrsOJFFz.mjs.map → encryption-BESGvjHD.mjs.map} +1 -1
- package/dist/{engine-ba9CvjTo.mjs → engine-CHij99aX.mjs} +2 -2
- package/dist/{engine-ba9CvjTo.mjs.map → engine-CHij99aX.mjs.map} +1 -1
- package/dist/{engine-DzBZR5D0.cjs → engine-U0xzB5i4.cjs} +2 -2
- package/dist/{engine-DzBZR5D0.cjs.map → engine-U0xzB5i4.cjs.map} +1 -1
- package/dist/{github-CVdbVlT5.mjs → github-2OSRBf9G.mjs} +2 -2
- package/dist/{github-CVdbVlT5.mjs.map → github-2OSRBf9G.mjs.map} +1 -1
- package/dist/{github-BLjU59Ye.cjs → github-BM-Y9M2G.cjs} +2 -2
- package/dist/{github-BLjU59Ye.cjs.map → github-BM-Y9M2G.cjs.map} +1 -1
- package/dist/index.cjs +215 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +216 -44
- package/dist/index.mjs.map +1 -1
- package/dist/{migrate-pfu4aYzX.mjs → migrate-3oLefufw.mjs} +2 -2
- package/dist/{migrate-pfu4aYzX.mjs.map → migrate-3oLefufw.mjs.map} +1 -1
- package/dist/{migrate-DkB833Jj.cjs → migrate-BlYiMA23.cjs} +2 -2
- package/dist/{migrate-DkB833Jj.cjs.map → migrate-BlYiMA23.cjs.map} +1 -1
- package/dist/{migrate-iEdyEx4S.cjs → migrate-C440QQvZ.cjs} +2 -2
- package/dist/{migrate-iEdyEx4S.cjs.map → migrate-C440QQvZ.cjs.map} +1 -1
- package/dist/{migrate-DlBgATa-.mjs → migrate-KwZsJFce.mjs} +2 -2
- package/dist/{migrate-DlBgATa-.mjs.map → migrate-KwZsJFce.mjs.map} +1 -1
- package/dist/{resolve-CQPn66jr.mjs → resolve-BPIDcuQ3.mjs} +3 -3
- package/dist/{resolve-CQPn66jr.mjs.map → resolve-BPIDcuQ3.mjs.map} +1 -1
- package/dist/{resolve-4_5N67Fk.cjs → resolve-CBrJTyDO.cjs} +3 -3
- package/dist/{resolve-4_5N67Fk.cjs.map → resolve-CBrJTyDO.cjs.map} +1 -1
- package/dist/{rollback-C0cbdsM-.mjs → rollback-B7uQKHEk.mjs} +3 -3
- package/dist/{rollback-C0cbdsM-.mjs.map → rollback-B7uQKHEk.mjs.map} +1 -1
- package/dist/{rollback-CgYUPLbq.cjs → rollback-P09wRaW4.cjs} +3 -3
- package/dist/{rollback-CgYUPLbq.cjs.map → rollback-P09wRaW4.cjs.map} +1 -1
- package/dist/{seeds-BdkFpW0P.mjs → seeds-B4PiO_48.mjs} +2332 -1525
- package/dist/seeds-B4PiO_48.mjs.map +1 -0
- package/dist/{seeds-ZljwYV_p.cjs → seeds-BjHiy9tW.cjs} +3877 -2950
- package/dist/seeds-BjHiy9tW.cjs.map +1 -0
- package/dist/target/public.cjs +1 -1
- package/dist/target/public.mjs +1 -1
- package/package.json +15 -15
- package/dist/compose-Bn4OJONR.cjs.map +0 -1
- package/dist/compose-n7K8H5j8.mjs.map +0 -1
- package/dist/seeds-BdkFpW0P.mjs.map +0 -1
- package/dist/seeds-ZljwYV_p.cjs.map +0 -1
|
@@ -4,7 +4,7 @@ const require_discover = require("./discover-D1It5r_h.cjs");
|
|
|
4
4
|
const require_derive = require("./derive-DAbo49sm.cjs");
|
|
5
5
|
const require_workspace = require("./workspace-Bp8FEkF-.cjs");
|
|
6
6
|
const require_define = require("./define-DzRz8FgH.cjs");
|
|
7
|
-
const require_seeds = require("./seeds-
|
|
7
|
+
const require_seeds = require("./seeds-BjHiy9tW.cjs");
|
|
8
8
|
const require_SubscriberGenerator = require("./SubscriberGenerator-CajwOa5W.cjs");
|
|
9
9
|
const require_drivers = require("./drivers-BdvtCKc7.cjs");
|
|
10
10
|
const require_databases = require("./databases-BY-pEImp.cjs");
|
|
@@ -792,330 +792,6 @@ function pinImages(file, digests, images) {
|
|
|
792
792
|
});
|
|
793
793
|
}
|
|
794
794
|
//#endregion
|
|
795
|
-
//#region src/compose/logs.ts
|
|
796
|
-
/**
|
|
797
|
-
* The stack's log UI: OpenObserve, run beside the apps when
|
|
798
|
-
* `deploy.compose.logs` asks for it, and every backend's OpenTelemetry
|
|
799
|
-
* pointed at it.
|
|
800
|
-
*
|
|
801
|
-
* The production server already exports its traces and pino logs over
|
|
802
|
-
* OTLP/HTTP when `OTEL_EXPORTER_OTLP_ENDPOINT` is set. OpenObserve takes OTLP
|
|
803
|
-
* at `/api/<org>/v1/{logs,traces}` with HTTP basic auth, so wiring an app is
|
|
804
|
-
* two variables: the endpoint, `http://openobserve:5080/api/default`, and
|
|
805
|
-
* the header that signs in as the root user.
|
|
806
|
-
*
|
|
807
|
-
* It is reached, by default, through an SSH tunnel: published on 127.0.0.1
|
|
808
|
-
* only, because a port Docker publishes on every interface is opened in the
|
|
809
|
-
* firewall by Docker itself, past ufw's rules. Served publicly, it is a host
|
|
810
|
-
* on the stack's Caddy that refuses every address not allowed.
|
|
811
|
-
*
|
|
812
|
-
* Pure: the stack decides it, and the phases print and check it.
|
|
813
|
-
*/
|
|
814
|
-
/**
|
|
815
|
-
* The image, pinned. A log store's on-disk format is the thing that must not
|
|
816
|
-
* move under a running stack, so a new version is a change to this line.
|
|
817
|
-
*/
|
|
818
|
-
const OPENOBSERVE_IMAGE = "public.ecr.aws/zinclabs/openobserve:v1.0.4";
|
|
819
|
-
/** Its compose service name — the host the apps send to. */
|
|
820
|
-
const LOGS_SERVICE = "openobserve";
|
|
821
|
-
/** The organisation every app's telemetry lands in. */
|
|
822
|
-
const LOGS_ORG = "default";
|
|
823
|
-
/** The stage secrets that sign in as OpenObserve's root user. */
|
|
824
|
-
const LOGS_EMAIL_KEY = "ZO_ROOT_USER_EMAIL";
|
|
825
|
-
const LOGS_PASSWORD_KEY = "ZO_ROOT_USER_PASSWORD";
|
|
826
|
-
/** The stage sends its telemetry somewhere already, and logs are on too. */
|
|
827
|
-
var LogsEndpointConflict = class extends Error {
|
|
828
|
-
stage;
|
|
829
|
-
keys;
|
|
830
|
-
constructor(stage, keys) {
|
|
831
|
-
super(`The stage '${stage}' sets ${keys.join(", ")} in its secrets, and deploy.compose.logs also runs OpenObserve for it — each backend can send its telemetry to one place. Either keep your own OTLP backend: remove logs from deploy.compose in gkm.config.ts; or use the bundled OpenObserve: remove ${keys.join(", ")} from the stage's secrets, and every backend is pointed at it.`);
|
|
832
|
-
this.stage = stage;
|
|
833
|
-
this.keys = keys;
|
|
834
|
-
this.name = "LogsEndpointConflict";
|
|
835
|
-
}
|
|
836
|
-
};
|
|
837
|
-
/** A root password OpenObserve would refuse to start with. */
|
|
838
|
-
var LogsPasswordWeak = class extends Error {
|
|
839
|
-
stage;
|
|
840
|
-
constructor(stage) {
|
|
841
|
-
super(`The stage '${stage}' sets ${LOGS_PASSWORD_KEY}, and OpenObserve refuses it: a root password must be 8 to 128 characters with a lowercase letter, an uppercase letter, a digit and a symbol. Set another with gkm secrets:set ${LOGS_PASSWORD_KEY} '…' --stage ${stage}, or unset it to have one generated.`);
|
|
842
|
-
this.stage = stage;
|
|
843
|
-
this.name = "LogsPasswordWeak";
|
|
844
|
-
}
|
|
845
|
-
};
|
|
846
|
-
/** A deployed stage with logs on and no root password generated yet. */
|
|
847
|
-
var LogsPasswordMissing = class extends Error {
|
|
848
|
-
stage;
|
|
849
|
-
constructor(stage) {
|
|
850
|
-
super(`The stage '${stage}' runs OpenObserve and has no ${LOGS_PASSWORD_KEY} in its secrets. Run gkm compose --stage ${stage} without --dry-run once to generate it, or set one: gkm secrets:set ${LOGS_PASSWORD_KEY} '…' --stage ${stage}`);
|
|
851
|
-
this.stage = stage;
|
|
852
|
-
this.name = "LogsPasswordMissing";
|
|
853
|
-
}
|
|
854
|
-
};
|
|
855
|
-
/** Whether OpenObserve accepts `password` for its root user. */
|
|
856
|
-
function isStrongLogsPassword(password) {
|
|
857
|
-
return password.length >= 8 && password.length <= 128 && /[a-z]/.test(password) && /[A-Z]/.test(password) && /\d/.test(password) && /[^A-Za-z0-9]/.test(password);
|
|
858
|
-
}
|
|
859
|
-
/**
|
|
860
|
-
* A root password: 192 random bits, with a fixed tail so every class
|
|
861
|
-
* OpenObserve requires is present whatever the random part drew.
|
|
862
|
-
*/
|
|
863
|
-
function generateLogsPassword() {
|
|
864
|
-
return `${(0, node_crypto.randomBytes)(24).toString("base64url")}-Zo1`;
|
|
865
|
-
}
|
|
866
|
-
/**
|
|
867
|
-
* The stage's secrets with a generated root password, where it has none.
|
|
868
|
-
* Pure, like `withGeneratedSecrets`: the caller keeps the result once the
|
|
869
|
-
* run goes ahead.
|
|
870
|
-
*/
|
|
871
|
-
function withLogsPassword(secrets) {
|
|
872
|
-
if (secrets.custom?.["ZO_ROOT_USER_PASSWORD"]) return {
|
|
873
|
-
secrets,
|
|
874
|
-
generated: []
|
|
875
|
-
};
|
|
876
|
-
return {
|
|
877
|
-
secrets: {
|
|
878
|
-
...secrets,
|
|
879
|
-
custom: {
|
|
880
|
-
...secrets.custom,
|
|
881
|
-
[LOGS_PASSWORD_KEY]: generateLogsPassword()
|
|
882
|
-
},
|
|
883
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
884
|
-
},
|
|
885
|
-
generated: [LOGS_PASSWORD_KEY]
|
|
886
|
-
};
|
|
887
|
-
}
|
|
888
|
-
/**
|
|
889
|
-
* `OTEL_EXPORTER_OTLP_HEADERS` signing in as `email`.
|
|
890
|
-
*
|
|
891
|
-
* The variable's values are percent-decoded by the SDK (they follow the W3C
|
|
892
|
-
* baggage format), so the space after `Basic` is written `%20`. Base64's own
|
|
893
|
-
* `+`, `/` and `=` pass through decoding unchanged.
|
|
894
|
-
*/
|
|
895
|
-
function otlpHeaders(email, password) {
|
|
896
|
-
return `Authorization=Basic%20${Buffer.from(`${email}:${password}`).toString("base64")}`;
|
|
897
|
-
}
|
|
898
|
-
/** The stack's OpenObserve for one stage. */
|
|
899
|
-
function stackLogs(options) {
|
|
900
|
-
const { config, stage, local, custom } = options;
|
|
901
|
-
const conflicting = Object.keys(custom).filter(require_seeds.isOtlpDestination).sort();
|
|
902
|
-
if (conflicting.length > 0) throw new LogsEndpointConflict(stage, conflicting);
|
|
903
|
-
if (!local && !options.domain) throw new require_seeds.NoDomainForStage(stage);
|
|
904
|
-
const email = custom["ZO_ROOT_USER_EMAIL"] ?? (local ? "admin@gkm.localhost" : `admin@${options.domain}`);
|
|
905
|
-
const set = custom[LOGS_PASSWORD_KEY];
|
|
906
|
-
if (!set && !local) throw new LogsPasswordMissing(stage);
|
|
907
|
-
const password = set ?? "Geekmidas-1";
|
|
908
|
-
if (!isStrongLogsPassword(password)) throw new LogsPasswordWeak(stage);
|
|
909
|
-
const host = config.public ? local ? `logs.${options.project}.localhost` : `logs.${options.domain}` : void 0;
|
|
910
|
-
const url = host ? `https://${host}${local && options.https !== 443 ? `:${options.https}` : ""}` : `http://localhost:${config.port}`;
|
|
911
|
-
return {
|
|
912
|
-
...config,
|
|
913
|
-
email,
|
|
914
|
-
password,
|
|
915
|
-
passwordFromSecrets: Boolean(set),
|
|
916
|
-
url,
|
|
917
|
-
...host ? { host } : {},
|
|
918
|
-
env: {
|
|
919
|
-
[LOGS_EMAIL_KEY]: email,
|
|
920
|
-
[LOGS_PASSWORD_KEY]: password,
|
|
921
|
-
ZO_DATA_DIR: "/data",
|
|
922
|
-
ZO_COMPACT_DATA_RETENTION_DAYS: String(config.retentionDays),
|
|
923
|
-
ZO_TELEMETRY: "false"
|
|
924
|
-
},
|
|
925
|
-
appEnv: {
|
|
926
|
-
OTEL_EXPORTER_OTLP_ENDPOINT: `http://${LOGS_SERVICE}:${require_workspace.LOGS_PORT}/api/${LOGS_ORG}`,
|
|
927
|
-
OTEL_EXPORTER_OTLP_HEADERS: otlpHeaders(email, password)
|
|
928
|
-
}
|
|
929
|
-
};
|
|
930
|
-
}
|
|
931
|
-
/**
|
|
932
|
-
* OpenObserve's service. The image has no shell, `wget` or `curl`, so its
|
|
933
|
-
* health check is its own binary asking the running server for its status —
|
|
934
|
-
* which exits non-zero when nothing answers on its port.
|
|
935
|
-
*/
|
|
936
|
-
function logsService(logs) {
|
|
937
|
-
return {
|
|
938
|
-
image: OPENOBSERVE_IMAGE,
|
|
939
|
-
restart: "unless-stopped",
|
|
940
|
-
env_file: [{
|
|
941
|
-
path: `./${LOGS_SERVICE}.env`,
|
|
942
|
-
format: "raw"
|
|
943
|
-
}],
|
|
944
|
-
volumes: ["openobserve-data:/data"],
|
|
945
|
-
...logs.public ? {} : { ports: [`127.0.0.1:${logs.port}:${require_workspace.LOGS_PORT}`] },
|
|
946
|
-
healthcheck: {
|
|
947
|
-
test: [
|
|
948
|
-
"CMD",
|
|
949
|
-
"/openobserve",
|
|
950
|
-
"node",
|
|
951
|
-
"status"
|
|
952
|
-
],
|
|
953
|
-
interval: "10s",
|
|
954
|
-
timeout: "5s",
|
|
955
|
-
retries: 12,
|
|
956
|
-
start_period: "20s"
|
|
957
|
-
}
|
|
958
|
-
};
|
|
959
|
-
}
|
|
960
|
-
/** What `gkm compose` prints once the stack is up: how to open the logs. */
|
|
961
|
-
function logsAccess(logs, ctx) {
|
|
962
|
-
const login = `login: ${logs.email}, password: ${ctx.local && !logs.passwordFromSecrets ? logs.password : `gkm secrets:show --stage ${ctx.stage} --reveal → ${LOGS_PASSWORD_KEY}`}`;
|
|
963
|
-
if (logs.public) return [`📜 Logs (OpenObserve): ${logs.url} (${login})`, ` answered only for ${logs.public.allow.join(", ")}; every other address gets 403`];
|
|
964
|
-
return [
|
|
965
|
-
`📜 Logs (OpenObserve) on 127.0.0.1:${logs.port} — from your computer:`,
|
|
966
|
-
...ctx.local ? [` on this machine, open http://localhost:${logs.port} directly; from another:`] : [],
|
|
967
|
-
` ssh -N -L ${logs.port}:localhost:${logs.port} ${ctx.user}@${ctx.hostname} (user and host are guesses: this machine's)`,
|
|
968
|
-
` then open http://localhost:${logs.port} (${login})`,
|
|
969
|
-
`⚠️ Docker-published ports bypass ufw, so OpenObserve is bound to 127.0.0.1 only — reach it through the tunnel, not by opening the port.`
|
|
970
|
-
];
|
|
971
|
-
}
|
|
972
|
-
//#endregion
|
|
973
|
-
//#region src/compose/redis.ts
|
|
974
|
-
/**
|
|
975
|
-
* The stack's Redis: what every declared cache lives in when a workspace runs
|
|
976
|
-
* as a `gkm compose` stack, on the local stage and on a deployed one alike.
|
|
977
|
-
*
|
|
978
|
-
* A cache is the one store whose contents can always be rebuilt, so unlike
|
|
979
|
-
* Mailpit and MinIO it is a production service, not a dev stand-in: it runs
|
|
980
|
-
* for every stage, on the compose network only, with nothing published. It
|
|
981
|
-
* is bounded (`maxmemory`, evicting the least recently used key), persisted
|
|
982
|
-
* (an append-only file on a named volume, kept by `--down`) and password
|
|
983
|
-
* protected — the stage's own password, generated once like its seed.
|
|
984
|
-
*
|
|
985
|
-
* A stage that sets a cache's URL in its secrets — a managed Redis — keeps
|
|
986
|
-
* it, and a stack whose every cache is set that way runs no Redis at all.
|
|
987
|
-
*
|
|
988
|
-
* Pure: the stack decides it, and the phases keep the password.
|
|
989
|
-
*/
|
|
990
|
-
/**
|
|
991
|
-
* Where a stack's caches live: its own Redis, whatever the deploy target's
|
|
992
|
-
* default is. A stack is one machine running containers, and a Redis beside
|
|
993
|
-
* the apps is cheaper for a cache than a table in the database they share.
|
|
994
|
-
*/
|
|
995
|
-
const STACK_CACHE = "redis";
|
|
996
|
-
/** Its compose service name — the host every cache URL points at. */
|
|
997
|
-
const REDIS_SERVICE = "redis";
|
|
998
|
-
/** The port it answers on, inside the network. */
|
|
999
|
-
const REDIS_PORT = 6379;
|
|
1000
|
-
/** Reconcile's pin, so `gkm dev` and the stack run one Redis. */
|
|
1001
|
-
const REDIS_IMAGE = require_seeds.DEFAULT_IMAGES.redis;
|
|
1002
|
-
/**
|
|
1003
|
-
* How much it may hold before it evicts. A cache that grows until the box
|
|
1004
|
-
* runs out of memory takes the apps with it; 256 MB is a lot of sessions and
|
|
1005
|
-
* little of a small server. A project's `docker-compose.<stage>.yml` can
|
|
1006
|
-
* replace the command to change it.
|
|
1007
|
-
*/
|
|
1008
|
-
const REDIS_MAXMEMORY = "256mb";
|
|
1009
|
-
/** The stage secret holding its password. */
|
|
1010
|
-
const REDIS_PASSWORD_KEY = "REDIS_PASSWORD";
|
|
1011
|
-
/** Redis's own count of logical databases, before `--databases` raises it. */
|
|
1012
|
-
const REDIS_DATABASES = 16;
|
|
1013
|
-
/** A deployed stage that runs the stack's Redis and has no password yet. */
|
|
1014
|
-
var RedisPasswordMissing = class extends Error {
|
|
1015
|
-
stage;
|
|
1016
|
-
constructor(stage) {
|
|
1017
|
-
super(`The stage '${stage}' runs the stack's Redis and has no ${REDIS_PASSWORD_KEY} in its secrets. Run gkm compose --stage ${stage} without --dry-run once to generate it, or set one: gkm secrets:set ${REDIS_PASSWORD_KEY} '…' --stage ${stage}`);
|
|
1018
|
-
this.stage = stage;
|
|
1019
|
-
this.name = "RedisPasswordMissing";
|
|
1020
|
-
}
|
|
1021
|
-
};
|
|
1022
|
-
/**
|
|
1023
|
-
* Whether a stage's stack runs Redis: a cache is declared and the stage's
|
|
1024
|
-
* secrets do not set the URL of every one.
|
|
1025
|
-
*/
|
|
1026
|
-
function runsRedis(manifest, custom) {
|
|
1027
|
-
return Object.values(manifest).some((declaration) => declaration?.kind === "cache" && (declaration.provides ?? []).some((key) => custom[key] === void 0));
|
|
1028
|
-
}
|
|
1029
|
-
/** A password: 256 random bits, URL-safe, so it sits in a URL unescaped. */
|
|
1030
|
-
function generateRedisPassword() {
|
|
1031
|
-
return (0, node_crypto.randomBytes)(32).toString("base64url");
|
|
1032
|
-
}
|
|
1033
|
-
/**
|
|
1034
|
-
* The stage's secrets with a generated Redis password, where it has none.
|
|
1035
|
-
* Pure, like `withGeneratedSecrets`: the caller keeps the result once the run
|
|
1036
|
-
* goes ahead.
|
|
1037
|
-
*/
|
|
1038
|
-
function withRedisPassword(secrets) {
|
|
1039
|
-
if (secrets.custom?.["REDIS_PASSWORD"]) return {
|
|
1040
|
-
secrets,
|
|
1041
|
-
generated: []
|
|
1042
|
-
};
|
|
1043
|
-
return {
|
|
1044
|
-
secrets: {
|
|
1045
|
-
...secrets,
|
|
1046
|
-
custom: {
|
|
1047
|
-
...secrets.custom,
|
|
1048
|
-
[REDIS_PASSWORD_KEY]: generateRedisPassword()
|
|
1049
|
-
},
|
|
1050
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1051
|
-
},
|
|
1052
|
-
generated: [REDIS_PASSWORD_KEY]
|
|
1053
|
-
};
|
|
1054
|
-
}
|
|
1055
|
-
/**
|
|
1056
|
-
* The stack's Redis for one stage, or nothing where no cache needs it.
|
|
1057
|
-
*
|
|
1058
|
-
* Each cache it holds gets a logical database of its own, by the order of
|
|
1059
|
-
* their ids, so two caches never read each other's keys.
|
|
1060
|
-
*/
|
|
1061
|
-
function stackRedis(options) {
|
|
1062
|
-
const { plan, stage, local, custom } = options;
|
|
1063
|
-
const caches = plan.resources.filter((r) => r.kind === "cache" && custom[r.envKey] === void 0).sort((a, b) => a.id.localeCompare(b.id));
|
|
1064
|
-
if (caches.length === 0) return void 0;
|
|
1065
|
-
const set = custom[REDIS_PASSWORD_KEY];
|
|
1066
|
-
if (!set && !local) throw new RedisPasswordMissing(stage);
|
|
1067
|
-
const password = set ?? "geekmidas";
|
|
1068
|
-
const auth = encodeURIComponent(password);
|
|
1069
|
-
return {
|
|
1070
|
-
password,
|
|
1071
|
-
passwordFromSecrets: Boolean(set),
|
|
1072
|
-
urls: Object.fromEntries(caches.map((cache, index) => [cache.envKey, `redis://:${auth}@${REDIS_SERVICE}:${REDIS_PORT}/${index}`])),
|
|
1073
|
-
env: {
|
|
1074
|
-
[REDIS_PASSWORD_KEY]: password,
|
|
1075
|
-
REDISCLI_AUTH: password
|
|
1076
|
-
},
|
|
1077
|
-
databases: Math.max(REDIS_DATABASES, caches.length)
|
|
1078
|
-
};
|
|
1079
|
-
}
|
|
1080
|
-
/**
|
|
1081
|
-
* Redis's service: bounded, persisted and password protected, on the
|
|
1082
|
-
* network alone.
|
|
1083
|
-
*
|
|
1084
|
-
* The command runs the image's own entrypoint with `redis-server` first, so
|
|
1085
|
-
* it still drops to the `redis` user and owns `/data`; the password is read
|
|
1086
|
-
* from the env file by the shell (`$$` is compose's escape for `$`), so
|
|
1087
|
-
* neither the compose file nor the container's command holds it.
|
|
1088
|
-
*/
|
|
1089
|
-
function redisService(redis) {
|
|
1090
|
-
const flags = [
|
|
1091
|
-
`--requirepass "$$${REDIS_PASSWORD_KEY}"`,
|
|
1092
|
-
`--maxmemory ${REDIS_MAXMEMORY}`,
|
|
1093
|
-
"--maxmemory-policy allkeys-lru",
|
|
1094
|
-
"--appendonly yes",
|
|
1095
|
-
...redis.databases > REDIS_DATABASES ? [`--databases ${redis.databases}`] : []
|
|
1096
|
-
];
|
|
1097
|
-
return {
|
|
1098
|
-
image: REDIS_IMAGE,
|
|
1099
|
-
restart: "unless-stopped",
|
|
1100
|
-
command: [
|
|
1101
|
-
"sh",
|
|
1102
|
-
"-c",
|
|
1103
|
-
`exec docker-entrypoint.sh redis-server ${flags.join(" ")}`
|
|
1104
|
-
],
|
|
1105
|
-
env_file: [{
|
|
1106
|
-
path: `./${REDIS_SERVICE}.env`,
|
|
1107
|
-
format: "raw"
|
|
1108
|
-
}],
|
|
1109
|
-
volumes: ["redis-data:/data"],
|
|
1110
|
-
healthcheck: {
|
|
1111
|
-
test: ["CMD-SHELL", "redis-cli ping | grep -q PONG"],
|
|
1112
|
-
interval: "5s",
|
|
1113
|
-
timeout: "3s",
|
|
1114
|
-
retries: 10
|
|
1115
|
-
}
|
|
1116
|
-
};
|
|
1117
|
-
}
|
|
1118
|
-
//#endregion
|
|
1119
795
|
//#region src/compose/caddyfile.ts
|
|
1120
796
|
/** Where Caddy reads a stage's own certificate, inside its container. */
|
|
1121
797
|
const CADDY_TLS_DIR = "/etc/caddy/tls";
|
|
@@ -1246,6 +922,43 @@ const LOG_ROTATION = {
|
|
|
1246
922
|
"max-file": "3"
|
|
1247
923
|
}
|
|
1248
924
|
};
|
|
925
|
+
/** The local stage's stack, without the logins `gkm dev` generates. */
|
|
926
|
+
var LocalCredentialsMissing = class extends Error {
|
|
927
|
+
stage;
|
|
928
|
+
constructor(stage) {
|
|
929
|
+
super(`The local stage '${stage}' runs with this machine's generated logins, and none were passed. Load them with loadLocalCredentials(workspace) and pass them as localCredentials.`);
|
|
930
|
+
this.stage = stage;
|
|
931
|
+
this.name = "LocalCredentialsMissing";
|
|
932
|
+
}
|
|
933
|
+
};
|
|
934
|
+
/**
|
|
935
|
+
* A deployed stage's container logins, derived from its seed like its role
|
|
936
|
+
* passwords — so every deploy of the stage computes the same ones, and no one
|
|
937
|
+
* reading the repo can.
|
|
938
|
+
*/
|
|
939
|
+
function derivedCredentials(project, plan, seed) {
|
|
940
|
+
const derive = (purpose) => require_seeds.localRolePassword(project, plan, purpose, seed);
|
|
941
|
+
return {
|
|
942
|
+
postgres: {
|
|
943
|
+
user: require_seeds.postgresSuperuser(project),
|
|
944
|
+
password: derive("master")
|
|
945
|
+
},
|
|
946
|
+
minio: {
|
|
947
|
+
user: `${project}-minio`,
|
|
948
|
+
password: derive("minio")
|
|
949
|
+
},
|
|
950
|
+
rabbitmq: {
|
|
951
|
+
user: require_seeds.LOCAL_RABBITMQ_USER,
|
|
952
|
+
password: derive("rabbitmq")
|
|
953
|
+
},
|
|
954
|
+
redis: { password: derive("redis") },
|
|
955
|
+
cacheToken: derive("cache-token"),
|
|
956
|
+
emulator: {
|
|
957
|
+
accessKeyId: require_seeds.EMULATOR_ACCESS_KEY_ID,
|
|
958
|
+
secretAccessKey: derive("emulator")
|
|
959
|
+
}
|
|
960
|
+
};
|
|
961
|
+
}
|
|
1249
962
|
/** A value only the stage's secrets can hold, and they do not. */
|
|
1250
963
|
var StageSecretMissing = class extends Error {
|
|
1251
964
|
app;
|
|
@@ -1324,15 +1037,23 @@ function composeStack(input) {
|
|
|
1324
1037
|
const plan = require_seeds.planFor(manifest, stage, (0, _geekmidas_manifest.provisionOrder)(manifest), {
|
|
1325
1038
|
localStage: workspace.stages.local,
|
|
1326
1039
|
events: require_SubscriberGenerator.DEFAULT_EVENTS.server,
|
|
1327
|
-
cache: STACK_CACHE,
|
|
1040
|
+
cache: require_seeds.STACK_CACHE,
|
|
1328
1041
|
edge: false
|
|
1329
1042
|
});
|
|
1330
1043
|
const byId = new Map(plan.resources.map((r) => [r.id, r]));
|
|
1331
|
-
|
|
1332
|
-
|
|
1044
|
+
if (local && !input.localCredentials) throw new LocalCredentialsMissing(stage);
|
|
1045
|
+
const seed = local ? input.localCredentials.seed : input.secrets?.seed;
|
|
1046
|
+
if (!seed) throw new StageSeedMissing(stage);
|
|
1047
|
+
const containers = local ? input.localCredentials : derivedCredentials(workspace.name, plan, seed);
|
|
1333
1048
|
const credential = {
|
|
1334
|
-
|
|
1335
|
-
|
|
1049
|
+
containers: {
|
|
1050
|
+
...containers,
|
|
1051
|
+
minio: {
|
|
1052
|
+
user: custom.AWS_ACCESS_KEY_ID ?? containers.minio.user,
|
|
1053
|
+
password: custom.AWS_SECRET_ACCESS_KEY ?? containers.minio.password
|
|
1054
|
+
}
|
|
1055
|
+
},
|
|
1056
|
+
seed
|
|
1336
1057
|
};
|
|
1337
1058
|
const apps = stackApps(workspace, manifest, plan, {
|
|
1338
1059
|
local,
|
|
@@ -1364,14 +1085,15 @@ function composeStack(input) {
|
|
|
1364
1085
|
for (const worker of workers) reads.set(worker.name, [...require_seeds.workerEnvKeys(manifest, worker.id, input.runnables) ?? []]);
|
|
1365
1086
|
const domain = workspace.deploy?.domains?.[stage];
|
|
1366
1087
|
const logsConfig = require_workspace.resolveLogs(workspace.deploy?.compose?.logs);
|
|
1367
|
-
const logsBase = logsConfig ? stackLogs({
|
|
1088
|
+
const logsBase = logsConfig ? require_seeds.stackLogs({
|
|
1368
1089
|
config: logsConfig,
|
|
1369
1090
|
stage,
|
|
1370
1091
|
local,
|
|
1371
1092
|
project: workspace.name,
|
|
1372
1093
|
...domain ? { domain } : {},
|
|
1373
1094
|
custom,
|
|
1374
|
-
https
|
|
1095
|
+
https,
|
|
1096
|
+
...local ? { localLogin: input.localCredentials.logs } : {}
|
|
1375
1097
|
}) : void 0;
|
|
1376
1098
|
const services = local ? {
|
|
1377
1099
|
missing: [],
|
|
@@ -1384,18 +1106,18 @@ function composeStack(input) {
|
|
|
1384
1106
|
allow: input.allowDevServices ?? [],
|
|
1385
1107
|
...domain ? { domain } : {}
|
|
1386
1108
|
});
|
|
1387
|
-
const redis = stackRedis({
|
|
1109
|
+
const redis = require_seeds.stackRedis({
|
|
1388
1110
|
plan,
|
|
1389
1111
|
stage,
|
|
1390
1112
|
local,
|
|
1391
|
-
custom
|
|
1113
|
+
custom,
|
|
1114
|
+
...local ? { localPassword: input.localCredentials.redis.password } : {}
|
|
1392
1115
|
});
|
|
1393
|
-
const infra = [...plan.containers.filter((c) => !NOT_RUN[c]).filter((c) => c !== "minio" || services.minio.length > 0).filter((c) => c !== "mailpit" || services.mailpit.length > 0).filter((c) => c !== "redis" || redis !== void 0), ...logsBase ? [LOGS_SERVICE] : []].sort();
|
|
1116
|
+
const infra = [...plan.containers.filter((c) => !NOT_RUN[c]).filter((c) => c !== "minio" || services.minio.length > 0).filter((c) => c !== "mailpit" || services.mailpit.length > 0).filter((c) => c !== "redis" || redis !== void 0), ...logsBase ? [require_seeds.LOGS_SERVICE] : []].sort();
|
|
1394
1117
|
const storage = infra.includes("minio") ? (() => {
|
|
1395
1118
|
const buckets = services.minio.map((id) => byId.get(id)?.name).filter((name) => Boolean(name)).sort();
|
|
1396
1119
|
return {
|
|
1397
|
-
|
|
1398
|
-
password: custom.AWS_SECRET_ACCESS_KEY ?? (local ? "geekmidas" : require_seeds.localRolePassword(workspace.name, plan, "minio", seed)),
|
|
1120
|
+
...credential.containers.minio,
|
|
1399
1121
|
buckets,
|
|
1400
1122
|
policies: require_seeds.bucketPolicies(plan).filter((p) => buckets.includes(p.bucket))
|
|
1401
1123
|
};
|
|
@@ -1430,7 +1152,7 @@ function composeStack(input) {
|
|
|
1430
1152
|
const edgeServices = new Set(proxy === "traefik" ? [
|
|
1431
1153
|
...apps.map((app) => app.name),
|
|
1432
1154
|
...fileServers.size > 0 ? ["minio"] : [],
|
|
1433
|
-
...logsBase?.host && logsBase.public ? [LOGS_SERVICE] : []
|
|
1155
|
+
...logsBase?.host && logsBase.public ? [require_seeds.LOGS_SERVICE] : []
|
|
1434
1156
|
] : []);
|
|
1435
1157
|
const hostOf = (service) => edgeServices.has(service) ? edgeAlias(project, service) : service;
|
|
1436
1158
|
const logs = logsBase && {
|
|
@@ -1442,8 +1164,8 @@ function composeStack(input) {
|
|
|
1442
1164
|
};
|
|
1443
1165
|
const derivation = {
|
|
1444
1166
|
project: workspace.name,
|
|
1445
|
-
|
|
1446
|
-
|
|
1167
|
+
credentials: credential.containers,
|
|
1168
|
+
seed: credential.seed,
|
|
1447
1169
|
...!local && domain ? { mailFrom: `noreply@${domain}` } : {}
|
|
1448
1170
|
};
|
|
1449
1171
|
const outside = require_seeds.networkEnv(plan, {
|
|
@@ -1559,7 +1281,7 @@ function composeStack(input) {
|
|
|
1559
1281
|
infra,
|
|
1560
1282
|
apps,
|
|
1561
1283
|
workers,
|
|
1562
|
-
|
|
1284
|
+
credentials: credential.containers,
|
|
1563
1285
|
...storage ? { storage } : {},
|
|
1564
1286
|
...logs ? { logs } : {},
|
|
1565
1287
|
...redis ? { redis } : {},
|
|
@@ -1586,10 +1308,10 @@ function composeStack(input) {
|
|
|
1586
1308
|
})),
|
|
1587
1309
|
...[...fileServers.values()].map(({ route }) => route),
|
|
1588
1310
|
...logs?.host && logs.public ? [{
|
|
1589
|
-
name: LOGS_SERVICE,
|
|
1311
|
+
name: require_seeds.LOGS_SERVICE,
|
|
1590
1312
|
host: logs.host,
|
|
1591
1313
|
upstreams: [{
|
|
1592
|
-
service: LOGS_SERVICE,
|
|
1314
|
+
service: require_seeds.LOGS_SERVICE,
|
|
1593
1315
|
port: require_workspace.LOGS_PORT
|
|
1594
1316
|
}],
|
|
1595
1317
|
streaming: true,
|
|
@@ -1604,7 +1326,7 @@ function composeStack(input) {
|
|
|
1604
1326
|
workspaceRoot: workspace.root,
|
|
1605
1327
|
apps: workspace.apps,
|
|
1606
1328
|
manifest,
|
|
1607
|
-
cache: STACK_CACHE
|
|
1329
|
+
cache: require_seeds.STACK_CACHE
|
|
1608
1330
|
});
|
|
1609
1331
|
}
|
|
1610
1332
|
for (const worker of workers) {
|
|
@@ -1616,7 +1338,7 @@ function composeStack(input) {
|
|
|
1616
1338
|
}, workspace.apps[worker.host], {
|
|
1617
1339
|
layout,
|
|
1618
1340
|
workspaceRoot: workspace.root,
|
|
1619
|
-
cache: STACK_CACHE
|
|
1341
|
+
cache: require_seeds.STACK_CACHE
|
|
1620
1342
|
});
|
|
1621
1343
|
}
|
|
1622
1344
|
return {
|
|
@@ -1741,13 +1463,14 @@ function hostOf(name, app, workspace, resource, options) {
|
|
|
1741
1463
|
/** The compose document: the infrastructure, the apps, and the edge. */
|
|
1742
1464
|
function stackFile(options) {
|
|
1743
1465
|
const { project, plan, apps } = options;
|
|
1744
|
-
const infra = options.infra.filter((name) => name !== LOGS_SERVICE);
|
|
1466
|
+
const infra = options.infra.filter((name) => name !== require_seeds.LOGS_SERVICE);
|
|
1745
1467
|
const derived = require_seeds.composeFor({
|
|
1746
1468
|
...plan,
|
|
1747
1469
|
containers: [...infra]
|
|
1748
1470
|
}, {
|
|
1749
1471
|
project,
|
|
1750
|
-
ports: Object.fromEntries(require_seeds.portKeys(infra, plan.fakes).map((key) => [key, 0]))
|
|
1472
|
+
ports: Object.fromEntries(require_seeds.portKeys(infra, plan.fakes).map((key) => [key, 0])),
|
|
1473
|
+
credentials: options.credentials
|
|
1751
1474
|
});
|
|
1752
1475
|
const services = {};
|
|
1753
1476
|
const volumes = {
|
|
@@ -1766,13 +1489,7 @@ function stackFile(options) {
|
|
|
1766
1489
|
};
|
|
1767
1490
|
}
|
|
1768
1491
|
const postgres = services.postgres;
|
|
1769
|
-
if (postgres)
|
|
1770
|
-
postgres.environment = {
|
|
1771
|
-
...postgres.environment,
|
|
1772
|
-
POSTGRES_PASSWORD: options.master
|
|
1773
|
-
};
|
|
1774
|
-
postgres.ports = ["127.0.0.1::5432"];
|
|
1775
|
-
}
|
|
1492
|
+
if (postgres) postgres.ports = ["127.0.0.1::5432"];
|
|
1776
1493
|
const minio = services.minio;
|
|
1777
1494
|
if (minio && options.storage) {
|
|
1778
1495
|
minio.environment = {
|
|
@@ -1782,8 +1499,8 @@ function stackFile(options) {
|
|
|
1782
1499
|
};
|
|
1783
1500
|
minio.ports = ["127.0.0.1::9000"];
|
|
1784
1501
|
}
|
|
1785
|
-
if (services["redis"] && options.redis) services[REDIS_SERVICE] = redisService(options.redis);
|
|
1786
|
-
if (options.logs) services[LOGS_SERVICE] = logsService(options.logs);
|
|
1502
|
+
if (services["redis"] && options.redis) services[require_seeds.REDIS_SERVICE] = require_seeds.redisService(options.redis);
|
|
1503
|
+
if (options.logs) services[require_seeds.LOGS_SERVICE] = require_seeds.logsService(options.logs);
|
|
1787
1504
|
for (const app of apps) services[app.name] = {
|
|
1788
1505
|
image: app.ref,
|
|
1789
1506
|
...app.build ? { build: {
|
|
@@ -2064,6 +1781,7 @@ const defaultDeps = {
|
|
|
2064
1781
|
revision: gitRevision,
|
|
2065
1782
|
sql: require_seeds.pgClient,
|
|
2066
1783
|
buckets: require_seeds.bucketClient,
|
|
1784
|
+
logins: require_seeds.ensurePostgresLogin,
|
|
2067
1785
|
migrate: require_databases.migrateDatabases,
|
|
2068
1786
|
seed: require_databases.seedDatabases,
|
|
2069
1787
|
probe: httpsProbe,
|
|
@@ -2122,6 +1840,7 @@ async function validateCompose(ctx, deps, options = {}) {
|
|
|
2122
1840
|
...registry ? { registry } : {}
|
|
2123
1841
|
},
|
|
2124
1842
|
secrets,
|
|
1843
|
+
...stage === workspace.stages.local ? { localCredentials: (await require_seeds.loadLocalCredentials(workspace)).credentials } : {},
|
|
2125
1844
|
allowDevServices: ctx.allowDevServices,
|
|
2126
1845
|
ports: edgePorts(deps.env),
|
|
2127
1846
|
...layout ? { layout } : {},
|
|
@@ -2208,11 +1927,11 @@ async function stageSecrets(ctx, manifest) {
|
|
|
2208
1927
|
generated: []
|
|
2209
1928
|
};
|
|
2210
1929
|
const withSeed = require_seeds.withGeneratedSecrets(stored ?? require_seeds.initStageSecrets(ctx.stage), manifest);
|
|
2211
|
-
const withLogs = require_workspace.resolveLogs(ctx.workspace.deploy?.compose?.logs) ? withLogsPassword(withSeed.secrets) : {
|
|
1930
|
+
const withLogs = require_workspace.resolveLogs(ctx.workspace.deploy?.compose?.logs) ? require_seeds.withLogsPassword(withSeed.secrets) : {
|
|
2212
1931
|
secrets: withSeed.secrets,
|
|
2213
1932
|
generated: []
|
|
2214
1933
|
};
|
|
2215
|
-
const withRedis = runsRedis(manifest, withLogs.secrets.custom ?? {}) ? withRedisPassword(withLogs.secrets) : {
|
|
1934
|
+
const withRedis = require_seeds.runsRedis(manifest, withLogs.secrets.custom ?? {}) ? require_seeds.withRedisPassword(withLogs.secrets) : {
|
|
2216
1935
|
secrets: withLogs.secrets,
|
|
2217
1936
|
generated: []
|
|
2218
1937
|
};
|
|
@@ -2390,10 +2109,20 @@ async function prepareDatabases(ctx, run, deps) {
|
|
|
2390
2109
|
const { stack } = run;
|
|
2391
2110
|
const workspace = ctx.workspace;
|
|
2392
2111
|
const port = await deps.docker.port(run.ref, "postgres", 5432);
|
|
2112
|
+
const superuser = stack.credential.containers.postgres;
|
|
2113
|
+
const login = await deps.logins({
|
|
2114
|
+
port,
|
|
2115
|
+
login: superuser,
|
|
2116
|
+
legacy: [{
|
|
2117
|
+
user: require_seeds.LEGACY_LOCAL_LOGIN.user,
|
|
2118
|
+
password: superuser.password
|
|
2119
|
+
}, ...stack.local ? [require_seeds.LEGACY_LOCAL_LOGIN] : []]
|
|
2120
|
+
});
|
|
2121
|
+
if (login.notice) ctx.logger.info(login.notice);
|
|
2393
2122
|
const statements = require_seeds.postgresStatements(stack.plan, workspace.name, stack.credential.seed);
|
|
2394
2123
|
if (statements.length > 0) {
|
|
2395
2124
|
ctx.logger.info("🗄️ Creating databases, roles and grants…");
|
|
2396
|
-
await require_seeds.applyPostgres(deps.sql(port,
|
|
2125
|
+
await require_seeds.applyPostgres(deps.sql(port, login.login), statements);
|
|
2397
2126
|
}
|
|
2398
2127
|
const sources = {};
|
|
2399
2128
|
const manifest = await require_discover.discover({
|
|
@@ -2404,8 +2133,11 @@ async function prepareDatabases(ctx, run, deps) {
|
|
|
2404
2133
|
const env = require_seeds.envFor(stack.plan, {
|
|
2405
2134
|
ports: { [require_seeds.primaryPortKey("postgres")]: port },
|
|
2406
2135
|
project: workspace.name,
|
|
2407
|
-
|
|
2408
|
-
|
|
2136
|
+
credentials: {
|
|
2137
|
+
...stack.credential.containers,
|
|
2138
|
+
postgres: login.login
|
|
2139
|
+
},
|
|
2140
|
+
seed: stack.credential.seed
|
|
2409
2141
|
});
|
|
2410
2142
|
const options = {
|
|
2411
2143
|
root: workspace.root,
|
|
@@ -2557,7 +2289,7 @@ async function verifyCompose(ctx, run, deps) {
|
|
|
2557
2289
|
edge
|
|
2558
2290
|
})));
|
|
2559
2291
|
results.push(...await Promise.all(stack.workers.map((worker) => checkContainer(ctx, run, deps, worker.name))));
|
|
2560
|
-
if (stack.logs) results.push(await checkContainer(ctx, run, deps, LOGS_SERVICE));
|
|
2292
|
+
if (stack.logs) results.push(await checkContainer(ctx, run, deps, require_seeds.LOGS_SERVICE));
|
|
2561
2293
|
const down = results.filter((result) => !result.healthy).map(({ app, url, last }) => ({
|
|
2562
2294
|
app,
|
|
2563
2295
|
url,
|
|
@@ -2608,7 +2340,7 @@ async function checkContainer(ctx, run, deps, service) {
|
|
|
2608
2340
|
}
|
|
2609
2341
|
/** How to open the logs, printed — and as an event, for a headless caller. */
|
|
2610
2342
|
function reportLogs(ctx, logs, local) {
|
|
2611
|
-
const lines = logsAccess(logs, {
|
|
2343
|
+
const lines = require_seeds.logsAccess(logs, {
|
|
2612
2344
|
stage: ctx.stage,
|
|
2613
2345
|
local,
|
|
2614
2346
|
user: currentUser(),
|
|
@@ -2617,7 +2349,7 @@ function reportLogs(ctx, logs, local) {
|
|
|
2617
2349
|
ctx.logger.info(`\n${lines.join("\n")}`);
|
|
2618
2350
|
ctx.emit({
|
|
2619
2351
|
type: "logs.ready",
|
|
2620
|
-
service: LOGS_SERVICE,
|
|
2352
|
+
service: require_seeds.LOGS_SERVICE,
|
|
2621
2353
|
access: logs.public ? "public" : "tunnel",
|
|
2622
2354
|
url: logs.url,
|
|
2623
2355
|
...logs.public ? { allow: [...logs.public.allow] } : { port: logs.port },
|
|
@@ -2760,8 +2492,8 @@ async function writeStack(root, dir, stack) {
|
|
|
2760
2492
|
force: true
|
|
2761
2493
|
});
|
|
2762
2494
|
for (const app of [...stack.apps, ...stack.workers]) if (app.env) await write((0, node_path.join)(dir, `${app.name}.env`), envFile(app.env), 384);
|
|
2763
|
-
if (stack.logs && stack.compose.services["openobserve"]?.env_file) await write((0, node_path.join)(dir, `${LOGS_SERVICE}.env`), envFile(stack.logs.env), 384);
|
|
2764
|
-
if (stack.redis && stack.compose.services["redis"]?.env_file) await write((0, node_path.join)(dir, `${REDIS_SERVICE}.env`), envFile(stack.redis.env), 384);
|
|
2495
|
+
if (stack.logs && stack.compose.services["openobserve"]?.env_file) await write((0, node_path.join)(dir, `${require_seeds.LOGS_SERVICE}.env`), envFile(stack.logs.env), 384);
|
|
2496
|
+
if (stack.redis && stack.compose.services["redis"]?.env_file) await write((0, node_path.join)(dir, `${require_seeds.REDIS_SERVICE}.env`), envFile(stack.redis.env), 384);
|
|
2765
2497
|
for (const entry of await (0, node_fs_promises.readdir)(dir)) if (entry.endsWith(".credentials")) await (0, node_fs_promises.rm)((0, node_path.join)(dir, entry));
|
|
2766
2498
|
for (const [path, content] of Object.entries(stack.dockerfiles)) await write((0, node_path.join)(root, path), content);
|
|
2767
2499
|
await require_seeds.ensureDockerignore(require_seeds.findBuildRoot(root));
|
|
@@ -2933,4 +2665,4 @@ Object.defineProperty(exports, "stackOverrideFile", {
|
|
|
2933
2665
|
}
|
|
2934
2666
|
});
|
|
2935
2667
|
|
|
2936
|
-
//# sourceMappingURL=compose-
|
|
2668
|
+
//# sourceMappingURL=compose-76ho0pUg.cjs.map
|