@wtfalch/foundry 0.39.2 → 0.39.4
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.
|
@@ -74,22 +74,34 @@ export declare const SIGNIN_DB_BACKUP_ENV: {
|
|
|
74
74
|
readonly keyId: "BACKUP_S3_KEY_ID";
|
|
75
75
|
readonly secret: "BACKUP_S3_SECRET";
|
|
76
76
|
readonly prefix: "BACKUP_S3_PREFIX";
|
|
77
|
+
readonly script: "BACKUP_S3_SCRIPT";
|
|
77
78
|
};
|
|
78
79
|
/** Where in the bucket a company's dumps go: `signin-db/<slug>/signin-db-<UTC time>.dump`. */
|
|
79
80
|
export declare function signinDbBackupPrefix(slug: string): string;
|
|
80
|
-
/** The env entries the backup command needs, for the database app. */
|
|
81
|
-
export declare function signinDbBackupEnvs(target: SigninDbBackupTarget, slug: string
|
|
81
|
+
/** The env entries the backup command needs, for the database app, the script included. */
|
|
82
|
+
export declare function signinDbBackupEnvs(target: SigninDbBackupTarget, slug: string, db: {
|
|
83
|
+
user: string;
|
|
84
|
+
database: string;
|
|
85
|
+
}): Array<{
|
|
82
86
|
key: string;
|
|
83
87
|
value: string;
|
|
84
88
|
}>;
|
|
85
89
|
/**
|
|
86
|
-
* The
|
|
90
|
+
* The script the backup command runs. A custom-format dump goes to a temporary file (an upload
|
|
87
91
|
* needs a length), is signed with SigV4 and put with curl, and the file is removed on every exit. The
|
|
88
92
|
* credentials reach curl on its standard input as a config, never in an argument. Every failure ends the
|
|
89
|
-
* run non-zero, and curl's error text names the HTTP status only.
|
|
90
|
-
* command in
|
|
93
|
+
* run non-zero, and curl's error text names the HTTP status only. It lives in the app's env, base64,
|
|
94
|
+
* because Coolify stores a task's command in 255 characters and this script is longer.
|
|
95
|
+
*/
|
|
96
|
+
export declare function signinDbBackupScript(user: string, database: string): string;
|
|
97
|
+
/** The most Coolify stores in a scheduled task's command (`varchar(255)`); a longer one answers 500. */
|
|
98
|
+
export declare const COOLIFY_TASK_COMMAND_MAX = 255;
|
|
99
|
+
/**
|
|
100
|
+
* The command Coolify runs in the container: it decodes the script from the env and runs it. An
|
|
101
|
+
* empty env fails the run instead of passing it. No single quote: Coolify wraps the command in single
|
|
102
|
+
* quotes.
|
|
91
103
|
*/
|
|
92
|
-
export declare function signinDbBackupCommand(
|
|
104
|
+
export declare function signinDbBackupCommand(): string;
|
|
93
105
|
/**
|
|
94
106
|
* Makes sure the database app has its backup task, and returns its uuid. The task is found by name
|
|
95
107
|
* before it is created, and updated to the full wanted body every time (Coolify hides the stored
|
|
@@ -97,9 +109,6 @@ export declare function signinDbBackupCommand(user: string, database: string): s
|
|
|
97
109
|
* read back and must be listed enabled with the wanted frequency and timeout, or this throws: a
|
|
98
110
|
* schedule that cannot be seen is not a backup. The caller records the uuid. Errors name the label only.
|
|
99
111
|
*/
|
|
100
|
-
export declare function ensureSigninDbBackupTask(coolify: Pick<CoolifyPort, 'raw'>, appId: string, label: string
|
|
101
|
-
user: string;
|
|
102
|
-
database: string;
|
|
103
|
-
}): Promise<string>;
|
|
112
|
+
export declare function ensureSigninDbBackupTask(coolify: Pick<CoolifyPort, 'raw'>, appId: string, label: string): Promise<string>;
|
|
104
113
|
/** A company on the TLS database whose nightly dump is not scheduled yet: the sign-in step plans again to schedule it. */
|
|
105
114
|
export declare function signinDbBackupMissing(recordedIds: Readonly<Record<string, string>>): boolean;
|
|
@@ -113,13 +113,14 @@ export const SIGNIN_DB_BACKUP_ENV = {
|
|
|
113
113
|
keyId: 'BACKUP_S3_KEY_ID',
|
|
114
114
|
secret: 'BACKUP_S3_SECRET',
|
|
115
115
|
prefix: 'BACKUP_S3_PREFIX',
|
|
116
|
+
script: 'BACKUP_S3_SCRIPT',
|
|
116
117
|
};
|
|
117
118
|
/** Where in the bucket a company's dumps go: `signin-db/<slug>/signin-db-<UTC time>.dump`. */
|
|
118
119
|
export function signinDbBackupPrefix(slug) {
|
|
119
120
|
return `signin-db/${slug}`;
|
|
120
121
|
}
|
|
121
|
-
/** The env entries the backup command needs, for the database app. */
|
|
122
|
-
export function signinDbBackupEnvs(target, slug) {
|
|
122
|
+
/** The env entries the backup command needs, for the database app, the script included. */
|
|
123
|
+
export function signinDbBackupEnvs(target, slug, db) {
|
|
123
124
|
return [
|
|
124
125
|
{ key: SIGNIN_DB_BACKUP_ENV.endpoint, value: target.endpoint.replace(/\/+$/, '') },
|
|
125
126
|
{ key: SIGNIN_DB_BACKUP_ENV.bucket, value: target.bucket },
|
|
@@ -127,16 +128,20 @@ export function signinDbBackupEnvs(target, slug) {
|
|
|
127
128
|
{ key: SIGNIN_DB_BACKUP_ENV.keyId, value: target.accessKeyId },
|
|
128
129
|
{ key: SIGNIN_DB_BACKUP_ENV.secret, value: target.secretAccessKey },
|
|
129
130
|
{ key: SIGNIN_DB_BACKUP_ENV.prefix, value: signinDbBackupPrefix(slug) },
|
|
131
|
+
{
|
|
132
|
+
key: SIGNIN_DB_BACKUP_ENV.script,
|
|
133
|
+
value: Buffer.from(signinDbBackupScript(db.user, db.database), 'utf8').toString('base64'),
|
|
134
|
+
},
|
|
130
135
|
];
|
|
131
136
|
}
|
|
132
137
|
/**
|
|
133
|
-
* The
|
|
138
|
+
* The script the backup command runs. A custom-format dump goes to a temporary file (an upload
|
|
134
139
|
* needs a length), is signed with SigV4 and put with curl, and the file is removed on every exit. The
|
|
135
140
|
* credentials reach curl on its standard input as a config, never in an argument. Every failure ends the
|
|
136
|
-
* run non-zero, and curl's error text names the HTTP status only.
|
|
137
|
-
* command in
|
|
141
|
+
* run non-zero, and curl's error text names the HTTP status only. It lives in the app's env, base64,
|
|
142
|
+
* because Coolify stores a task's command in 255 characters and this script is longer.
|
|
138
143
|
*/
|
|
139
|
-
export function
|
|
144
|
+
export function signinDbBackupScript(user, database) {
|
|
140
145
|
const e = SIGNIN_DB_BACKUP_ENV;
|
|
141
146
|
return [
|
|
142
147
|
'set -eu',
|
|
@@ -146,6 +151,17 @@ export function signinDbBackupCommand(user, database) {
|
|
|
146
151
|
`printf "user = \\"%s:%s\\"\\n" "$${e.keyId}" "$${e.secret}" | curl -sS --fail --max-time ${UPLOAD_MAX_SECONDS} --aws-sigv4 "aws:amz:$${e.region}:s3" -K - -T "$f" "$${e.endpoint}/$${e.bucket}/$${e.prefix}/\${f##*/}"`,
|
|
147
152
|
].join('; ');
|
|
148
153
|
}
|
|
154
|
+
/** The most Coolify stores in a scheduled task's command (`varchar(255)`); a longer one answers 500. */
|
|
155
|
+
export const COOLIFY_TASK_COMMAND_MAX = 255;
|
|
156
|
+
/**
|
|
157
|
+
* The command Coolify runs in the container: it decodes the script from the env and runs it. An
|
|
158
|
+
* empty env fails the run instead of passing it. No single quote: Coolify wraps the command in single
|
|
159
|
+
* quotes.
|
|
160
|
+
*/
|
|
161
|
+
export function signinDbBackupCommand() {
|
|
162
|
+
const v = `$${SIGNIN_DB_BACKUP_ENV.script}`;
|
|
163
|
+
return `[ -n "${v}" ] && printf %s "${v}" | base64 -d > /tmp/signin-db-backup.sh && sh /tmp/signin-db-backup.sh`;
|
|
164
|
+
}
|
|
149
165
|
function rows(body) {
|
|
150
166
|
if (!Array.isArray(body))
|
|
151
167
|
throw new Error('scheduled tasks list has an unexpected shape');
|
|
@@ -158,11 +174,11 @@ function rows(body) {
|
|
|
158
174
|
* read back and must be listed enabled with the wanted frequency and timeout, or this throws: a
|
|
159
175
|
* schedule that cannot be seen is not a backup. The caller records the uuid. Errors name the label only.
|
|
160
176
|
*/
|
|
161
|
-
export async function ensureSigninDbBackupTask(coolify, appId, label
|
|
177
|
+
export async function ensureSigninDbBackupTask(coolify, appId, label) {
|
|
162
178
|
const base = `/applications/${appId}/scheduled-tasks`;
|
|
163
179
|
const body = {
|
|
164
180
|
name: SIGNIN_DB_BACKUP_TASK_NAME,
|
|
165
|
-
command: signinDbBackupCommand(
|
|
181
|
+
command: signinDbBackupCommand(),
|
|
166
182
|
frequency: SIGNIN_DB_BACKUP_FREQUENCY,
|
|
167
183
|
timeout: SIGNIN_DB_BACKUP_TIMEOUT_SECONDS,
|
|
168
184
|
enabled: true,
|
package/dist/plan/signin-db.js
CHANGED
|
@@ -223,7 +223,10 @@ export async function provisionSigninDb(input) {
|
|
|
223
223
|
{ key: SIGNIN_DB_ENV.database, value: SIGNIN_DB_NAME },
|
|
224
224
|
{ key: SIGNIN_DB_ENV.cert, value: b64(server.certPem) },
|
|
225
225
|
{ key: SIGNIN_DB_ENV.key, value: b64(server.keyPem) },
|
|
226
|
-
...signinDbBackupEnvs(backup.target, input.slug
|
|
226
|
+
...signinDbBackupEnvs(backup.target, input.slug, {
|
|
227
|
+
user: SIGNIN_DB_USER,
|
|
228
|
+
database: SIGNIN_DB_NAME,
|
|
229
|
+
}),
|
|
227
230
|
];
|
|
228
231
|
const changed = await envsDiffer(coolify, app.appId, envs);
|
|
229
232
|
await coolify.bulkUpsertEnvs(app.appId, envs);
|
|
@@ -237,10 +240,7 @@ export async function provisionSigninDb(input) {
|
|
|
237
240
|
}
|
|
238
241
|
await input.record(SIGNIN_DB_CERT_NOT_AFTER_SCOPE_KEY, String(server.notAfter));
|
|
239
242
|
// The database is not used, and ZITADEL is not stopped for a move, until its nightly dump is scheduled.
|
|
240
|
-
await input.record(SIGNIN_DB_BACKUP_TASK_SCOPE_KEY, await ensureSigninDbBackupTask(coolify, app.appId, label
|
|
241
|
-
user: SIGNIN_DB_USER,
|
|
242
|
-
database: SIGNIN_DB_NAME,
|
|
243
|
-
}));
|
|
243
|
+
await input.record(SIGNIN_DB_BACKUP_TASK_SCOPE_KEY, await ensureSigninDbBackupTask(coolify, app.appId, label));
|
|
244
244
|
const dsn = signinDbDsn(input.internalHost, password);
|
|
245
245
|
runtime.onSecret?.(dsn);
|
|
246
246
|
return { appId: app.appId, dsn, ca: ca.certPem, password };
|