@stacksjs/ts-cloud 0.7.92 → 0.7.94
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/bin/cli.js +1235 -1183
- package/dist/bin/dashboard-server.js +451 -399
- package/dist/{chunk-29fwqkb7.js → chunk-0htae1c2.js} +456 -21
- package/dist/{chunk-fbwcv2vf.js → chunk-bs3jfnzp.js} +451 -41
- package/dist/control-plane/store.d.ts +1 -0
- package/dist/deploy/dashboard-database.d.ts +91 -3
- package/dist/deploy/dashboard-vitess.d.ts +154 -0
- package/dist/deploy/dashboard-vitess.test.d.ts +1 -0
- package/dist/deploy/index.js +2 -2
- package/dist/drivers/hetzner/client.d.ts +96 -0
- package/dist/drivers/hetzner/migrate-server.d.ts +124 -0
- package/dist/drivers/hetzner/migrate-server.test.d.ts +1 -0
- package/dist/drivers/hetzner/role-swap.d.ts +139 -0
- package/dist/drivers/hetzner/role-swap.test.d.ts +1 -0
- package/dist/drivers/index.js +1 -1
- package/dist/drivers/shared/db-provision.d.ts +4 -0
- package/dist/drivers/shared/deploy-script.d.ts +17 -1
- package/dist/drivers/shared/package-manager.d.ts +2 -0
- package/dist/drivers/shared/releases.d.ts +41 -2
- package/dist/drivers/shared/vitess-provision.d.ts +133 -0
- package/dist/drivers/shared/vitess-provision.test.d.ts +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +6 -2
- package/dist/telemetry/store.d.ts +1 -0
- package/dist/ui/account/automation.html +4 -4
- package/dist/ui/account/security.html +2 -2
- package/dist/ui/applications/compose.html +4 -4
- package/dist/ui/data/backups.html +4 -4
- package/dist/ui/data/services.html +4 -4
- package/dist/ui/data/volumes.html +3 -3
- package/dist/ui/index.html +4 -4
- package/dist/ui/integrations.html +2 -2
- package/dist/ui/operations/alerts.html +4 -4
- package/dist/ui/operations/configuration.html +4 -4
- package/dist/ui/operations/jobs.html +4 -4
- package/dist/ui/operations/maintenance.html +3 -3
- package/dist/ui/operations/observability.html +4 -4
- package/dist/ui/operations/previews.html +4 -4
- package/dist/ui/operations/queue.html +4 -4
- package/dist/ui/operations/regions.html +4 -4
- package/dist/ui/operations/releases.html +4 -4
- package/dist/ui/operations/workloads.html +4 -4
- package/dist/ui/security.html +2 -2
- package/dist/ui/server/actions.html +4 -4
- package/dist/ui/server/activity.html +2 -2
- package/dist/ui/server/capacity.html +4 -4
- package/dist/ui/server/database.html +124 -8
- package/dist/ui/server/deployments.html +4 -4
- package/dist/ui/server/diagnostics.html +2 -2
- package/dist/ui/server/firewall.html +4 -4
- package/dist/ui/server/fleet.html +4 -4
- package/dist/ui/server/logs.html +4 -4
- package/dist/ui/server/metrics.html +4 -4
- package/dist/ui/server/services.html +2 -2
- package/dist/ui/server/sites.html +4 -4
- package/dist/ui/server/ssh-keys.html +4 -4
- package/dist/ui/server/team.html +4 -4
- package/dist/ui/server/terminal.html +2 -2
- package/dist/ui/serverless/alarms.html +4 -4
- package/dist/ui/serverless/data.html +3 -3
- package/dist/ui/serverless/firewall.html +2 -2
- package/dist/ui/serverless/functions.html +4 -4
- package/dist/ui/serverless/logs.html +4 -4
- package/dist/ui/serverless/queues.html +4 -4
- package/dist/ui/serverless/secrets.html +4 -4
- package/dist/ui/serverless/traces.html +4 -4
- package/dist/ui/serverless.html +3 -3
- package/dist/ui-src/pages/server/database.stx +257 -9
- package/package.json +3 -3
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Swapping the roles of two servers.
|
|
3
|
+
*
|
|
4
|
+
* The situation this exists for: a server type is no longer obtainable. Hetzner
|
|
5
|
+
* retires older lines, and `available_for_migration` goes false everywhere, so
|
|
6
|
+
* a `change_type` onto that type can never succeed again. If you already own an
|
|
7
|
+
* instance of it, that instance is the only one you will ever have — and the
|
|
8
|
+
* right move is to put your heaviest workload on it rather than to keep trying
|
|
9
|
+
* to buy another.
|
|
10
|
+
*
|
|
11
|
+
* A resize cannot do this. What can is exchanging the two servers' primary IPs,
|
|
12
|
+
* so each address keeps pointing at the workload that answers on it, with no
|
|
13
|
+
* DNS change and no waiting on propagation.
|
|
14
|
+
*
|
|
15
|
+
* Two constraints decide whether it is possible at all, and both are cheap to
|
|
16
|
+
* check before anything is powered off:
|
|
17
|
+
*
|
|
18
|
+
* - A primary IP belongs to a datacenter. Two servers in different
|
|
19
|
+
* datacenters cannot exchange addresses, and finding that out halfway
|
|
20
|
+
* through leaves both boxes down with their addresses detached.
|
|
21
|
+
* - Data has to fit. Moving a workload onto a smaller disk fails at restore
|
|
22
|
+
* time, which is the worst moment to discover it.
|
|
23
|
+
*
|
|
24
|
+
* The planning is pure so those rules can be tested without an account.
|
|
25
|
+
*
|
|
26
|
+
* IMPORTANT, and not yet handled here: exchanging addresses does not move the
|
|
27
|
+
* workload. Each disk keeps the software and data it already had, so a swap on
|
|
28
|
+
* its own points every address at the wrong application. A complete role swap
|
|
29
|
+
* is three phases - deploy each workload onto its new host, restore its data,
|
|
30
|
+
* and only then exchange the addresses - and this module plans the third.
|
|
31
|
+
* `planRoleSwap` deliberately refuses to look like the whole job.
|
|
32
|
+
*/
|
|
33
|
+
export interface SwapServer {
|
|
34
|
+
id: number;
|
|
35
|
+
name: string;
|
|
36
|
+
/**
|
|
37
|
+
* Where the server sits, for the purpose of deciding whether an address can
|
|
38
|
+
* move to it. Derive it with {@link placementOf} rather than reading a field
|
|
39
|
+
* off the API response, and see that function for why. Null when unknown,
|
|
40
|
+
* which is a blocker rather than a pass.
|
|
41
|
+
*/
|
|
42
|
+
placement: string | null;
|
|
43
|
+
serverType: string;
|
|
44
|
+
diskSizeGb: number;
|
|
45
|
+
/** Bytes actually in use, so a move onto a smaller disk can be refused early. */
|
|
46
|
+
usedGb: number;
|
|
47
|
+
primaryIpId: number | null;
|
|
48
|
+
primaryIp: string | null;
|
|
49
|
+
}
|
|
50
|
+
export type SwapStepKind = 'power-off' | 'unassign-ip' | 'assign-ip' | 'power-on' | 'rename';
|
|
51
|
+
export interface SwapStep {
|
|
52
|
+
kind: SwapStepKind;
|
|
53
|
+
serverId: number;
|
|
54
|
+
/** For an IP step, the address being moved. */
|
|
55
|
+
ipId?: number;
|
|
56
|
+
/** For a rename, the name to take. */
|
|
57
|
+
name?: string;
|
|
58
|
+
description: string;
|
|
59
|
+
}
|
|
60
|
+
export interface SwapPlan {
|
|
61
|
+
ok: boolean;
|
|
62
|
+
/** Why the swap cannot proceed. Empty when it can. */
|
|
63
|
+
blockers: string[];
|
|
64
|
+
steps: SwapStep[];
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Whether a workload fits on the other server's disk.
|
|
68
|
+
*
|
|
69
|
+
* A margin is kept rather than comparing raw numbers: a disk that is exactly
|
|
70
|
+
* full is a disk that fails on the next write, and a restore needs room for
|
|
71
|
+
* both the archive and its expansion.
|
|
72
|
+
*/
|
|
73
|
+
export declare function fits(usedGb: number, targetDiskGb: number, marginRatio?: number): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Where a server sits, from whichever field the API still reports.
|
|
76
|
+
*
|
|
77
|
+
* Primary IPs are bound at datacenter granularity, so `datacenter` is the
|
|
78
|
+
* field this wants. The API has stopped returning it — `datacenter` is now
|
|
79
|
+
* null on both the server and the primary IP, leaving only `location`.
|
|
80
|
+
*
|
|
81
|
+
* Reading the missing field directly is worse than useless: two servers in
|
|
82
|
+
* different datacenters both report `undefined`, `undefined === undefined`,
|
|
83
|
+
* and the guard that exists to stop a cross-datacenter swap waves it through.
|
|
84
|
+
* The failure then lands halfway, with both boxes off and their addresses
|
|
85
|
+
* detached, which is the exact outcome the check was written to prevent.
|
|
86
|
+
*
|
|
87
|
+
* So: prefer the datacenter when present, fall back to the location, and
|
|
88
|
+
* return null when neither is known so the caller can refuse. Location is a
|
|
89
|
+
* sound proxy today because every Hetzner location contains exactly one
|
|
90
|
+
* datacenter; if that ever stops being true, this returns the coarser answer
|
|
91
|
+
* and the assign call is the backstop.
|
|
92
|
+
*/
|
|
93
|
+
export declare function placementOf(server: {
|
|
94
|
+
datacenter?: {
|
|
95
|
+
name?: string;
|
|
96
|
+
} | null;
|
|
97
|
+
location?: {
|
|
98
|
+
name?: string;
|
|
99
|
+
} | null;
|
|
100
|
+
}): string | null;
|
|
101
|
+
/**
|
|
102
|
+
* The parking name one server wears while the other takes its name.
|
|
103
|
+
*
|
|
104
|
+
* Hetzner rejects a duplicate server name, so the two cannot cross directly.
|
|
105
|
+
*/
|
|
106
|
+
export declare function swapTempName(name: string): string;
|
|
107
|
+
/**
|
|
108
|
+
* The ordered steps to exchange two servers' addresses and names.
|
|
109
|
+
*
|
|
110
|
+
* Both are powered off before either address moves. Hetzner refuses to detach a
|
|
111
|
+
* primary IP from a running server, and doing them one at a time would leave
|
|
112
|
+
* the first server up with no address — reachable by nobody and, worse, still
|
|
113
|
+
* accepting work it can no longer be reached about.
|
|
114
|
+
*/
|
|
115
|
+
export declare function planRoleSwap(a: SwapServer, b: SwapServer): SwapPlan;
|
|
116
|
+
/**
|
|
117
|
+
* Whether a type can still be migrated onto in a datacenter.
|
|
118
|
+
*
|
|
119
|
+
* `available` answers a different question — whether a NEW server of that type
|
|
120
|
+
* can be created — and reading it instead is why a doomed `change_type` looks
|
|
121
|
+
* like bad luck rather than a retired type. `available_for_migration` is the
|
|
122
|
+
* one `change_type` consults.
|
|
123
|
+
*/
|
|
124
|
+
export declare function canMigrateTo(datacenter: {
|
|
125
|
+
server_types?: {
|
|
126
|
+
available_for_migration?: number[];
|
|
127
|
+
};
|
|
128
|
+
}, serverTypeId: number): boolean;
|
|
129
|
+
/**
|
|
130
|
+
* The advice to print when a resize is impossible.
|
|
131
|
+
*
|
|
132
|
+
* A type that is unobtainable everywhere is not a capacity blip to retry
|
|
133
|
+
* through; it is retired, and the instance you hold is the last one you get.
|
|
134
|
+
*/
|
|
135
|
+
export declare function resizeAdvice(input: {
|
|
136
|
+
targetType: string;
|
|
137
|
+
migratableAnywhere: boolean;
|
|
138
|
+
ownedInstances: number;
|
|
139
|
+
}): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/drivers/index.js
CHANGED
|
@@ -15,6 +15,10 @@ import type { ComputeServicesConfig, DatabaseConfig } from '@ts-cloud/core';
|
|
|
15
15
|
* True when the database is co-located with the box (the managed-services
|
|
16
16
|
* engine): no host configured, or an explicit loopback host. Anything else is
|
|
17
17
|
* an external/managed database reached over TCP.
|
|
18
|
+
*
|
|
19
|
+
* An always-external engine is never local regardless of host — pointing one
|
|
20
|
+
* at 127.0.0.1 means a tunnel or a local proxy, not an engine this box
|
|
21
|
+
* installed and can administer over a unix socket.
|
|
18
22
|
*/
|
|
19
23
|
export declare function isLocalDatabase(database: DatabaseConfig | undefined): boolean;
|
|
20
24
|
/**
|
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared deploy script helpers for Forge-style compute deploys.
|
|
3
|
+
*
|
|
4
|
+
* Both server-app and server-static sites deploy with **zero downtime** the same
|
|
5
|
+
* way PHP/Laravel sites do (Envoyer-style): the artifact is unpacked into a fresh
|
|
6
|
+
* `releases/<id>` directory, shared paths (`.env`) are symlinked in, and the
|
|
7
|
+
* `current` symlink is repointed atomically (`mv -Tf`). The gateway serves the
|
|
8
|
+
* site from `<base>/current`, so a static swap is instantaneous (no window where
|
|
9
|
+
* the docroot is empty), and an app restart re-execs against the already-staged
|
|
10
|
+
* release (no window where the code is half-replaced). Old releases are kept for
|
|
11
|
+
* instant rollback. See {@link import('./releases')}.
|
|
12
|
+
*/
|
|
13
|
+
import type { SharedPathEntry } from '@ts-cloud/core';
|
|
1
14
|
/**
|
|
2
15
|
* Translate a `start` command (e.g. "bun run server.ts") into an absolute
|
|
3
16
|
* systemd ExecStart by swapping the leading runtime word for its absolute path.
|
|
@@ -30,8 +43,11 @@ export interface BuildSiteDeployScriptOptions {
|
|
|
30
43
|
* survive a deploy. `.env` is always shared; anything the app WRITES and must
|
|
31
44
|
* keep (a state directory, a database file) has to be listed here or the next
|
|
32
45
|
* release silently starts from empty.
|
|
46
|
+
*
|
|
47
|
+
* A `SharedPathSpec` entry points somewhere other than this site's own
|
|
48
|
+
* `shared/` — how several sites of one project share one file.
|
|
33
49
|
*/
|
|
34
|
-
sharedPaths?: readonly
|
|
50
|
+
sharedPaths?: readonly SharedPathEntry[];
|
|
35
51
|
/**
|
|
36
52
|
* True zero-downtime cutover for ported sites: the new release runs as its
|
|
37
53
|
* own systemd instance (`<slug>-<site>@<releaseId>`) that binds the same
|
|
@@ -27,6 +27,8 @@ export declare const PANTRY_PACKAGES: {
|
|
|
27
27
|
readonly mysql: 'mysql.com';
|
|
28
28
|
readonly mariadb: 'mariadb.com/server';
|
|
29
29
|
readonly postgres: 'postgresql.org';
|
|
30
|
+
readonly vitess: 'vitess.io';
|
|
31
|
+
readonly etcd: 'etcd.io';
|
|
30
32
|
readonly redis: 'redis.io';
|
|
31
33
|
readonly memcached: 'memcached.org';
|
|
32
34
|
readonly meilisearch: 'meilisearch.com';
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* $CREATE_RELEASE → {@link buildEnsureReleaseLayout} + git clone + {@link buildLinkSharedPaths}
|
|
13
13
|
* $ACTIVATE_RELEASE → {@link buildActivateRelease} (+ {@link buildPruneReleases})
|
|
14
14
|
*/
|
|
15
|
+
import type { SharedPathEntry } from '@ts-cloud/core';
|
|
15
16
|
/** Paths that are always shared across releases (Forge shares `.env` implicitly). */
|
|
16
17
|
export declare const DEFAULT_SHARED_PATHS: readonly string[];
|
|
17
18
|
/** Default number of past releases to retain for rollback. */
|
|
@@ -24,6 +25,13 @@ export declare function deployMetaDir(base: string): string;
|
|
|
24
25
|
export declare function deployHistoryPath(base: string): string;
|
|
25
26
|
/** Per-deploy output log path for a release. */
|
|
26
27
|
export declare function deployLogPath(base: string, releaseId: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Manifest of the shared paths the last deploy declared, written on every deploy
|
|
30
|
+
* so a rollback can relink them into an older release without knowing the site's
|
|
31
|
+
* config. Lives beside the deploy history (outside `releases/`, so pruning a
|
|
32
|
+
* release never takes it).
|
|
33
|
+
*/
|
|
34
|
+
export declare function sharedPathsManifestPath(base: string): string;
|
|
27
35
|
export interface ReleasePaths {
|
|
28
36
|
/** Site base directory (`/var/www/<site>`). */
|
|
29
37
|
base: string;
|
|
@@ -38,11 +46,25 @@ export interface ReleasePaths {
|
|
|
38
46
|
}
|
|
39
47
|
/** Resolve the standard release layout paths for a site + release id. */
|
|
40
48
|
export declare function releasePaths(base: string, releaseId: string): ReleasePaths;
|
|
49
|
+
/** The release-relative path an entry links, whichever form it takes. */
|
|
50
|
+
export declare function sharedPathOf(entry: SharedPathEntry): string;
|
|
51
|
+
/**
|
|
52
|
+
* One entry per release-relative path, last declaration winning — so a site
|
|
53
|
+
* that spells out `{ path: '.env', target: … }` overrides the implicit `.env`
|
|
54
|
+
* rather than fighting it. A plain `new Set` cannot do this: two specs for the
|
|
55
|
+
* same path are distinct objects.
|
|
56
|
+
*/
|
|
57
|
+
export declare function dedupeSharedPaths(entries: readonly SharedPathEntry[]): SharedPathEntry[];
|
|
41
58
|
/**
|
|
42
59
|
* Ensure the releases/ and shared/ skeleton exist, including the Laravel
|
|
43
60
|
* `storage` tree and an empty shared `.env` so symlinks never dangle.
|
|
61
|
+
*
|
|
62
|
+
* Also adopts any pre-existing live copy of a newly-shared path (see
|
|
63
|
+
* {@link buildAdoptSharedPathFn}) and records the shared-path list in
|
|
64
|
+
* {@link sharedPathsManifestPath}, so {@link buildRollbackScript} can relink an
|
|
65
|
+
* older release at the same shared state.
|
|
44
66
|
*/
|
|
45
|
-
export declare function buildEnsureReleaseLayout(paths: ReleasePaths, sharedPaths?: readonly
|
|
67
|
+
export declare function buildEnsureReleaseLayout(paths: ReleasePaths, sharedPaths?: readonly SharedPathEntry[]): string[];
|
|
46
68
|
/**
|
|
47
69
|
* Take the site's deploy lock for the rest of the script.
|
|
48
70
|
*
|
|
@@ -101,7 +123,18 @@ export declare function buildPromoteStagedRelease(paths: ReleasePaths): string[]
|
|
|
101
123
|
* Symlink every shared path from `shared/` into the freshly checked-out release,
|
|
102
124
|
* replacing whatever the checkout shipped (e.g. the repo's empty `storage`).
|
|
103
125
|
*/
|
|
104
|
-
export declare function buildLinkSharedPaths(paths: ReleasePaths, sharedPaths?: readonly
|
|
126
|
+
export declare function buildLinkSharedPaths(paths: ReleasePaths, sharedPaths?: readonly SharedPathEntry[]): string[];
|
|
127
|
+
/**
|
|
128
|
+
* The same links as {@link buildLinkSharedPaths}, but for a release that is
|
|
129
|
+
* already on disk and a shared-path list read from the box's manifest rather
|
|
130
|
+
* than from config. `releaseExpr` is a shell expression for the release dir.
|
|
131
|
+
*
|
|
132
|
+
* Used by rollback: a release cut before a path became shared still holds its
|
|
133
|
+
* own real copy there, so activating it would quietly swap the live state (the
|
|
134
|
+
* database) for that release's stale snapshot. A no-op on a box with no
|
|
135
|
+
* manifest — one that has never deployed a shared path.
|
|
136
|
+
*/
|
|
137
|
+
export declare function buildRelinkSharedPaths(paths: ReleasePaths, releaseExpr: string): string[];
|
|
105
138
|
/**
|
|
106
139
|
* Atomically repoint `current` at the new release. Writes a temp symlink and
|
|
107
140
|
* `mv -T`s it over `current` so there is no window where `current` is missing.
|
|
@@ -114,6 +147,12 @@ export declare function buildActivateRelease(paths: ReleasePaths): string[];
|
|
|
114
147
|
* -T`), and a no-op-safe guard fails loudly if the target is missing rather than
|
|
115
148
|
* leaving `current` dangling.
|
|
116
149
|
*
|
|
150
|
+
* Before the flip, every shared path recorded on the box is relinked into the
|
|
151
|
+
* target release ({@link buildRelinkSharedPaths}) so a rollback moves the CODE
|
|
152
|
+
* back without moving the DATA back — a release cut before a path became shared
|
|
153
|
+
* still carries its own copy, and going live with it would silently swap the
|
|
154
|
+
* database for a stale snapshot.
|
|
155
|
+
*
|
|
117
156
|
* With `unitBase` set (e.g. `myapp-api`), the script also swaps the running
|
|
118
157
|
* systemd release instance for sites deployed zero-downtime style (templated
|
|
119
158
|
* `<unitBase>@<releaseId>` units pinned to their release dirs): it starts the
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vitess provisioning.
|
|
3
|
+
*
|
|
4
|
+
* Two modes, because "run Vitess" means two very different things depending on
|
|
5
|
+
* why you are doing it:
|
|
6
|
+
*
|
|
7
|
+
* - **`combo`** runs the entire stack inside a single `vtcombo` process with
|
|
8
|
+
* an in-memory topology. It is the right answer for development and CI: one
|
|
9
|
+
* unit, one port, nothing to bootstrap, and it goes away cleanly. It is not
|
|
10
|
+
* durable and must never be used for real data.
|
|
11
|
+
* - **`cluster`** runs the real daemons (etcd, vtctld, vttablet beside a
|
|
12
|
+
* managed mysqld, vtgate) as separate systemd units on the box, with the
|
|
13
|
+
* ordering and topology bootstrap they require.
|
|
14
|
+
*
|
|
15
|
+
* ## What cluster mode is and is not
|
|
16
|
+
*
|
|
17
|
+
* This provisions a **single-box** Vitess: every component on one machine.
|
|
18
|
+
* That is a genuine deployment for staging, small production, and any case
|
|
19
|
+
* where you want Vitess's online DDL and query routing without yet needing
|
|
20
|
+
* horizontal scale. It is deliberately NOT a multi-box sharded cluster:
|
|
21
|
+
* spreading tablets across machines means per-shard placement, cross-box
|
|
22
|
+
* topology, and reparent policy, which are decisions an operator has to make
|
|
23
|
+
* rather than defaults a provisioner should invent.
|
|
24
|
+
*
|
|
25
|
+
* So a sharded keyspace here has its shards' tablets on one host. That gives
|
|
26
|
+
* you the routing and DDL semantics of Vitess and none of the fault
|
|
27
|
+
* tolerance, which is the honest trade and is stated in the config docs.
|
|
28
|
+
*
|
|
29
|
+
* ## Ordering is the whole problem
|
|
30
|
+
*
|
|
31
|
+
* Vitess daemons are not independent. vtctld and vttablet both need the
|
|
32
|
+
* topology store; vttablet also needs its mysqld; vtgate needs topology to
|
|
33
|
+
* route. Starting them in the wrong order does not fail cleanly - components
|
|
34
|
+
* retry, so a mis-ordered stack comes up "green" and then behaves oddly under
|
|
35
|
+
* load. The units below encode the dependency graph in `After=`/`Requires=`
|
|
36
|
+
* so systemd enforces it rather than relying on retry luck.
|
|
37
|
+
*/
|
|
38
|
+
import type { VitessKeyspaceConfig, VitessServiceConfig } from '@ts-cloud/core';
|
|
39
|
+
import type { PantrySpec } from './package-manager';
|
|
40
|
+
/** Where pantry exposes installed binaries. */
|
|
41
|
+
export declare const PANTRY_BIN: string;
|
|
42
|
+
/** vtgate's MySQL-protocol port. Applications connect here. */
|
|
43
|
+
export declare const VTGATE_MYSQL_PORT = 15306;
|
|
44
|
+
/** vtgate's gRPC port. */
|
|
45
|
+
export declare const VTGATE_GRPC_PORT = 15991;
|
|
46
|
+
/** vtctld's gRPC port. `vtctldclient --server` targets this. */
|
|
47
|
+
export declare const VTCTLD_GRPC_PORT = 15999;
|
|
48
|
+
/** vttablet's gRPC port. */
|
|
49
|
+
export declare const VTTABLET_GRPC_PORT = 16101;
|
|
50
|
+
/** Where etcd listens for the topology store. */
|
|
51
|
+
export declare const ETCD_CLIENT_PORT = 2379;
|
|
52
|
+
/** Root directory for Vitess state on the box. */
|
|
53
|
+
export declare const VITESS_ROOT = "/var/lib/vitess";
|
|
54
|
+
/**
|
|
55
|
+
* Tablet UID for the single-box tablet.
|
|
56
|
+
*
|
|
57
|
+
* Shared by mysqlctld and vttablet on purpose: they must agree, because
|
|
58
|
+
* Vitess derives the tablet's working directory (and therefore its mysqld
|
|
59
|
+
* socket) from `$VTDATAROOT/vt_<uid>`. Two different values silently give
|
|
60
|
+
* the tablet a mysqld it cannot find.
|
|
61
|
+
*/
|
|
62
|
+
export declare const VITESS_TABLET_UID = 100;
|
|
63
|
+
/** Re-exported so callers of the provisioner need only one import. */
|
|
64
|
+
export type { VitessKeyspaceConfig, VitessServiceConfig };
|
|
65
|
+
export declare function enabled(value: boolean | VitessServiceConfig | undefined): value is true | VitessServiceConfig;
|
|
66
|
+
/** Packages a Vitess box needs, given the mode and whether etcd is external. */
|
|
67
|
+
export declare function vitessPackages(config: VitessServiceConfig): PantrySpec[];
|
|
68
|
+
/**
|
|
69
|
+
* The unprivileged account every Vitess daemon runs as.
|
|
70
|
+
*
|
|
71
|
+
* Not a hardening nicety: Vitess refuses to start as root outright
|
|
72
|
+
* ("running this as root makes no sense" from servenv.Init), so a unit with
|
|
73
|
+
* no `User=` crash-loops immediately on every daemon.
|
|
74
|
+
*/
|
|
75
|
+
export declare const VITESS_USER = "vitess";
|
|
76
|
+
/** Directory holding the generated launcher scripts. */
|
|
77
|
+
export declare const VITESS_LIB = "/usr/local/lib/vitess";
|
|
78
|
+
/** The launcher scripts recorded so far, for inspection and testing. */
|
|
79
|
+
export declare function buildLaunchers(): Map<string, string>;
|
|
80
|
+
/**
|
|
81
|
+
* The single-process development stack.
|
|
82
|
+
*
|
|
83
|
+
* `vtcombo` runs vtgate, vttablet, and vtctld together against an in-memory
|
|
84
|
+
* topology, so there is nothing to order and nothing to bootstrap. The
|
|
85
|
+
* keyspaces are declared on the command line and exist from the first start.
|
|
86
|
+
*/
|
|
87
|
+
export declare function buildVtcomboUnit(config: VitessServiceConfig): string;
|
|
88
|
+
/** etcd, the topology store every real Vitess component reads. */
|
|
89
|
+
export declare function buildEtcdUnit(): string;
|
|
90
|
+
/** vtctld: the control plane `vtctldclient` talks to. */
|
|
91
|
+
export declare function buildVtctldUnit(config: VitessServiceConfig): string;
|
|
92
|
+
/** vttablet: manages one mysqld and serves its shard. */
|
|
93
|
+
export declare function buildVttabletUnit(config: VitessServiceConfig, keyspace: string, shard: string): string;
|
|
94
|
+
/** mysqlctld: the managed mysqld a tablet owns. */
|
|
95
|
+
export declare function buildMysqlctldUnit(config: VitessServiceConfig): string;
|
|
96
|
+
/** Where the generated vtgate credentials live. */
|
|
97
|
+
export declare const VITESS_AUTH_FILE = "/etc/vitess/auth.json";
|
|
98
|
+
/**
|
|
99
|
+
* vtgate's static credentials file.
|
|
100
|
+
*
|
|
101
|
+
* vtgate defaults to `--mysql-auth-server-impl static` and exits with "no
|
|
102
|
+
* AuthServer name static registered" when no credentials are supplied, so
|
|
103
|
+
* this is required, not optional. The alternative Vitess offers is
|
|
104
|
+
* `none`, which would leave an unauthenticated MySQL endpoint - acceptable
|
|
105
|
+
* only for the loopback-bound combo stack, never for a cluster.
|
|
106
|
+
*/
|
|
107
|
+
export declare function buildVitessAuthFileScript(config: VitessServiceConfig): string[];
|
|
108
|
+
/** vtgate: the query router applications connect to. */
|
|
109
|
+
export declare function buildVtgateUnit(config: VitessServiceConfig): string;
|
|
110
|
+
/**
|
|
111
|
+
* Bootstrap the topology: register the cell, then create each keyspace.
|
|
112
|
+
*
|
|
113
|
+
* Idempotent. `AddCellInfo` and `CreateKeyspace` both fail when the object
|
|
114
|
+
* already exists, and a re-provision must not turn that into a failed deploy,
|
|
115
|
+
* so each is guarded on the corresponding read.
|
|
116
|
+
*/
|
|
117
|
+
export declare function buildVitessBootstrapScript(config: VitessServiceConfig): string[];
|
|
118
|
+
/**
|
|
119
|
+
* Wait until vtgate actually answers on its MySQL port.
|
|
120
|
+
*
|
|
121
|
+
* The deploy should fail here rather than later: a box that finished
|
|
122
|
+
* provisioning with a vtgate that never came up will accept a deploy and then
|
|
123
|
+
* fail every request, which is much harder to attribute.
|
|
124
|
+
*/
|
|
125
|
+
export declare function buildVitessHealthCheck(config: VitessServiceConfig): string[];
|
|
126
|
+
/**
|
|
127
|
+
* Full provisioning script for a Vitess box.
|
|
128
|
+
*
|
|
129
|
+
* Order matters and is deliberate: install, write every unit, reload systemd
|
|
130
|
+
* ONCE, then start in dependency order, then bootstrap, then health-gate.
|
|
131
|
+
* Reloading per-unit would make systemd act on a half-written stack.
|
|
132
|
+
*/
|
|
133
|
+
export declare function buildVitessProvisionScript(value: boolean | VitessServiceConfig | undefined): string[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ export { deployStaticSite, deployStaticSiteFull, uploadStaticFiles, invalidateCa
|
|
|
33
33
|
export { collectServerDnsDomains, hostAcceptsIpv6, IPV6_EXCLUDED_HOST_LABELS, normalizePublicIpv6, reconcileAddressRecords, removeStaleServerAddressRecords, verifyAddressRecord, } from './deploy/server-dns';
|
|
34
34
|
export type { AddressRecordReport } from './deploy/server-dns';
|
|
35
35
|
export type { EnsureDashboardLogger, ResolvedDashboardAuth, StaticSiteConfig, DeployResult, UploadOptions, ExternalDnsStaticSiteConfig, ExternalDnsDeployResult, DeploySiteConfig, DeploySiteResult, StaticSiteDnsProvider, SiteDeployKind, DeploymentValidationResult, BuildImageOptions, BuiltImage, CodeSource, DeployServerlessOptions, ResolvedContext, } from './deploy';
|
|
36
|
-
export { createCloudDriver, CloudDriverFactory, cloudDrivers, AwsDriver, HetznerDriver, HetznerClient, resolveHetznerApiToken, normalizeSshPublicKey, ensureFirewall, ensureServer, ensureSshKey, serverPublicIpv4, sshExec, sshExecOrThrow, scpUpload, waitForSsh, waitForCloudInit, buildSshArgs, generateUbuntuAppCloudInit, wrapCloudInitUserData, buildHostCleanupScript, buildSiteDeployScript, buildStaticSiteDeployScript, resolveExecStart, deployAllComputeSites, deploySiteRelease, } from './drivers';
|
|
36
|
+
export { createCloudDriver, CloudDriverFactory, cloudDrivers, AwsDriver, HetznerDriver, HetznerClient, resolveHetznerApiToken, normalizeSshPublicKey, ensureFirewall, ensureServer, ensureSshKey, serverPublicIpv4, sshExec, sshExecOrThrow, scpUpload, waitForSsh, waitForCloudInit, buildSshArgs, generateUbuntuAppCloudInit, wrapCloudInitUserData, buildHostCleanupScript, buildSiteDeployScript, buildStaticSiteDeployScript, resolveExecStart, deployAllComputeSites, deploySiteRelease, reloadRpxGateway, renewRpxCertificates, } from './drivers';
|
|
37
37
|
export type { CreateCloudDriverOptions } from './drivers/factory';
|
|
38
38
|
export { dashboardActions, resolveDashboardAction, sanitizeCloudConfig, startLocalDashboardServer, } from './deploy/local-dashboard-server';
|
|
39
39
|
export type { DashboardAction, LocalDashboardServer, LocalDashboardServerOptions, } from './deploy/local-dashboard-server';
|
package/dist/index.js
CHANGED
|
@@ -283,7 +283,7 @@ import {
|
|
|
283
283
|
volumeCapabilities,
|
|
284
284
|
webhookEndpoint,
|
|
285
285
|
zeroCapacity
|
|
286
|
-
} from "./chunk-
|
|
286
|
+
} from "./chunk-0htae1c2.js";
|
|
287
287
|
import {
|
|
288
288
|
deleteStaticSite,
|
|
289
289
|
deployStaticSite,
|
|
@@ -387,7 +387,9 @@ import {
|
|
|
387
387
|
normalizePublicIpv6,
|
|
388
388
|
normalizeSshPublicKey,
|
|
389
389
|
reconcileAddressRecords,
|
|
390
|
+
reloadRpxGateway,
|
|
390
391
|
removeStaleServerAddressRecords,
|
|
392
|
+
renewRpxCertificates,
|
|
391
393
|
resolveDashboardAuth,
|
|
392
394
|
resolveExecStart,
|
|
393
395
|
resolveHetznerApiToken,
|
|
@@ -403,7 +405,7 @@ import {
|
|
|
403
405
|
waitForCloudInit,
|
|
404
406
|
waitForSsh,
|
|
405
407
|
wrapCloudInitUserData
|
|
406
|
-
} from "./chunk-
|
|
408
|
+
} from "./chunk-bs3jfnzp.js";
|
|
407
409
|
import {
|
|
408
410
|
ABTestManager,
|
|
409
411
|
AI,
|
|
@@ -5254,11 +5256,13 @@ export {
|
|
|
5254
5256
|
requiresReplacement,
|
|
5255
5257
|
requestHash,
|
|
5256
5258
|
replicaManager,
|
|
5259
|
+
renewRpxCertificates,
|
|
5257
5260
|
renderServerCron,
|
|
5258
5261
|
renderComposeTemplate,
|
|
5259
5262
|
removeStaleServerAddressRecords,
|
|
5260
5263
|
removeSourceWebhook,
|
|
5261
5264
|
remapKey,
|
|
5265
|
+
reloadRpxGateway,
|
|
5262
5266
|
releaseTrafficPlan,
|
|
5263
5267
|
releaseStrategyCapabilities,
|
|
5264
5268
|
regionPairManager,
|