@localctl/cli 0.2.0 → 0.4.0
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/LICENSE +21 -21
- package/README.md +398 -431
- package/assets/manifests/namespace-addons.yaml +4 -4
- package/assets/manifests/tls-store.yaml +8 -8
- package/bin/localctl.js +2 -2
- package/package.json +61 -54
- package/src/commands/addons.js +56 -56
- package/src/commands/doctor.js +44 -43
- package/src/commands/down.js +35 -35
- package/src/commands/exec.js +15 -15
- package/src/commands/generateManifests.js +12 -12
- package/src/commands/hosts.js +23 -23
- package/src/commands/logs.js +45 -45
- package/src/commands/profiles.js +180 -180
- package/src/commands/prune.js +49 -49
- package/src/commands/registryInfo.js +18 -18
- package/src/commands/reload.js +44 -44
- package/src/commands/secrets.js +75 -75
- package/src/commands/setup.js +36 -36
- package/src/commands/status.js +136 -136
- package/src/commands/up.js +123 -123
- package/src/index.js +38 -36
- package/src/lib/addonDirs.js +43 -43
- package/src/lib/addonLoader.js +190 -190
- package/src/lib/addons/cluster/logging/addon.yaml +46 -46
- package/src/lib/addons/cluster/logging/config/all-logs.json +21 -21
- package/src/lib/addons/cluster/monitoring/addon.yaml +33 -33
- package/src/lib/addons/mongo/addon.yaml +18 -18
- package/src/lib/addons/postgres/addon.yaml +39 -39
- package/src/lib/addons/redis/addon.yaml +29 -29
- package/src/lib/appSecrets.js +60 -60
- package/src/lib/clusterAddons.js +59 -59
- package/src/lib/clusterProvision.js +171 -170
- package/src/lib/configSchema.js +103 -103
- package/src/lib/constants.js +16 -16
- package/src/lib/engine.js +36 -20
- package/src/lib/exec.js +77 -77
- package/src/lib/hostsFile.js +79 -79
- package/src/lib/loadConfig.js +51 -51
- package/src/lib/logger.js +9 -9
- package/src/lib/manifestGen.js +210 -210
- package/src/lib/paths.js +41 -41
- package/src/lib/podman.js +72 -72
- package/src/lib/profileStore.js +134 -134
- package/src/lib/projectContext.js +32 -32
- package/src/lib/prompt.js +97 -97
- package/src/lib/toolInstall.js +30 -30
- package/src/lib/ui.js +50 -50
- package/src/lib/updateCheck.js +84 -0
- package/src/lib/updateCheckWorker.js +46 -0
- package/src/lib/workloadReadiness.js +35 -35
- package/templates/Tiltfile.tmpl +35 -35
package/README.md
CHANGED
|
@@ -1,431 +1,398 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
-
|
|
30
|
-
|
|
31
|
-
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
-
|
|
41
|
-
|
|
42
|
-
-
|
|
43
|
-
|
|
44
|
-
-
|
|
45
|
-
|
|
46
|
-
-
|
|
47
|
-
|
|
48
|
-
-
|
|
49
|
-
|
|
50
|
-
-
|
|
51
|
-
|
|
52
|
-
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
localctl
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
localctl app up
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
(
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
##
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
- [docs/getting-started.md](./docs/getting-started.md) — the install/quickstart flow, in more detail
|
|
400
|
-
- [docs/architecture.md](./docs/architecture.md) — every component and why it was chosen, with diagrams
|
|
401
|
-
- [docs/config-schema.md](./docs/config-schema.md) — full `.local/config.json` reference
|
|
402
|
-
- [docs/adding-tools.md](./docs/adding-tools.md) — add new per-app or cluster-wide addons
|
|
403
|
-
- [docs/debugging.md](./docs/debugging.md) — attach a debugger, per language
|
|
404
|
-
- [docs/uninstalling.md](./docs/uninstalling.md) — full teardown reference
|
|
405
|
-
- [docs/troubleshooting.md](./docs/troubleshooting.md) — known issues and fixes
|
|
406
|
-
|
|
407
|
-
## Docs Site
|
|
408
|
-
|
|
409
|
-
Everything under `docs/` is also published as a [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/)
|
|
410
|
-
site — search, dark/light mode, and the Mermaid diagrams in [Architecture](./docs/architecture.md)
|
|
411
|
-
rendered properly (GitHub renders Mermaid too, but the site's theme is nicer for reading).
|
|
412
|
-
|
|
413
|
-
**One-time setup**, once this repo has a real GitHub remote:
|
|
414
|
-
|
|
415
|
-
1. In `mkdocs.yml`, replace every `USERNAME` with your GitHub username (or org), and in this
|
|
416
|
-
README's link at the top.
|
|
417
|
-
2. Push to GitHub, then in the repo's **Settings → Pages**, set **Source** to **Deploy from a
|
|
418
|
-
branch** and **Branch** to **`gh-pages`** / **`/ (root)`**. (The first push of
|
|
419
|
-
`.github/workflows/docs.yml` below creates that branch for you — the option won't appear in the
|
|
420
|
-
dropdown until after that first run.)
|
|
421
|
-
|
|
422
|
-
From then on, **every push to `master`** rebuilds and redeploys the site automatically
|
|
423
|
-
(`.github/workflows/docs.yml`) — nothing to run by hand.
|
|
424
|
-
|
|
425
|
-
To preview locally before pushing:
|
|
426
|
-
|
|
427
|
-
```bash
|
|
428
|
-
python3 -m venv .venv && source .venv/bin/activate
|
|
429
|
-
pip install mkdocs-material
|
|
430
|
-
mkdocs serve # http://127.0.0.1:8000, live-reloads on save
|
|
431
|
-
```
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="https://raw.githubusercontent.com/psilvmoreira/localctl/master/docs/assets/favicon.svg" alt="localctl logo" width="96" height="96">
|
|
4
|
+
|
|
5
|
+
# localctl
|
|
6
|
+
|
|
7
|
+
**Local Kubernetes for app developers. One CLI, one cluster, a real HTTPS subdomain per app.**
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/@localctl/cli)
|
|
10
|
+
[](https://www.npmjs.com/package/@localctl/cli)
|
|
11
|
+
[](https://nodejs.org)
|
|
12
|
+
[](https://github.com/psilvmoreira/localctl/blob/master/LICENSE)
|
|
13
|
+
<br>
|
|
14
|
+
[](https://github.com/psilvmoreira/localctl/actions/workflows/release.yml)
|
|
15
|
+
[](https://github.com/psilvmoreira/localctl/actions/workflows/ci.yml)
|
|
16
|
+
[](https://psilvmoreira.github.io/localctl/)
|
|
17
|
+
[](https://github.com/semantic-release/semantic-release)
|
|
18
|
+
|
|
19
|
+
[**Documentation**](https://psilvmoreira.github.io/localctl/) ·
|
|
20
|
+
[**Getting started**](https://psilvmoreira.github.io/localctl/getting-started/) ·
|
|
21
|
+
[**Releases**](https://github.com/psilvmoreira/localctl/releases) ·
|
|
22
|
+
[**Report a bug**](https://github.com/psilvmoreira/localctl/issues/new)
|
|
23
|
+
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
```console
|
|
27
|
+
$ npm install -g @localctl/cli
|
|
28
|
+
$ localctl setup
|
|
29
|
+
$ cd my-app && localctl app new && localctl app up
|
|
30
|
+
|
|
31
|
+
ok my-app -> https://my-app.local.test
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Table of contents
|
|
37
|
+
|
|
38
|
+
- [Why localctl](#why-localctl)
|
|
39
|
+
- [Requirements](#requirements)
|
|
40
|
+
- [Installation](#installation)
|
|
41
|
+
- [Supported container engines](#supported-container-engines)
|
|
42
|
+
- [Updating](#updating)
|
|
43
|
+
- [Quick start](#quick-start)
|
|
44
|
+
- [Commands](#commands)
|
|
45
|
+
- [Configuration](#configuration)
|
|
46
|
+
- [Addons](#addons)
|
|
47
|
+
- [How it works](#how-it-works)
|
|
48
|
+
- [Documentation](#documentation)
|
|
49
|
+
- [Releases and versioning](#releases-and-versioning)
|
|
50
|
+
- [Contributing](#contributing)
|
|
51
|
+
- [Uninstalling](#uninstalling)
|
|
52
|
+
- [License](#license)
|
|
53
|
+
|
|
54
|
+
## Why localctl
|
|
55
|
+
|
|
56
|
+
Running several apps on Kubernetes locally usually means port juggling, hand-written YAML,
|
|
57
|
+
self-signed certificate warnings, and slow rebuilds. `localctl` replaces all of that with one
|
|
58
|
+
JSON file per app.
|
|
59
|
+
|
|
60
|
+
| | |
|
|
61
|
+
|---|---|
|
|
62
|
+
| 🧩 **One cluster, one CLI** | A single [k3d](https://k3d.io) cluster runs every app you develop. No per-project Kubernetes setup. |
|
|
63
|
+
| 🌐 **A subdomain per app** | `orders.local.test`, `billing.local.test`, routed by Traefik. No `localhost:3000` vs `:3001`. |
|
|
64
|
+
| 🔒 **HTTPS by default** | A locally-trusted wildcard certificate (via [mkcert](https://github.com/FiloSottile/mkcert)). Green padlock, no browser warnings. |
|
|
65
|
+
| 📄 **Config, not YAML** | Each app has one `.local/config.json`. Every Kubernetes manifest is generated from it. |
|
|
66
|
+
| ⚡ **Fast inner loop** | [Tilt](https://tilt.dev) builds, deploys, and live-syncs changed files into the running container. |
|
|
67
|
+
| 🐞 **Debugger-friendly** | Debug ports forwarded to `localhost`. Node, Python, Go, Java and .NET patterns included. |
|
|
68
|
+
| 🗄️ **Databases in one line** | Postgres, Redis and MongoDB per app, from real Helm charts, with credentials injected as Secrets. |
|
|
69
|
+
| 🐳 **Podman first** | Podman quirks (BuildKit, insecure registry) are detected and handled automatically. Docker Desktop and Rancher Desktop support is [experimental](#supported-container-engines). |
|
|
70
|
+
| 🧹 **Clean uninstall** | `localctl uninstall` reverses everything `localctl setup` did. |
|
|
71
|
+
|
|
72
|
+
## Requirements
|
|
73
|
+
|
|
74
|
+
| Requirement | Notes |
|
|
75
|
+
|---|---|
|
|
76
|
+
| **macOS** or **Windows** | Windows commands run in PowerShell. |
|
|
77
|
+
| **Node.js 18+** | Needed to install the CLI from npm. |
|
|
78
|
+
| **Container engine** | [Podman Desktop](https://podman-desktop.io/), running. See [supported container engines](#supported-container-engines). |
|
|
79
|
+
| **Homebrew** or **winget** | Used once by `localctl setup` to install missing tools. |
|
|
80
|
+
|
|
81
|
+
`localctl setup` installs `k3d`, `kubectl`, `tilt`, `mkcert` and `helm` for you if they're missing.
|
|
82
|
+
|
|
83
|
+
### Supported container engines
|
|
84
|
+
|
|
85
|
+
| Engine | Status |
|
|
86
|
+
|---|---|
|
|
87
|
+
| [Podman Desktop](https://podman-desktop.io/) | ✅ Tested |
|
|
88
|
+
| [Docker Desktop](https://www.docker.com/products/docker-desktop/) | 🧪 Experimental — not yet tested |
|
|
89
|
+
| [Rancher Desktop](https://rancherdesktop.io/) | 🧪 Experimental — not yet tested |
|
|
90
|
+
|
|
91
|
+
Experimental engines are detected and should work, since k3d only needs a Docker-compatible API,
|
|
92
|
+
but they haven't been through a full test cycle yet. `localctl setup` and `localctl doctor` print
|
|
93
|
+
a warning when one is in use. If you try one, please
|
|
94
|
+
[report how it went](https://github.com/psilvmoreira/localctl/issues/new).
|
|
95
|
+
|
|
96
|
+
## Installation
|
|
97
|
+
|
|
98
|
+
```sh
|
|
99
|
+
npm install -g @localctl/cli
|
|
100
|
+
localctl setup
|
|
101
|
+
localctl doctor # every line should read [ok]
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`localctl setup` detects your container engine, installs missing tools, creates the cluster and
|
|
105
|
+
the local image registry, trusts the `*.local.test` certificate, and updates your hosts file. It
|
|
106
|
+
is idempotent: run it again any time to repair your environment.
|
|
107
|
+
|
|
108
|
+
You'll see up to two one-time prompts during setup: **mkcert** asking to trust its local
|
|
109
|
+
certificate authority, and **sudo/Administrator** to write the `*.local.test` hosts entries.
|
|
110
|
+
|
|
111
|
+
**Pre-releases** are published under the `beta` tag: `npm install -g @localctl/cli@beta`.
|
|
112
|
+
|
|
113
|
+
### Updating
|
|
114
|
+
|
|
115
|
+
`localctl` checks npm for a new version at most once a day, in the background, and tells you
|
|
116
|
+
when one is available:
|
|
117
|
+
|
|
118
|
+
```console
|
|
119
|
+
Update available: 0.2.0 -> 0.3.0
|
|
120
|
+
Run npm install -g @localctl/cli to update.
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Update with `npm install -g @localctl/cli`. The check never slows a command down, is skipped in
|
|
124
|
+
CI, and can be turned off with `LOCALCTL_NO_UPDATE_CHECK=1`.
|
|
125
|
+
|
|
126
|
+
<details>
|
|
127
|
+
<summary><b>Getting <code>EACCES</code> on <code>npm install -g</code>?</b></summary>
|
|
128
|
+
|
|
129
|
+
npm's global directory isn't writable by your user, which is common on macOS when Node wasn't
|
|
130
|
+
installed through a version manager. Fix it once for every global install
|
|
131
|
+
([npm's documented fix](https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally)):
|
|
132
|
+
|
|
133
|
+
```sh
|
|
134
|
+
mkdir ~/.npm-global
|
|
135
|
+
npm config set prefix ~/.npm-global
|
|
136
|
+
echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> ~/.zshrc # or ~/.bash_profile
|
|
137
|
+
source ~/.zshrc
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
</details>
|
|
141
|
+
|
|
142
|
+
<details>
|
|
143
|
+
<summary><b>Install from source</b> (to work on localctl itself)</summary>
|
|
144
|
+
|
|
145
|
+
```sh
|
|
146
|
+
git clone https://github.com/psilvmoreira/localctl.git
|
|
147
|
+
cd localctl/cli
|
|
148
|
+
npm install
|
|
149
|
+
npm install -g .
|
|
150
|
+
localctl setup
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Or, without touching npm's global config, use the bootstrap scripts. They install a
|
|
154
|
+
self-contained shim in `~/.localctl/bin` and run `localctl setup` for you:
|
|
155
|
+
|
|
156
|
+
```sh
|
|
157
|
+
./bin/bootstrap.sh # macOS
|
|
158
|
+
./bin/bootstrap.ps1 # Windows (PowerShell)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
</details>
|
|
162
|
+
|
|
163
|
+
## Quick start
|
|
164
|
+
|
|
165
|
+
**1. Scaffold** — from inside your app's repository:
|
|
166
|
+
|
|
167
|
+
```sh
|
|
168
|
+
localctl app new
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
This asks for an app name and port, then creates `.local/config.json` and a `Tiltfile`.
|
|
172
|
+
|
|
173
|
+
**2. Deploy:**
|
|
174
|
+
|
|
175
|
+
```console
|
|
176
|
+
$ localctl app up
|
|
177
|
+
> Waiting for the deployment to become ready...
|
|
178
|
+
deployment "my-app" successfully rolled out
|
|
179
|
+
|
|
180
|
+
ok my-app -> https://my-app.local.test
|
|
181
|
+
debug: localhost:9229
|
|
182
|
+
logs: localctl app logs my-app -f
|
|
183
|
+
status: localctl app status
|
|
184
|
+
stop: localctl app down
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
The dev loop runs in the background, so closing the terminal doesn't stop it. Edit a file under
|
|
188
|
+
a `sync` path and it updates in the running container without a full rebuild. Use
|
|
189
|
+
`localctl app up -f` for the interactive Tilt UI instead.
|
|
190
|
+
|
|
191
|
+
**3. Check on it:**
|
|
192
|
+
|
|
193
|
+
```console
|
|
194
|
+
$ localctl app status
|
|
195
|
+
APP NAMESPACE READY URL DEV LOOP
|
|
196
|
+
my-app my-app 1/1 https://my-app.local.test running (pid 4815)
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
**4. Stop it:**
|
|
200
|
+
|
|
201
|
+
```sh
|
|
202
|
+
localctl app down
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
This removes only that app. The shared cluster keeps running for everything else.
|
|
206
|
+
|
|
207
|
+
> **Tip:** no app of your own yet? Clone the repo and try a ready-made example:
|
|
208
|
+
> [`node-app`](https://github.com/psilvmoreira/localctl/tree/master/examples/node-app) (Node.js + Postgres),
|
|
209
|
+
> [`python-app`](https://github.com/psilvmoreira/localctl/tree/master/examples/python-app) (Python + Redis), or
|
|
210
|
+
> [`dotnet-api`](https://github.com/psilvmoreira/localctl/tree/master/examples/dotnet-api) (.NET).
|
|
211
|
+
|
|
212
|
+
## Commands
|
|
213
|
+
|
|
214
|
+
Run `localctl <command> --help` for every option.
|
|
215
|
+
|
|
216
|
+
<details open>
|
|
217
|
+
<summary><b>Machine setup</b></summary>
|
|
218
|
+
|
|
219
|
+
| Command | Description |
|
|
220
|
+
|---|---|
|
|
221
|
+
| `localctl setup` | Install or repair the infrastructure: container engine, cluster, TLS, hosts. Idempotent. |
|
|
222
|
+
| `localctl doctor` | Health check of the active project's environment. |
|
|
223
|
+
| `localctl hosts sync` / `list` | Manage the `*.local.test` entries in your hosts file. |
|
|
224
|
+
| `localctl uninstall [-y]` | Remove every cluster, registry, hosts entry, certificate and state file `localctl` created. |
|
|
225
|
+
|
|
226
|
+
</details>
|
|
227
|
+
|
|
228
|
+
<details open>
|
|
229
|
+
<summary><b>Apps</b></summary>
|
|
230
|
+
|
|
231
|
+
| Command | Description |
|
|
232
|
+
|---|---|
|
|
233
|
+
| `localctl app new` | Scaffold `.local/config.json` and a `Tiltfile` in the current repository. |
|
|
234
|
+
| `localctl app up [-f]` | Build, deploy and live-reload the app. Background by default; `-f` for the Tilt UI. |
|
|
235
|
+
| `localctl app down` | Stop the dev loop and remove the app. Keeps its data. |
|
|
236
|
+
| `localctl app reload [-a <name>]` | Force a rebuild and redeploy without waiting for a file change. |
|
|
237
|
+
| `localctl app status [-a <name>] [-A]` | One app's detail inside its repository, or a table of every app. |
|
|
238
|
+
| `localctl app logs <name> [-f]` | Show or follow an app's logs. |
|
|
239
|
+
| `localctl app exec [cmd...]` | Open a shell (default `sh`) in the app's pod. |
|
|
240
|
+
| `localctl app prune [-y]` | Delete leftover data (volumes, secrets) of apps already taken down. |
|
|
241
|
+
| `localctl app secrets set <KEY> [value]` | Store a secret as a Kubernetes Secret, never in `config.json`. |
|
|
242
|
+
| `localctl app secrets list` / `show [KEY]` / `unset <KEY>` | List, reveal or remove secrets. |
|
|
243
|
+
|
|
244
|
+
</details>
|
|
245
|
+
|
|
246
|
+
<details open>
|
|
247
|
+
<summary><b>Addons and projects</b></summary>
|
|
248
|
+
|
|
249
|
+
| Command | Description |
|
|
250
|
+
|---|---|
|
|
251
|
+
| `localctl addons list` / `status` | Show available addons and what is running in the cluster. |
|
|
252
|
+
| `localctl addons enable <name>` / `disable <name>` | Turn a cluster-wide addon (`logging`, `monitoring`) on or off. |
|
|
253
|
+
| `localctl profiles new <name>` | Create an isolated project: its own cluster, or a namespace in an existing one. |
|
|
254
|
+
| `localctl profiles list` / `status` | Show every project, or the active one. |
|
|
255
|
+
| `localctl profiles switch <name>` | Make a project active and start its cluster if needed. |
|
|
256
|
+
|
|
257
|
+
</details>
|
|
258
|
+
|
|
259
|
+
## Configuration
|
|
260
|
+
|
|
261
|
+
Everything about how an app runs locally lives in its `.local/config.json`:
|
|
262
|
+
|
|
263
|
+
```json
|
|
264
|
+
{
|
|
265
|
+
"name": "orders-api",
|
|
266
|
+
"subdomain": "orders",
|
|
267
|
+
"port": 3000,
|
|
268
|
+
"build": { "context": ".", "dockerfile": "Dockerfile" },
|
|
269
|
+
"env": { "NODE_ENV": "development" },
|
|
270
|
+
"debug": { "enabled": true, "port": 9229, "type": "node" },
|
|
271
|
+
"dependencies": [{ "type": "postgres", "database": "orders" }],
|
|
272
|
+
"sync": [{ "localPath": "./src", "remotePath": "/app/src" }],
|
|
273
|
+
"tls": true
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
This deploys `orders-api` at `https://orders.local.test`, with its own Postgres instance and the
|
|
278
|
+
Node.js debugger on `localhost:9229`.
|
|
279
|
+
|
|
280
|
+
A [JSON Schema](https://github.com/psilvmoreira/localctl/blob/master/schema/app.schema.json) is
|
|
281
|
+
available for editor autocomplete and validation. Full field reference:
|
|
282
|
+
[**Config schema**](https://psilvmoreira.github.io/localctl/config-schema/).
|
|
283
|
+
|
|
284
|
+
## Addons
|
|
285
|
+
|
|
286
|
+
Every addon is one `addon.yaml` file pointing at a published Helm chart. No code required.
|
|
287
|
+
|
|
288
|
+
| Addon | Scope | Enable with | Chart |
|
|
289
|
+
|---|---|---|---|
|
|
290
|
+
| `postgres` | Per app | `"dependencies": [{ "type": "postgres" }]` | Bitnami |
|
|
291
|
+
| `redis` | Per app | `"dependencies": [{ "type": "redis" }]` | Bitnami |
|
|
292
|
+
| `mongo` | Per app | `"dependencies": [{ "type": "mongo" }]` | Bitnami |
|
|
293
|
+
| `logging` | Cluster | `localctl addons enable logging` → `https://grafana.local.test` | Grafana `loki-stack` |
|
|
294
|
+
| `monitoring` | Cluster | `localctl addons enable monitoring` → `https://monitoring.local.test` | `prometheus-community` |
|
|
295
|
+
|
|
296
|
+
Per-app dependencies get their connection details injected into the app container, and a
|
|
297
|
+
`wait-for-<type>` init container so the app never starts before its database is ready.
|
|
298
|
+
To add your own addon, see [**Adding tools**](https://psilvmoreira.github.io/localctl/adding-tools/).
|
|
299
|
+
|
|
300
|
+
## How it works
|
|
301
|
+
|
|
302
|
+
```
|
|
303
|
+
.local/config.json ──► localctl ──► Kubernetes manifests ──► Tilt ──► k3d cluster
|
|
304
|
+
(your app repo) validates (generated, never builds, Traefik ingress
|
|
305
|
+
+ generates hand-written) pushes, + local registry
|
|
306
|
+
live-syncs + *.local.test TLS
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
`localctl` validates the config, generates every manifest, and manages the cluster lifecycle.
|
|
310
|
+
Tilt handles the build, push and live-sync loop. Full breakdown, including multi-project support
|
|
311
|
+
and Podman handling: [**Architecture**](https://psilvmoreira.github.io/localctl/architecture/).
|
|
312
|
+
|
|
313
|
+
## Documentation
|
|
314
|
+
|
|
315
|
+
The full documentation lives at **[psilvmoreira.github.io/localctl](https://psilvmoreira.github.io/localctl/)**.
|
|
316
|
+
|
|
317
|
+
| Guide | What's inside |
|
|
318
|
+
|---|---|
|
|
319
|
+
| [Getting started](https://psilvmoreira.github.io/localctl/getting-started/) | Install and first deploy, step by step |
|
|
320
|
+
| [Architecture](https://psilvmoreira.github.io/localctl/architecture/) | Every component, why it was chosen, multi-project support |
|
|
321
|
+
| [Config schema](https://psilvmoreira.github.io/localctl/config-schema/) | Every `.local/config.json` field |
|
|
322
|
+
| [Debugging](https://psilvmoreira.github.io/localctl/debugging/) | Attach a debugger in Node, Python, Go, Java and .NET |
|
|
323
|
+
| [Adding tools](https://psilvmoreira.github.io/localctl/adding-tools/) | Write your own per-app or cluster-wide addon |
|
|
324
|
+
| [Troubleshooting](https://psilvmoreira.github.io/localctl/troubleshooting/) | Known issues, with cause and fix |
|
|
325
|
+
| [Uninstalling](https://psilvmoreira.github.io/localctl/uninstalling/) | Full teardown reference |
|
|
326
|
+
| [Releasing](https://psilvmoreira.github.io/localctl/releasing/) | How versions are cut and published |
|
|
327
|
+
|
|
328
|
+
## Releases and versioning
|
|
329
|
+
|
|
330
|
+
- Releases are fully automated: every merge to `master` is analysed by
|
|
331
|
+
[semantic-release](https://github.com/semantic-release/semantic-release), which picks the next
|
|
332
|
+
version, publishes to npm and creates a [GitHub Release](https://github.com/psilvmoreira/localctl/releases)
|
|
333
|
+
with notes and the package tarball.
|
|
334
|
+
- Versions follow [Semantic Versioning](https://semver.org). Before `1.0.0`, minor versions may
|
|
335
|
+
contain breaking changes.
|
|
336
|
+
- npm releases are published from GitHub Actions with
|
|
337
|
+
[provenance](https://docs.npmjs.com/generating-provenance-statements). The npm package page links
|
|
338
|
+
each version to the exact commit and workflow run that built it.
|
|
339
|
+
|
|
340
|
+
## Contributing
|
|
341
|
+
|
|
342
|
+
Issues and pull requests are welcome.
|
|
343
|
+
|
|
344
|
+
1. Fork the repository and create a branch.
|
|
345
|
+
2. Make your change and run the tests:
|
|
346
|
+
```sh
|
|
347
|
+
cd cli
|
|
348
|
+
npm ci
|
|
349
|
+
npm test # every command loads, --version is correct
|
|
350
|
+
npm run test:pack # the published package installs and runs
|
|
351
|
+
```
|
|
352
|
+
3. Open a pull request with a [Conventional Commits](https://www.conventionalcommits.org/) title.
|
|
353
|
+
The title decides the next version:
|
|
354
|
+
|
|
355
|
+
| Title | Release |
|
|
356
|
+
|---|---|
|
|
357
|
+
| `fix: ...` | Patch (`0.2.0` → `0.2.1`) |
|
|
358
|
+
| `feat: ...` | Minor (`0.2.1` → `0.3.0`) |
|
|
359
|
+
| `feat!: ...` | Major (`0.3.0` → `1.0.0`) |
|
|
360
|
+
| `docs:` `chore:` `ci:` `refactor:` `test:` | No release |
|
|
361
|
+
|
|
362
|
+
<details>
|
|
363
|
+
<summary><b>Repository layout</b></summary>
|
|
364
|
+
|
|
365
|
+
```
|
|
366
|
+
localctl/
|
|
367
|
+
├── cli/ the localctl CLI (published to npm as @localctl/cli)
|
|
368
|
+
│ ├── bin/ executable entry point
|
|
369
|
+
│ ├── src/commands/ one file per command
|
|
370
|
+
│ ├── src/lib/ config validation, manifest generation, cluster/hosts/Podman handling
|
|
371
|
+
│ │ └── addons/ built-in addons (postgres, redis, mongo, logging, monitoring)
|
|
372
|
+
│ ├── templates/ Tiltfile copied into apps by `localctl app new`
|
|
373
|
+
│ └── scripts/ packaging and test scripts
|
|
374
|
+
├── cluster/manifests/ cluster-level manifests (TLS store, addon namespace)
|
|
375
|
+
├── schema/ JSON Schema for .local/config.json
|
|
376
|
+
├── examples/ ready-to-run sample apps
|
|
377
|
+
├── docs/ documentation site (MkDocs Material, deployed to GitHub Pages)
|
|
378
|
+
└── bin/ bootstrap and uninstall scripts for source installs
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
</details>
|
|
382
|
+
|
|
383
|
+
## Uninstalling
|
|
384
|
+
|
|
385
|
+
```sh
|
|
386
|
+
localctl uninstall # clusters, registries, hosts entries, certificates, state
|
|
387
|
+
npm uninstall -g @localctl/cli # the CLI itself
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
`localctl uninstall` asks for confirmation (skip with `-y`) and is safe to re-run. It leaves the
|
|
391
|
+
shared tools (`k3d`, `kubectl`, `tilt`, `mkcert`, `node`) and mkcert's root CA installed, since
|
|
392
|
+
other projects may use them. It prints the exact commands to remove them too. Installed from
|
|
393
|
+
source with the bootstrap script? Use `./bin/uninstall.sh` or `./bin/uninstall.ps1` instead.
|
|
394
|
+
Details: [**Uninstalling**](https://psilvmoreira.github.io/localctl/uninstalling/).
|
|
395
|
+
|
|
396
|
+
## License
|
|
397
|
+
|
|
398
|
+
[MIT](https://github.com/psilvmoreira/localctl/blob/master/LICENSE) © Pedro Moreira
|