tatnet 0.1.3

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.
Files changed (3) hide show
  1. package/README.md +169 -0
  2. package/bin/tatnet.js +96 -0
  3. package/package.json +38 -0
package/README.md ADDED
@@ -0,0 +1,169 @@
1
+ # tatnet — консольный клиент TatNet
2
+
3
+ `tatnet` управляет облаком TatNet из терминала: виртуальные машины,
4
+ приложения, базы Postgres и Valkey, DNS, объектное хранилище, SSH-ключи.
5
+
6
+ Построен поверх [tatnet-go](https://github.com/tatnet-ru/tatnet-go) —
7
+ клиента, генерируемого из контракта `/v1`. Рукописного HTTP здесь нет, и
8
+ контракт — тот же самый документ, что публикует API.
9
+
10
+ ## Установка
11
+
12
+ Без установки вообще — если есть Node:
13
+
14
+ ```bash
15
+ npx tatnet vm list
16
+ ```
17
+
18
+ Постоянно:
19
+
20
+ ```bash
21
+ npm i -g tatnet
22
+ ```
23
+
24
+ Бинарник качается не при установке, а приезжает готовым подпакетом на вашу
25
+ платформу (`optionalDependencies` с полями `os`/`cpu`), поэтому работает и
26
+ под `--ignore-scripts`, и из офлайн-кэша. Поддержаны linux, macOS и Windows
27
+ на x64 и arm64.
28
+
29
+ Бинарником с [релизов](https://github.com/tatnet-ru/tatnet-cli/releases)
30
+ (файлы несут номер версии, подставьте свою):
31
+
32
+ ```bash
33
+ VER=0.1.3
34
+ curl -sSL "https://github.com/tatnet-ru/tatnet-cli/releases/download/v$VER/tatnet_${VER}_linux_amd64.tar.gz" | tar xz
35
+ sudo install tatnet /usr/local/bin/
36
+ ```
37
+
38
+ Либо пакетом — `tatnet_${VER}_linux_amd64.deb` / `.rpm`. Рядом с
39
+ артефактами лежит `checksums.txt`.
40
+
41
+ Из исходников, если стоит Go:
42
+
43
+ ```bash
44
+ go install github.com/tatnet-ru/tatnet-cli/cmd/tatnet@latest
45
+ ```
46
+
47
+ ## Начало работы
48
+
49
+ Ключ создаётся в панели: **Аккаунт → API-ключи**. Ключ принадлежит одному
50
+ аккаунту и несёт свою политику прав, поэтому аккаунт нигде не указывается.
51
+
52
+ ```bash
53
+ tatnet auth login # спросит ключ, проверит его и сохранит
54
+ tatnet auth status # чей ключ и что он может
55
+ tatnet project list
56
+ tatnet profile set-project прод # проект по умолчанию
57
+ ```
58
+
59
+ Ключ проверяется до записи в конфиг: сохранённый нерабочий ключ выглядел бы
60
+ как настроенный CLI и падал бы на первой же команде.
61
+
62
+ ## Примеры
63
+
64
+ ```bash
65
+ tatnet vm list
66
+ tatnet vm get web-1 # по имени или hostname, не только по id
67
+ tatnet vm stop web-1
68
+ tatnet vm backup create web-1 --name до-обновления
69
+
70
+ tatnet app deploy магазин
71
+ tatnet app env set магазин DATABASE_URL 'postgres://…' --secret
72
+ tatnet app job run магазин миграции
73
+ tatnet app run list магазин --job миграции
74
+
75
+ tatnet pg list
76
+ tatnet pg parameters get основная # заданное рядом с применённым
77
+ tatnet pg ca основная --out ca.crt
78
+ tatnet pg backup list основная
79
+
80
+ tatnet dns record create example.com www A 185.152.80.60
81
+ tatnet s3 bucket create фото --public
82
+ tatnet s3 object presign фото отчёт.pdf
83
+ ```
84
+
85
+ ## Вывод
86
+
87
+ | `-o` | что делает |
88
+ |---|---|
89
+ | `table` | по умолчанию, только ключевые колонки |
90
+ | `wide` | плюс идентификаторы и подробности |
91
+ | `json` | ровно то, что вернул API — для скриптов |
92
+ | `yaml` | то же в YAML |
93
+
94
+ Списки вычитываются **целиком**: поле `count` в ответах API — размер
95
+ страницы, а не размер набора, поэтому конец определяется короткой
96
+ страницей. `--limit` ограничивает явно.
97
+
98
+ ## Профили
99
+
100
+ Конфиг лежит в `~/.config/tatnet/config.yaml` (или `$TATNET_CONFIG`),
101
+ пишется режимом 0600 — в нём ключ.
102
+
103
+ ```yaml
104
+ current: прод
105
+ profiles:
106
+ прод:
107
+ api_key: tn_live_…
108
+ project: 7f3c9c1e-…
109
+ стенд:
110
+ api_key: tn_live_…
111
+ base_url: https://api.stage.tatnet.ru/v1
112
+ ```
113
+
114
+ ```bash
115
+ tatnet profile list
116
+ tatnet profile use стенд
117
+ tatnet --profile стенд vm list
118
+ ```
119
+
120
+ Переменные окружения перебивают профиль, флаги — переменные:
121
+ `TATNET_API_KEY`, `TATNET_BASE_URL`, `TATNET_PROJECT`, `TATNET_PROFILE`,
122
+ `TATNET_OUTPUT`, `TATNET_CONFIG`.
123
+
124
+ ## `tatnet api` — всё остальное
125
+
126
+ Своими командами выведены 91 операция из 161. Остальные — балансировщики,
127
+ сети, Kubernetes, функции, тома, домены, сертификаты — доступны прямым
128
+ вызовом:
129
+
130
+ ```bash
131
+ tatnet api --list load-balancers # что вообще есть
132
+ tatnet api /vpcs
133
+ tatnet api /floating-ips -X POST -f name=fip-1 -f cluster_id=…
134
+ tatnet api /projects/<id>/kubernetes-clusters/<id>/kubeconfig
135
+ ```
136
+
137
+ Адрес проверяется по вшитому контракту **до** отправки: иначе опечатка
138
+ вернула бы 404, неотличимый от «такого ресурса нет». Если API новее этого
139
+ CLI — `--allow-unknown`.
140
+
141
+ ## Разрушающие действия
142
+
143
+ Удаление, сброс пароля и замена узлов спрашивают подтверждение. Когда ввод
144
+ не терминал (скрипт, CI), вопрос задать некому — такие команды **требуют
145
+ `--yes`**, а не соглашаются молча.
146
+
147
+ ## Что здесь проверяется тестами
148
+
149
+ Контракт связан с деревом команд гейтом (`internal/cli/coverage_test.go`):
150
+
151
+ * каждая операция, объявленная командой, обязана существовать в контракте —
152
+ переименовали операцию в API, CLI падает на сборке, а не у клиента;
153
+ * покрытый раздел покрыт **целиком** — новая операция в нём валит тест, а не
154
+ остаётся тихо недоступной;
155
+ * отложенный раздел не покрыт **частично** — наполовину выведенный раздел
156
+ это список, которому уже нельзя верить;
157
+ * вшитый контракт совпадает с контрактом той версии `tatnet-go`, на которой
158
+ собран CLI.
159
+
160
+ Обновление контракта: `./scripts/sync-contract.sh`, затем `go test ./...` —
161
+ гейт покажет, что появилось нового.
162
+
163
+ ## Разработка
164
+
165
+ ```bash
166
+ go build ./...
167
+ go test ./...
168
+ go run ./cmd/tatnet --help
169
+ ```
package/bin/tatnet.js ADDED
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ // Тонкая обёртка: находит бинарник своей платформы и отдаёт ему управление.
5
+ //
6
+ // Сам бинарник лежит в отдельном пакете на платформу, подключённом через
7
+ // optionalDependencies с полями os/cpu — npm ставит ровно один подходящий.
8
+ // Скачивания в postinstall здесь намеренно нет: он не работает при
9
+ // --ignore-scripts, требует сети в момент установки и ломает офлайн-кэш,
10
+ // а npx выполняется как раз в тех средах, где всё это встречается.
11
+
12
+ const { spawnSync } = require("node:child_process");
13
+ const fs = require("node:fs");
14
+ const path = require("node:path");
15
+
16
+ // Платформенные пакеты — в скоупе @tatnet: незанятые имена вида
17
+ // tatnet-cli-win32-arm64 реестр отвергает эвристикой антиспама, а имена
18
+ // внутри собственной организации под неё не попадают. Главный пакет
19
+ // остаётся неймспейсным (`npx tatnet`) — его имя коротко и проходит.
20
+ const PACKAGES = {
21
+ "darwin-arm64": "@tatnet/cli-darwin-arm64",
22
+ "darwin-x64": "@tatnet/cli-darwin-x64",
23
+ "linux-arm64": "@tatnet/cli-linux-arm64",
24
+ "linux-x64": "@tatnet/cli-linux-x64",
25
+ "win32-arm64": "@tatnet/cli-win32-arm64",
26
+ "win32-x64": "@tatnet/cli-win32-x64",
27
+ };
28
+
29
+ const RELEASES = "https://github.com/tatnet-ru/tatnet-cli/releases";
30
+
31
+ function fail(message) {
32
+ process.stderr.write("tatnet: " + message + "\n");
33
+ process.exit(1);
34
+ }
35
+
36
+ function resolveBinary() {
37
+ const key = process.platform + "-" + process.arch;
38
+ const pkg = PACKAGES[key];
39
+ if (!pkg) {
40
+ fail(
41
+ "нет сборки для " + key + ".\n" +
42
+ "Поддерживаются: " + Object.keys(PACKAGES).join(", ") + ".\n" +
43
+ "Соберите из исходников: go install github.com/tatnet-ru/tatnet-cli/cmd/tatnet@latest"
44
+ );
45
+ }
46
+
47
+ const exe = process.platform === "win32" ? "tatnet.exe" : "tatnet";
48
+ let manifest;
49
+ try {
50
+ // Через package.json, а не напрямую по файлу: так путь находится
51
+ // одинаково и в обычном node_modules, и в pnpm со ссылками.
52
+ manifest = require.resolve(pkg + "/package.json");
53
+ } catch {
54
+ fail(
55
+ "пакет " + pkg + " не установлен.\n" +
56
+ "Так бывает при установке с --no-optional или --ignore-optional.\n" +
57
+ "Поставьте его явно: npm i " + pkg + "\n" +
58
+ "Либо возьмите бинарник: " + RELEASES
59
+ );
60
+ }
61
+
62
+ const binary = path.join(path.dirname(manifest), "bin", exe);
63
+ if (!fs.existsSync(binary)) {
64
+ fail("пакет " + pkg + " установлен, но бинарника в нём нет: " + binary);
65
+ }
66
+ return binary;
67
+ }
68
+
69
+ function ensureExecutable(binary) {
70
+ if (process.platform === "win32") return;
71
+ try {
72
+ fs.accessSync(binary, fs.constants.X_OK);
73
+ } catch {
74
+ // Некоторые установщики теряют бит запуска при распаковке.
75
+ try {
76
+ fs.chmodSync(binary, 0o755);
77
+ } catch (err) {
78
+ fail("бинарник не исполняемый и права поправить не удалось: " + err.message);
79
+ }
80
+ }
81
+ }
82
+
83
+ const binary = resolveBinary();
84
+ ensureExecutable(binary);
85
+
86
+ const result = spawnSync(binary, process.argv.slice(2), { stdio: "inherit" });
87
+
88
+ if (result.error) {
89
+ fail("не удалось запустить " + binary + ": " + result.error.message);
90
+ }
91
+ // Код возврата обязан дойти до вызывающего: на CLI строят скрипты, и
92
+ // потерянный ненулевой код превратил бы отказ в успех.
93
+ if (result.signal) {
94
+ process.exit(1);
95
+ }
96
+ process.exit(result.status === null ? 1 : result.status);
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "tatnet",
3
+ "version": "0.1.3",
4
+ "description": "Консольный клиент публичного API TatNet",
5
+ "keywords": [
6
+ "tatnet",
7
+ "cli",
8
+ "cloud",
9
+ "postgres",
10
+ "valkey",
11
+ "dns",
12
+ "s3"
13
+ ],
14
+ "homepage": "https://github.com/tatnet-ru/tatnet-cli#readme",
15
+ "bugs": "https://github.com/tatnet-ru/tatnet-cli/issues",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/tatnet-ru/tatnet-cli.git"
19
+ },
20
+ "bin": {
21
+ "tatnet": "bin/tatnet.js"
22
+ },
23
+ "files": [
24
+ "bin/tatnet.js",
25
+ "README.md"
26
+ ],
27
+ "engines": {
28
+ "node": ">=18"
29
+ },
30
+ "optionalDependencies": {
31
+ "@tatnet/cli-darwin-arm64": "0.1.3",
32
+ "@tatnet/cli-darwin-x64": "0.1.3",
33
+ "@tatnet/cli-linux-arm64": "0.1.3",
34
+ "@tatnet/cli-linux-x64": "0.1.3",
35
+ "@tatnet/cli-win32-arm64": "0.1.3",
36
+ "@tatnet/cli-win32-x64": "0.1.3"
37
+ }
38
+ }