@nitra/cursor 1.8.63 → 1.8.64
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/mdc/k8s.mdc +52 -32
- package/package.json +1 -1
- package/scripts/check-k8s.mjs +10 -10
package/mdc/k8s.mdc
CHANGED
|
@@ -42,7 +42,7 @@ alwaysApply: false
|
|
|
42
42
|
}
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
Якщо правило **`k8s`** підключено в **`.n-cursor.json`** (масив **`rules`**), у **кореневому** `package.json`
|
|
45
|
+
Якщо правило **`k8s`** підключено в **`.n-cursor.json`** (масив **`rules`**), у **кореневому** `package.json` **мають** бути скрипт **`lint-k8s`** і виклик **`bun run lint-k8s`** у агрегованому **`lint`** (див. **`bun.mdc`**). Це перевіряє **`npx @nitra/cursor check bun`**.
|
|
46
46
|
|
|
47
47
|
Шлях до скрипта підстав свій (`./scripts/…` після копіювання, `node_modules/@nitra/cursor/scripts/…` якщо пакет у залежностях).
|
|
48
48
|
|
|
@@ -96,34 +96,25 @@ jobs:
|
|
|
96
96
|
|
|
97
97
|
## Deployment: `resources`
|
|
98
98
|
|
|
99
|
-
|
|
99
|
+
У **`Deployment`** у кожному **`containers`** / **`initContainers`** має бути **`resources`**; якщо лімітів ще немає — мінімум порожній запис:
|
|
100
100
|
|
|
101
101
|
```yaml
|
|
102
102
|
resources: {}
|
|
103
103
|
```
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
**`check k8s`** перевіряє наявність **`resources`** у кожному документі **Deployment** під **`k8s`**. Поле **`imagePullPolicy`** скрипт **не** перевіряє (залишається політиці Kubernetes за тегом образу).
|
|
106
106
|
|
|
107
|
-
**`
|
|
108
|
-
|
|
109
|
-
Якщо в **`Deployment`** у **`spec.template.spec.containers`** або **`initContainers`** задано образ **`hasura/graphql-engine`**, у полі **`image`** має бути саме **`hasura/graphql-engine:v2.48.15.ubi.amd64`** (для еквівалента Docker Hub допускається префікс **`docker.io/`**). Інші теги або сторонні реєстри з тим самим репозиторієм **`hasura/graphql-engine`** — порушення **`check k8s`**.
|
|
107
|
+
Образ **`hasura/graphql-engine`**: дозволений лише канонічний тег із константи **`HASURA_GRAPHQL_ENGINE_IMAGE`** у **`check-k8s.mjs`** (допускається префікс **`docker.io/`**); решта — помилка **check k8s**.
|
|
110
108
|
|
|
111
109
|
## Service: заборонені анотації GKE
|
|
112
110
|
|
|
113
|
-
У **`kind: Service`** не
|
|
114
|
-
|
|
115
|
-
- **`cloud.google.com/neg`**
|
|
116
|
-
- **`cloud.google.com/backend-config`**
|
|
117
|
-
|
|
118
|
-
Вони потрібні для інтеграції з **Ingress** / класичним балансуванням GKE; після переходу на **Gateway API** їх слід **прибрати** з маніфестів. **`check k8s`** завершиться помилкою, якщо хоча б один із цих ключів присутній.
|
|
111
|
+
У **`kind: Service`** не додавай у **`metadata.annotations`** **`cloud.google.com/neg`** і **`cloud.google.com/backend-config`** (legacy під Ingress / старе балансування GKE). **check k8s** падає, якщо ключ є.
|
|
119
112
|
|
|
120
113
|
## Service: `svc.yaml` і `svc-hl.yaml` (Gateway API)
|
|
121
114
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
- У маршрутах **Gateway API** з групи **`gateway.networking.k8s.io`** (**`HTTPRoute`**, **`GRPCRoute`**, **`TCPRoute`**, **`TLSRoute`**, **`UDPRoute`**) посилання **`backendRefs`** / **`backendRef`** на **Service** мають вказувати лише сервіси з цього headless-файлу (ім’я з суфіксом **`-hl`**).
|
|
126
|
-
- Якщо **`svc.yaml`** підключено через **`kustomization.yaml`** (**`resources`**, **`bases`**, **`components`**, **`crds`**, **`patches[].path`**, **`patchesStrategicMerge`**), у **тому ж** **`kustomization.yaml`** додай посилання на відповідний **`svc-hl.yaml`** (той самий відносний префікс каталогу, що й для **`svc.yaml`**).
|
|
115
|
+
Пара файлів для кластерного й headless **Service**: **`svc.yaml`** + **`svc-hl.yaml`** в одному каталозі, **`spec.type: ClusterIP`** / **`clusterIP: None`**, імена **`-hl`**, узгодженість пар, маршрути **`gateway.networking.k8s.io`** (**HTTPRoute**, **GRPCRoute**, **TCPRoute**, **TLSRoute**, **UDPRoute**) — **backendRef** лише на сервіси з суфіксом **`-hl`**; якщо **kustomization** посилається на **`svc.yaml`**, у **тому ж** **`kustomization.yaml`** має бути посилання на sibling **`svc-hl.yaml`**. Скрипт **не** створює файли — додай **`svc-hl.yaml`** вручну (копія з правками **name** / **clusterIP**).
|
|
116
|
+
|
|
117
|
+
**Точні умови та повідомлення `fail`** — верхній JSDoc **`npm/scripts/check-k8s.mjs`**.
|
|
127
118
|
|
|
128
119
|
## Kustomize: структура каталогів (`base` / overlays)
|
|
129
120
|
|
|
@@ -142,11 +133,11 @@ resources: {}
|
|
|
142
133
|
|
|
143
134
|
### Namespace
|
|
144
135
|
|
|
145
|
-
- **`base/kustomization.yaml`:**
|
|
136
|
+
- **`base/kustomization.yaml`:** поле **`namespace:`** має бути **непорожнім** (перевіряє **check k8s**, якщо файл є).
|
|
146
137
|
|
|
147
|
-
- **Де не дублювати `metadata.namespace`:** у YAML
|
|
138
|
+
- **Де не дублювати `metadata.namespace`:** у YAML, досяжних через **граф Kustomize** (шляхи з **`kustomization.yaml`**, як у логіці **`collectKustomizeManagedRelPaths`** / **check k8s**). **Namespace** задає **`namespace:`** у kustomization.
|
|
148
139
|
|
|
149
|
-
- **Коли `metadata.namespace`
|
|
140
|
+
- **Коли `metadata.namespace` обов’язковий у файлі:** YAML під **`k8s`**, який **не** в графі жодного kustomization — непорожній **`metadata.namespace`** для namespaced **kind** (винятки — кластерні **kind**, перелік **`CLUSTER_SCOPED_KINDS`** у **`check-k8s.mjs`**). Якщо namespace у маніфесті не потрібен — підключи файл через **`resources`** / **`patches`** тощо.
|
|
150
141
|
|
|
151
142
|
- **Не додавай** окремі **patches** Kustomize, які лише змінюють **namespace**: **namespace** визначає Kustomize; у overlays додаткові зміни — без дублювання логіки **namespace**.
|
|
152
143
|
|
|
@@ -182,27 +173,56 @@ resources: {}
|
|
|
182
173
|
|
|
183
174
|
**`check k8s`:** заборонено **`kind: Ingress`**.
|
|
184
175
|
|
|
185
|
-
|
|
176
|
+
3. Якщо **HTTPRoute** посилається на **Service** в іншому **namespace**, потрібен **ReferenceGrant** (дозвіл). Наприклад **HTTPRoute** в **`contract`** і **Service** в **`dev`** — додай маніфест на кшталт **`base/rg.yaml`** (фрагмент нижче).
|
|
177
|
+
|
|
178
|
+
```yaml title="base/rg.yaml"
|
|
179
|
+
# yaml-language-server: $schema=https://datreeio.github.io/CRDs-catalog/gateway.networking.k8s.io/referencegrant_v1beta1.json
|
|
180
|
+
apiVersion: gateway.networking.k8s.io/v1beta1
|
|
181
|
+
kind: ReferenceGrant
|
|
182
|
+
metadata:
|
|
183
|
+
name: contract-to-dev
|
|
184
|
+
namespace: dev
|
|
185
|
+
spec:
|
|
186
|
+
from:
|
|
187
|
+
- group: gateway.networking.k8s.io
|
|
188
|
+
kind: HTTPRoute
|
|
189
|
+
namespace: contract
|
|
190
|
+
to:
|
|
191
|
+
- group: ''
|
|
192
|
+
kind: Service
|
|
193
|
+
# Якщо name не вказано, доступ дозволено до всіх Service в цьому namespace
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**ReferenceGrant** має бути в **namespace** тих **Service**, до яких відкривається доступ (у прикладі — **`dev`**). Якщо **`namespace:`** у **overlay** не збігається з **namespace** гранта, **не** додавай **`base/rg.yaml`** у **`resources:`** того overlay — Kustomize може перезаписати **`metadata.namespace`** гранта. Натомість застосуй **`patches`** (JSON patch), щоб явно виставити потрібний **namespace**:
|
|
197
|
+
|
|
198
|
+
```yaml title="overlay/kustomization.yaml (фрагмент)"
|
|
199
|
+
patches:
|
|
200
|
+
- target:
|
|
201
|
+
kind: ReferenceGrant
|
|
202
|
+
name: contract-to-dev
|
|
203
|
+
patch: |-
|
|
204
|
+
- op: replace
|
|
205
|
+
path: /metadata/namespace
|
|
206
|
+
value: dev
|
|
207
|
+
```
|
|
186
208
|
|
|
187
|
-
|
|
209
|
+
## Перевірка
|
|
188
210
|
|
|
189
|
-
|
|
211
|
+
**`npx @nitra/cursor check k8s`** — програмні критерії в **JSDoc на початку** **`npm/scripts/check-k8s.mjs`**. Якщо під **`k8s`** немає **`*.yaml`** — крок пропущено. Канон **`$schema`** для редактора — розділ **«Визначення схеми YAML`** нижче.
|
|
190
212
|
|
|
191
|
-
|
|
213
|
+
**Не входить у check k8s:** наприклад **ReferenceGrant** і доступ між **namespace** (лише рекомендації тут), **kubeconform** / **kubescape** — це **`bun run lint-k8s`**.
|
|
192
214
|
|
|
193
|
-
|
|
215
|
+
## Що саме в скрипті `check-k8s.mjs`
|
|
194
216
|
|
|
195
|
-
|
|
217
|
+
Повний перелік умов, константи (**`YANNH_PIN`**, **`CLUSTER_SCOPED_KINDS`**, **`HASURA_GRAPHQL_ENGINE_IMAGE`** тощо) і допоміжні функції — у файлі скрипта; змінив вимогу для **check** — онови **JSDoc** і за потреби тести в **`npm/tests/check-k8s-schema.test.mjs`**.
|
|
196
218
|
|
|
197
|
-
При зміні **PIN** версії Kubernetes
|
|
219
|
+
При зміні **PIN** версії Kubernetes узгодь **`check-k8s.mjs`**, **`run-k8s.mjs`** (**`KUBERNETES_VERSION`**, **`DATREE_CRD_SCHEMA_LOCATION`**) і цей файл (**lint-k8s**, **Визначення схеми YAML**).
|
|
198
220
|
|
|
199
221
|
## Коли застосовувати (агентам)
|
|
200
222
|
|
|
201
|
-
-
|
|
202
|
-
-
|
|
203
|
-
-
|
|
204
|
-
- Дотримуйся структури **Kustomize** (`base` = dev, overlays без дублювання `base`, коментарі для рядків, що змінюються в overlay). У **`base/kustomization.yaml`** завжди задавай непорожній **`namespace:`**. У **`k8s/base`** у кожному ресурсному YAML має бути явний **`metadata.namespace`**. Поза **base**, якщо не хочеш **`metadata.namespace`** у файлі — підключи його до kustomization (**`resources`** / **`patches`** тощо); інакше додай явний **`metadata.namespace`**.
|
|
205
|
-
- Після міграції на нову структуру **видали** застарілі файли та каталоги, які вже замінені (див. **Міграція зі старої структури**).
|
|
223
|
+
- Після змін у k8s YAML: **`npx @nitra/cursor check k8s`** і за наявності правила — **`bun run lint-k8s`**.
|
|
224
|
+
- Оновив **`apiVersion` / `kind`** — підправ **перший** рядок **`$schema`** (див. **Визначення схеми YAML**).
|
|
225
|
+
- Дотримуйся **Kustomize** з цього правила; деталі **namespace** / графа ресурсів — **check k8s** + підказки в JSDoc скрипта.
|
|
206
226
|
|
|
207
227
|
## Визначення схеми YAML (канон)
|
|
208
228
|
|
package/package.json
CHANGED
package/scripts/check-k8s.mjs
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* (datree за замовчуванням: GitHub Pages `https://datreeio.github.io/CRDs-catalog/…`).
|
|
7
7
|
*
|
|
8
8
|
* Додатково: у кожному YAML-документі з **`kind: Deployment`** у кожного контейнера
|
|
9
|
-
* **`spec.template.spec.containers[]`** має бути ключ **`resources`** (значення —
|
|
9
|
+
* **`spec.template.spec.containers[]`** має бути ключ **`resources`** (значення — об’єкт, допускається
|
|
10
10
|
* порожній **`{}`**). Поле **`imagePullPolicy`** не перевіряється — діють типові правила Kubernetes
|
|
11
|
-
* (`:latest` або
|
|
11
|
+
* (`:latest` або коли тег не вказано → **Always**, інші теги → **IfNotPresent**). Якщо серед **`containers`** /
|
|
12
12
|
* **`initContainers`** є образ **`hasura/graphql-engine`**, дозволено лише пін **`HASURA_GRAPHQL_ENGINE_IMAGE`**
|
|
13
13
|
* (див. k8s.mdc).
|
|
14
14
|
*
|
|
@@ -327,7 +327,7 @@ export function kustomizationSvcYamlMissingSvcHlViolation(kustomizationDir, path
|
|
|
327
327
|
if (basename(abs).toLowerCase() === 'svc.yaml') {
|
|
328
328
|
const hlAbs = resolve(dirname(abs), 'svc-hl.yaml')
|
|
329
329
|
if (!resolved.has(hlAbs)) {
|
|
330
|
-
return `kustomization посилається на «${ref}» — додай у тому ж kustomization.yaml посилання на відповідний svc-hl.yaml (очікуваний шлях поруч,
|
|
330
|
+
return `kustomization посилається на «${ref}» — додай у тому ж kustomization.yaml посилання на відповідний svc-hl.yaml (очікуваний шлях поруч, наприклад той самий префікс каталогу + svc-hl.yaml; див. k8s.mdc)`
|
|
331
331
|
}
|
|
332
332
|
}
|
|
333
333
|
}
|
|
@@ -627,9 +627,9 @@ async function readK8sYamlBodyAfterModelineForSvcPair(abs) {
|
|
|
627
627
|
}
|
|
628
628
|
|
|
629
629
|
/**
|
|
630
|
-
* Розбирає YAML на корені
|
|
630
|
+
* Розбирає YAML на корені документів (ігнорує зламані документи).
|
|
631
631
|
* @param {string} body фрагмент YAML
|
|
632
|
-
* @returns {unknown[]} масив
|
|
632
|
+
* @returns {unknown[]} масив успішно розібраних коренів YAML-документів
|
|
633
633
|
*/
|
|
634
634
|
function parseK8sYamlDocumentObjectRoots(body) {
|
|
635
635
|
try {
|
|
@@ -722,7 +722,7 @@ function scanIngressInYamlDocuments(rel, body, fail) {
|
|
|
722
722
|
|
|
723
723
|
/**
|
|
724
724
|
* Чи порушує маніфест вимогу **`Deployment.spec.template.spec.containers[].resources`** (див. k8s.mdc).
|
|
725
|
-
* @param {unknown} manifest корінь YAML-документа як
|
|
725
|
+
* @param {unknown} manifest корінь YAML-документа як запис JavaScript
|
|
726
726
|
* @returns {string | null} текст порушення для `fail` або null, якщо перевірка не застосовується / ок
|
|
727
727
|
*/
|
|
728
728
|
export function deploymentResourcesViolation(manifest) {
|
|
@@ -752,7 +752,7 @@ export function deploymentResourcesViolation(manifest) {
|
|
|
752
752
|
}
|
|
753
753
|
const r = cont.resources
|
|
754
754
|
if (r === null || typeof r !== 'object' || Array.isArray(r)) {
|
|
755
|
-
return `контейнер "${label}": resources має бути
|
|
755
|
+
return `контейнер "${label}": resources має бути записом у YAML (наприклад порожній: resources: {})`
|
|
756
756
|
}
|
|
757
757
|
}
|
|
758
758
|
}
|
|
@@ -761,7 +761,7 @@ export function deploymentResourcesViolation(manifest) {
|
|
|
761
761
|
}
|
|
762
762
|
|
|
763
763
|
/**
|
|
764
|
-
* Прибирає digest з посилання на образ (`@sha256:…`) для порівняння
|
|
764
|
+
* Прибирає digest з посилання на образ (`@sha256:…`) для порівняння тегу образу.
|
|
765
765
|
* @param {string} image значення поля `image`
|
|
766
766
|
* @returns {string} той самий рядок без суфікса `@…` (digest), з `.trim()`
|
|
767
767
|
*/
|
|
@@ -771,7 +771,7 @@ function stripImageDigest(image) {
|
|
|
771
771
|
}
|
|
772
772
|
|
|
773
773
|
/**
|
|
774
|
-
* Чи рядок `image` вказує на репозиторій **hasura/graphql-engine** (будь-який тег / без
|
|
774
|
+
* Чи рядок `image` вказує на репозиторій **hasura/graphql-engine** (будь-який тег / без вказаного тегу).
|
|
775
775
|
* @param {string} image значення поля `image`
|
|
776
776
|
* @returns {boolean} true, якщо шлях образу закінчується на `hasura/graphql-engine` з тегом або без
|
|
777
777
|
*/
|
|
@@ -808,7 +808,7 @@ function hasuraGraphqlEngineViolationInContainerList(list, containers) {
|
|
|
808
808
|
}
|
|
809
809
|
|
|
810
810
|
/**
|
|
811
|
-
* Чи порушує **Deployment** вимогу
|
|
811
|
+
* Чи порушує **Deployment** вимогу щодо зафіксованого образу **hasura/graphql-engine** (k8s.mdc).
|
|
812
812
|
* @param {unknown} manifest корінь YAML-документа
|
|
813
813
|
* @returns {string | null} текст порушення або null, якщо не Deployment / образу немає / ок
|
|
814
814
|
*/
|