@nitra/cursor 3.22.0 → 3.23.1
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/.pi-template/extensions/n-cursor-adr/docs/index.md +181 -0
- package/AGENTS.template.md +4 -0
- package/CHANGELOG.md +37 -3
- package/bin/docs/n-cursor.md +636 -0
- package/bin/docs/rename-yaml-extensions.md +207 -0
- package/bin/n-cursor.js +30 -3
- package/package.json +1 -1
- package/rules/abie/docs/fix.md +18 -0
- package/rules/abie/js/docs/applies.md +26 -0
- package/rules/abie/js/docs/env_dns.md +32 -0
- package/rules/abie/js/docs/firebase_hosting.md +23 -0
- package/rules/abie/js/docs/hc_pairing.md +35 -0
- package/rules/abie/js/docs/ua_http_route.md +28 -0
- package/rules/abie/js/docs/ua_node_selector.md +28 -0
- package/rules/abie/lib/docs/enabled.md +29 -0
- package/rules/abie/lib/docs/env-dns.md +35 -0
- package/rules/abie/lib/docs/hc-yaml.md +33 -0
- package/rules/abie/lib/docs/http-route.md +44 -0
- package/rules/abie/lib/docs/k8s-tree.md +40 -0
- package/rules/abie/lib/docs/kustomization-patches.md +47 -0
- package/rules/abie/lib/docs/overlay-paths.md +38 -0
- package/rules/abie/lib/docs/yaml.md +29 -0
- package/rules/adr/docs/fix.md +148 -0
- package/rules/adr/js/docs/hooks.md +259 -0
- package/rules/bun/docs/fix.md +156 -0
- package/rules/bun/js/docs/layout.md +393 -0
- package/rules/capacitor/docs/fix.md +121 -0
- package/rules/capacitor/js/docs/platforms.md +295 -0
- package/rules/changelog/changelog.mdc +4 -2
- package/rules/changelog/docs/fix.md +174 -0
- package/rules/changelog/js/consistency.mjs +114 -13
- package/rules/changelog/js/docs/consistency.md +387 -0
- package/rules/changelog/lib/docs/package-manifest.md +210 -0
- package/rules/ci4/docs/fix.md +179 -0
- package/rules/ci4/js/docs/marksman_config.md +128 -0
- package/rules/docker/docker.mdc +8 -3
- package/rules/docker/docs/fix.md +171 -0
- package/rules/docker/js/docs/lint.md +258 -0
- package/rules/docker/lib/docs/docker-hadolint.md +184 -0
- package/rules/docker/lib/docs/docker-mirror.md +247 -0
- package/rules/docker/lib/docs/docker-native-addon.md +170 -0
- package/rules/docker/lib/docs/docker-nginx-user.md +219 -0
- package/rules/docker/lint/docs/lint.md +193 -0
- package/rules/efes/docs/fix.md +203 -0
- package/rules/feedback/docs/fix.md +140 -0
- package/rules/flow/docs/fix.md +152 -0
- package/rules/ga/docs/fix.md +158 -0
- package/rules/ga/js/docs/lint.md +100 -0
- package/rules/ga/js/docs/workflows.md +217 -0
- package/rules/ga/lint/docs/lint.md +209 -0
- package/rules/ga/policy/clean_merged_branch/clean_merged_branch.rego +11 -2
- package/rules/ga/policy/clean_merged_branch/template/clean-merged-branch.yml.snippet.yml +3 -4
- package/rules/graphql/docs/fix.md +126 -0
- package/rules/graphql/js/docs/tooling.md +264 -0
- package/rules/graphql/lib/docs/graphql-gql-scan.md +219 -0
- package/rules/hasura/docs/fix.md +120 -0
- package/rules/hasura/hasura.mdc +14 -0
- package/rules/hasura/js/docs/internal_urls.md +326 -0
- package/rules/image-avif/docs/fix.md +132 -0
- package/rules/image-avif/js/docs/avif_generation.md +241 -0
- package/rules/image-compress/docs/fix.md +150 -0
- package/rules/image-compress/js/docs/package_setup.md +191 -0
- package/rules/js-bun-db/docs/fix.md +148 -0
- package/rules/js-bun-db/js/docs/safety.md +231 -0
- package/rules/js-bun-db/js-bun-db.mdc +42 -13
- package/rules/js-bun-db/lib/docs/bun-sql-scan.md +347 -0
- package/rules/js-bun-redis/docs/fix.md +123 -0
- package/rules/js-bun-redis/js/docs/imports.md +176 -0
- package/rules/js-bun-redis/lib/docs/redis-imports.md +223 -0
- package/rules/js-lint/docs/fix.md +117 -0
- package/rules/js-lint/js/docs/lint.md +250 -0
- package/rules/js-lint/js/docs/tooling.md +348 -0
- package/rules/js-lint/js/docs/utils_imports.md +207 -0
- package/rules/js-lint-ci/docs/fix.md +154 -0
- package/rules/js-lint-ci/js/docs/lint.md +144 -0
- package/rules/js-mssql/docs/fix.md +128 -0
- package/rules/js-mssql/js/docs/deps.md +263 -0
- package/rules/js-mssql/lib/docs/mssql-pool-scan.md +367 -0
- package/rules/js-run/docs/fix.md +144 -0
- package/rules/js-run/js/docs/runtime.md +388 -0
- package/rules/js-run/lib/docs/bunyan-imports.md +117 -0
- package/rules/js-run/lib/docs/check-env-scan.md +433 -0
- package/rules/js-run/lib/docs/conn-file-rules.md +300 -0
- package/rules/js-run/lib/docs/conn-imports-scan.md +204 -0
- package/rules/js-run/lib/docs/promise-settimeout-scan.md +326 -0
- package/rules/k8s/docs/fix.md +129 -0
- package/rules/k8s/js/docs/manifests.md +344 -0
- package/rules/k8s/js/manifests.mjs +6 -2
- package/rules/k8s/k8s.mdc +4 -2
- package/rules/k8s/lint/docs/lint.md +411 -0
- package/rules/k8s/policy/network_policy/template/deployment.snippet.yaml +2 -0
- package/rules/k8s/policy/network_policy/template/stateful-set.snippet.yaml +2 -0
- package/rules/nginx-default-tpl/docs/fix.md +124 -0
- package/rules/nginx-default-tpl/js/docs/template.md +378 -0
- package/rules/npm-module/docs/fix.md +98 -0
- package/rules/npm-module/js/docs/package_structure.md +274 -0
- package/rules/npm-module/js/docs/rule_meta.md +137 -0
- package/rules/npm-module/js/docs/skill_meta.md +190 -0
- package/rules/php/docs/fix.md +107 -0
- package/rules/php/js/docs/tooling.md +152 -0
- package/rules/php/lint/docs/lint.md +215 -0
- package/rules/python/docs/fix.md +163 -0
- package/rules/python/js/docs/applies.md +108 -0
- package/rules/python/js/docs/tooling.md +153 -0
- package/rules/python/lint/docs/lint.md +322 -0
- package/rules/rego/docs/fix.md +121 -0
- package/rules/rego/js/docs/applies.md +174 -0
- package/rules/rego/js/docs/lint.md +118 -0
- package/rules/rego/lint/docs/lint.md +204 -0
- package/rules/release/docs/change.md +185 -0
- package/rules/release/docs/fix.md +119 -0
- package/rules/release/docs/release.md +222 -0
- package/rules/release/lib/docs/aggregate.md +246 -0
- package/rules/release/lib/docs/change-file.md +200 -0
- package/rules/release/lib/docs/fallback.md +203 -0
- package/rules/rust/docs/fix.md +129 -0
- package/rules/rust/js/docs/applies.md +140 -0
- package/rules/rust/lib/docs/has-cargo-toml.md +130 -0
- package/rules/security/docs/fix.md +86 -0
- package/rules/security/js/docs/lint.md +171 -0
- package/rules/security/js/docs/sample_secret.md +190 -0
- package/rules/security/js/docs/trufflehog.md +137 -0
- package/rules/security/js/lint.mjs +9 -1
- package/rules/style-lint/docs/fix.md +155 -0
- package/rules/style-lint/js/docs/lint.md +184 -0
- package/rules/style-lint/js/docs/tooling.md +194 -0
- package/rules/tauri/docs/fix.md +158 -0
- package/rules/tauri/js/docs/cargo_mutants_config.md +168 -0
- package/rules/tauri/js/docs/tooling.md +228 -0
- package/rules/test/coverage/coverage.mjs +15 -3
- package/rules/test/docs/fix.md +132 -0
- package/rules/test/js/data/stryker_config/docs/stryker-vue-macros-ignorer.md +138 -0
- package/rules/test/js/data/stryker_config/docs/stryker.config.baseline.md +134 -0
- package/rules/test/js/data/stryker_config/docs/stryker.config.vue.baseline.md +160 -0
- package/rules/test/js/data/vitest_config/docs/vitest.config.baseline.md +195 -0
- package/rules/test/js/docs/cargo_mutants_config.md +173 -0
- package/rules/test/js/docs/location.md +136 -0
- package/rules/test/js/docs/no-process-chdir.md +160 -0
- package/rules/test/js/docs/no-relative-fs-path.md +271 -0
- package/rules/test/js/docs/stryker_config.md +152 -0
- package/rules/test/js/docs/vitest-config-pool-forks.md +174 -0
- package/rules/text/docs/fix.md +118 -0
- package/rules/text/js/docs/forbidden-prettier.md +143 -0
- package/rules/text/js/docs/formatting.md +256 -0
- package/rules/text/js/docs/lint.md +122 -0
- package/rules/text/lint/docs/lint.md +220 -0
- package/rules/text/lint/docs/run-dotenv-linter.md +157 -0
- package/rules/text/lint/docs/run-shellcheck.md +212 -0
- package/rules/text/lint/docs/run-v8r.md +197 -0
- package/rules/vue/docs/fix.md +127 -0
- package/rules/vue/js/docs/packages.md +335 -0
- package/rules/vue/lib/docs/vue-forbidden-imports.md +261 -0
- package/rules/worktree/docs/fix.md +161 -0
- package/schemas/rule-meta.json +5 -1
- package/scripts/auto-rules.mjs +7 -4
- package/scripts/coverage-classify/docs/apply.md +202 -0
- package/scripts/coverage-classify/docs/cache.md +203 -0
- package/scripts/coverage-classify/docs/index.md +218 -0
- package/scripts/coverage-classify/docs/prompt.md +132 -0
- package/scripts/coverage-classify/docs/verdict-schema.md +169 -0
- package/scripts/coverage-fix-extract.mjs +122 -0
- package/scripts/coverage-fix.mjs +1 -1
- package/scripts/dispatcher/docs/graph.md +346 -0
- package/scripts/dispatcher/docs/index.md +236 -0
- package/scripts/dispatcher/docs/trace.md +296 -0
- package/scripts/dispatcher/index.mjs +1 -1
- package/scripts/dispatcher/lib/active.mjs +4 -8
- package/scripts/dispatcher/lib/commands.mjs +7 -11
- package/scripts/dispatcher/lib/docs/active.md +348 -0
- package/scripts/dispatcher/lib/docs/artifact.md +232 -0
- package/scripts/dispatcher/lib/docs/budget.md +167 -0
- package/scripts/dispatcher/lib/docs/capability.md +196 -0
- package/scripts/dispatcher/lib/docs/commands.md +210 -0
- package/scripts/dispatcher/lib/docs/events.md +182 -0
- package/scripts/dispatcher/lib/docs/executor.md +190 -0
- package/scripts/dispatcher/lib/docs/flow-lock.md +161 -0
- package/scripts/dispatcher/lib/docs/flow-resolve.md +267 -0
- package/scripts/dispatcher/lib/docs/gate.md +231 -0
- package/scripts/dispatcher/lib/docs/level.md +335 -0
- package/scripts/dispatcher/lib/docs/plan-panel.md +181 -0
- package/scripts/dispatcher/lib/docs/plan.md +200 -0
- package/scripts/dispatcher/lib/docs/planner.md +269 -0
- package/scripts/dispatcher/lib/docs/review.md +255 -0
- package/scripts/dispatcher/lib/docs/reviewer.md +240 -0
- package/scripts/dispatcher/lib/docs/snapshot.md +247 -0
- package/scripts/dispatcher/lib/docs/spec.md +203 -0
- package/scripts/dispatcher/lib/docs/state-store.md +303 -0
- package/scripts/dispatcher/lib/docs/subagent-runner.md +173 -0
- package/scripts/dispatcher/lib/executor.mjs +6 -1
- package/scripts/dispatcher/lib/flow-resolve.mjs +3 -1
- package/scripts/dispatcher/lib/level.mjs +29 -3
- package/scripts/dispatcher/lib/review.mjs +1 -1
- package/scripts/dispatcher/lib/subagent-runner.mjs +5 -3
- package/scripts/docs/auto-rules.md +376 -0
- package/scripts/docs/auto-skills.md +173 -0
- package/scripts/docs/build-agents-commands.md +183 -0
- package/scripts/docs/cli-entry.md +153 -0
- package/scripts/docs/coverage-fix.md +177 -0
- package/scripts/docs/ensure-nitra-cursor-dev-dependencies.md +189 -0
- package/scripts/lib/changed-files.mjs +4 -1
- package/scripts/lib/docs/changed-files.md +149 -0
- package/scripts/lib/docs/check-mdc-template-refs.md +222 -0
- package/scripts/lib/docs/check-reporter.md +175 -0
- package/scripts/lib/docs/discover-check-rules-from-cursor.md +157 -0
- package/scripts/lib/docs/discover-checkable-rules.md +165 -0
- package/scripts/lib/docs/ensure-tool.md +254 -0
- package/scripts/lib/docs/generated-markdown.md +275 -0
- package/scripts/lib/docs/gha-workflow.md +326 -0
- package/scripts/lib/docs/inline-template-links.md +303 -0
- package/scripts/lib/docs/list-rule-ids.md +156 -0
- package/scripts/lib/docs/load-cursor-config.md +147 -0
- package/scripts/lib/docs/mirror-parity.md +167 -0
- package/scripts/lib/worktree.mjs +26 -0
- package/scripts/worktree-cli.mjs +12 -2
- package/skills/coverage-fix/SKILL.md +34 -45
- package/skills/docgen/SKILL.md +44 -23
- package/skills/docgen/bench/etalon/firebase_hosting.md +19 -0
- package/skills/docgen/bench/etalon/k8s-tree.md +24 -0
- package/skills/docgen/bench/etalon/overlay-paths.md +24 -0
- package/skills/docgen/js/docgen-ignore.mjs +54 -0
- package/skills/docgen/js/docgen-scan.mjs +37 -21
- package/skills/llm-patch/SKILL.md +23 -2
- package/skills/start-check/SKILL.md +26 -53
- package/skills/start-check/js/check.mjs +211 -0
- package/skills/taze/SKILL.md +9 -3
- package/skills/taze/js/diff.mjs +154 -0
- package/types/bin/n-cursor.d.ts +1 -1
- package/skills/fix-tests/SKILL.md +0 -119
- package/skills/fix-tests/meta.json +0 -1
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
# manifests.mjs — перевірки та автофікси Kubernetes-маніфестів
|
|
2
|
+
|
|
3
|
+
## Огляд
|
|
4
|
+
|
|
5
|
+
Модуль `npm/rules/k8s/js/manifests.mjs` — реалізація команди `check k8s` (правило `k8s.mdc`). Він обходить усі `*.yaml` / `*.yml` під сегментом каталогу `k8s` у репозиторії та виконує комплексну перевірку та автокорекцію Kubernetes-маніфестів:
|
|
6
|
+
|
|
7
|
+
- modeline `# yaml-language-server: $schema=…` (URL за `https://`, без дублікатів, рівно один на файл, у першому рядку);
|
|
8
|
+
- URL схеми обирається за `apiVersion`/`kind` маніфесту — kustomization (schemastore), yannh, datree (CRDs-catalog) або «явна таблиця» `EXPLICIT_K8S_SCHEMAS`; виняток — `apiVersion: alb.yc.io/v1alpha1`, `kind: HttpBackendGroup`, де modeline бути не повинно;
|
|
9
|
+
- ресурси контейнерів для `kind: Deployment` (`spec.template.spec.containers[].resources.requests.cpu` і `…memory`); жорсткий канон у `…/k8s/…/base/…` — `cpu: '0.02'` / `memory: '128Mi'`, поза base — рекомендовані дефолти `0.5` / `512Mi`;
|
|
10
|
+
- структура Kustomize: заборона каталогу `…/k8s/dev/…`; обовʼязковий `namespace:` у `k8s/base/kustomization.yaml`; сортування `resources:` (через rego) та `patches[]`; перевірка JSON6902 inline-патчів (сорт за `path`, заборона `remove`+`add` на один шлях);
|
|
11
|
+
- існування локальних посилань у `kustomization.yaml` (`resources` / `bases` / `components` / `crds` / `patches[].path` / `patchesStrategicMerge` / `patchesJson6902[].path` / `configurations` / `replacements[].path`);
|
|
12
|
+
- розвʼязання `patches[].target` і `patchesJson6902[].target` у каталозі ресурсів (рекурсивно через вкладені kustomization-и); видалення зайвих `group` / `version` у `target`, коли немає колізії GVK + name;
|
|
13
|
+
- пари `svc.yaml` ⇄ `svc-hl.yaml` у каталозі та підключення обох у `kustomization.yaml`; перевірка `Service.spec.type: ClusterIP` у `svc.yaml`, `spec.clusterIP: None` і суфіксу `-hl` у `svc-hl.yaml`; перевірка `HealthCheckPolicy.spec.targetRef.name` (GKE) на headless-сервіс; перевірка Gateway-API `backendRefs` (тільки `-hl`, без надлишкового `namespace`);
|
|
14
|
+
- автоматична заміна `apiVersion: batch/v1beta1` → `batch/v1` на диску;
|
|
15
|
+
- автоматичне видалення YAML-файлів, що складаються лише з `kind: BackendConfig`; `fail` при змішуванні з іншими `kind`;
|
|
16
|
+
- автоматична конвертація патчів `op: replace` на `/spec/template/spec/containers/<N>/image` у блок `images:` Kustomize та чистка існуючого `images:` (зрізає `:tag` у `name`, прибирає зайвий `newTag`);
|
|
17
|
+
- HPA / PDB / `topologySpreadConstraints` для `Deployment` у `…/k8s/…/base/`: HPA і PDB живуть у sibling-каталозі `…/k8s/…/components/` (Kustomize Component) — у base/ їх заборонено; ENV-залежні межі (dev-like vs прод);
|
|
18
|
+
- `NetworkPolicy` для кожного workload-маніфесту (`Deployment`, `StatefulSet`, `DaemonSet`, `Job`, `CronJob`): канонічний YAML генерується зі snippet-шаблонів (`deployment`, `statefulSet`), додає HTTPRoute-aware GCLB ingress-правило з `35.191.0.0/16` + `130.211.0.0/22` + `10.0.0.0/8`; відсутні документи створюються автоматично; заборонено `egress: [{}]`;
|
|
19
|
+
- спеціальні правила Hasura: канонічний `HTTPRoute` (4 правила з `URLRewrite`/`RequestHeaderModifier`); обовʼязковий ключ `HASURA_GRAPHQL_ENABLE_REMOTE_SCHEMA_PERMISSIONS=true` у `ConfigMap` поруч з Deployment з образом `hasura/graphql-engine`; контроль `HASURA_GRAPHQL_ENABLED_APIS` в overlays;
|
|
20
|
+
- прод-оверрайди в overlay `kustomization.yaml`: `/spec/minReplicas`, `/spec/maxReplicas` для HPA та `/spec/minAvailable` для PDB через JSON6902 або Strategic Merge.
|
|
21
|
+
|
|
22
|
+
Усе пер-документне ядро перевірок (Ingress заборонено, autoscaling/v1 заборонено, GCP-анотації Service, metadata.namespace, рутинне валідаційне ядро) делеговано в `rego`-полісі `npm/policy/k8s/*` і виконується одним батчем через `runConftestBatch` всередині `runAllK8sRego`. JS лишає кросфайлову оркестрацію, modeline та FS-existence перевірки.
|
|
23
|
+
|
|
24
|
+
## Експорти / API
|
|
25
|
+
|
|
26
|
+
### Константи
|
|
27
|
+
|
|
28
|
+
| Експорт | Тип | Призначення |
|
|
29
|
+
| --------------------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
30
|
+
| `SERVICE_FORBIDDEN_GCP_ANNOTATION_KEYS` | `readonly string[]` (frozen) | Заборонені ключі анотацій `cloud.google.com/neg` та `cloud.google.com/backend-config` у `Service`. |
|
|
31
|
+
| `DEFAULT_CONTAINER_CPU_REQUEST` | `string = '0.5'` | Рекомендований `resources.requests.cpu` поза base. |
|
|
32
|
+
| `DEFAULT_CONTAINER_MEMORY_REQUEST` | `string = '512Mi'` | Рекомендований `resources.requests.memory` поза base. |
|
|
33
|
+
| `K8S_BASE_CONTAINER_CPU_REQUEST` | `string = '0.02'` | Обовʼязковий `cpu` у шарі `…/k8s/…/base/…`. |
|
|
34
|
+
| `K8S_BASE_CONTAINER_MEMORY_REQUEST` | `string = '128Mi'` | Обовʼязковий `memory` у шарі `…/k8s/…/base/…`. |
|
|
35
|
+
| `HASURA_REQUIRED_ENV_KEYS` | `string[]` | Перелік env-ключів, які мають бути у `data` ConfigMap для Hasura-Deployment (для людиночитного pass-повідомлення; авторитет — rego). |
|
|
36
|
+
| `HPA_FILENAME` | `string = 'hpa.yaml'` | Канонічна назва HPA-файла. |
|
|
37
|
+
| `PDB_FILENAME` | `string = 'pdb.yaml'` | Канонічна назва PDB-файла. |
|
|
38
|
+
| `NETWORK_POLICY_FILENAME` | `string = 'networkpolicy.yaml'` | Канонічна назва NetworkPolicy-файла. |
|
|
39
|
+
| `WORKLOAD_KINDS_WITH_NETWORK_POLICY` | `readonly string[]` (frozen) | `kind`-и, для яких потрібен `NetworkPolicy` поруч. |
|
|
40
|
+
| `COMPONENTS_DIR` | `string = 'components'` | Назва каталогу sibling до `base/` для Kustomize Components з HPA/PDB. |
|
|
41
|
+
| `KIND_TO_SNIPPET` | `Record<string, 'deployment' \| 'statefulSet'>` | Mapping `kind` → ім’я snippet-шаблону для `NetworkPolicy`. |
|
|
42
|
+
|
|
43
|
+
### Predicate / класифікатори шляху
|
|
44
|
+
|
|
45
|
+
- `isK8sYamlUnderBaseDirectory(relPosix: string): boolean` — чи відносний POSIX-шлях має сегмент `base/` всередині `k8s/…`.
|
|
46
|
+
- `pathHasK8sSegment(filePath: string, root?: string): boolean` — чи серед компонентів шляху (відносно `root`, якщо передано) є сегмент `k8s`.
|
|
47
|
+
- `isForbiddenK8sDevPath(rel: string): boolean` — `true` для шляхів виду `…/k8s/dev/…`.
|
|
48
|
+
- `isClusterScopedKubernetesKind(kind: string): boolean` — `true` для вбудованих cluster-scoped `kind`-ів (`Namespace`, `Node`, `ClusterRole`, …).
|
|
49
|
+
- `isBaseKustomizationPath(rel: string): boolean` — чи це `…/k8s/base/kustomization.yaml`.
|
|
50
|
+
- `isK8sBaseManifestYamlPath(rel: string, baseLower: string): boolean` — чи це ресурсний YAML у `k8s/base/` (не `kustomization.yaml`).
|
|
51
|
+
- `isHasuraDeploymentManifest(manifest: unknown): boolean` — чи `Deployment` використовує образ `hasura/graphql-engine` у будь-якому контейнері (`containers` / `initContainers`).
|
|
52
|
+
|
|
53
|
+
### Парсери / витягувачі
|
|
54
|
+
|
|
55
|
+
- `splitK8sApiVersion(apiVersion: unknown): { group: string, version: string }` — для `v1` повертає `group: ''`.
|
|
56
|
+
- `extractApiVersionAndKind(doc)` — внутрішня (не експортована), повертає `{ apiVersion, kind }` з тексту першого YAML-документа.
|
|
57
|
+
- `expectedSchemaUrl(filePath: string, doc: string): { expected: string \| null, reason: string }` — очікуваний `$schema` для маніфесту згідно з k8s.mdc; `null` означає «немає публічної схеми, modeline допустимо опустити».
|
|
58
|
+
- `k8sYamlFirstDocIsAlbYcHttpBackendGroup(yamlBody: string): boolean` — чи перший документ — `alb.yc.io/v1alpha1 HttpBackendGroup` (для виключення modeline).
|
|
59
|
+
- `collectJson6902OperationsFromPatchText(patchText: string): Array<{ op: string, path: string }>` — нормалізовані `op` (lowercase, trim) і `path`; порожній масив, якщо це не JSON6902-масив.
|
|
60
|
+
|
|
61
|
+
### Перевірки (повертають `string | null` — текст порушення або `null`)
|
|
62
|
+
|
|
63
|
+
- `deploymentResourcesViolation(manifest, inK8sBaseLayer = false)` — перевірка `Deployment.spec.template.spec.containers[].resources.requests.{cpu,memory}` (у base — жорстко `0.02` / `128Mi`).
|
|
64
|
+
- `metadataNamespaceRequiredViolation(manifest, inBaseDir = false)` — непорожній `metadata.namespace` для namespaced-документів (крім `Kustomization`, `List` і кластерних `kind`).
|
|
65
|
+
- `baseKustomizationNamespaceViolation(obj)` — непорожній `namespace:` у `base/kustomization.yaml`.
|
|
66
|
+
- `kustomizationPatchesSortedViolation(obj)` — `patches[]` у Kustomization відсортовано за tuple `[target.kind, target.name, target.namespace, path]`.
|
|
67
|
+
- `kustomizationInlinePatchOpsSortedViolation(patchText)` — inline JSON6902-ops відсортовано за `path` (тільки якщо всі `add`/`replace` і `path` попарно дизʼюнктні).
|
|
68
|
+
- `kustomizationSvcYamlMissingSvcHlViolation(kustomizationDir, pathRefs)` — для кожного `svc.yaml` у `pathRefs` є sibling `svc-hl.yaml`.
|
|
69
|
+
- `serviceSvcYamlClusterIpTypeViolation(manifest)` — `Service.spec.type === 'ClusterIP'` у `svc.yaml`.
|
|
70
|
+
- `serviceSvcHlYamlHeadlessViolation(manifest)` — `Service` у `svc-hl.yaml` headless (`spec.clusterIP: 'None'`) і `metadata.name` із суфіксом `-hl`.
|
|
71
|
+
- `healthCheckPolicyTargetRefHeadlessServiceViolation(manifest)` — `HealthCheckPolicy` (`networking.gke.io/v1`) посилається на headless `Service` (суфікс `-hl`).
|
|
72
|
+
- `httpRouteHasuraCanonViolation(manifest)` — канон 4 правил `HTTPRoute` для Hasura-Deployment.
|
|
73
|
+
- `deploymentTopologySpreadConstraintsViolation(manifest, expectedAppLabel)` — обовʼязкові канонічні `topologySpreadConstraints` у `Deployment`.
|
|
74
|
+
- `hpaManifestViolations(manifest, expectedDeployName, isDevLike): string[]` — список помилок (`scaleTargetRef`, replica-межі, `behavior`, …).
|
|
75
|
+
- `pdbManifestViolations(manifest, expectedAppLabel, isDevLike): string[]` — список помилок (`minAvailable`, `selector`).
|
|
76
|
+
|
|
77
|
+
### Класифікатори / збиральники
|
|
78
|
+
|
|
79
|
+
- `classifyBackendConfigManifestPresence(body: string): 'none' \| 'only' \| 'mixed' \| 'unparsed'` — для логіки «видалити лише `BackendConfig`-файл / fail при змішуванні».
|
|
80
|
+
- `collectDeploymentConfigMapRefs(deployment): Set<string>` — імена ConfigMap із `envFrom[*].configMapRef.name` та `volumes[*].configMap.name`.
|
|
81
|
+
- `collectGatewayApiRouteBackendServiceNames(spec): string[]` — імена `Service` з `backendRefs`/`backendRef` у дереві `spec` маршруту Gateway API (можливі дублікати).
|
|
82
|
+
- `collectGatewayApiRouteBackendRefsWithRedundantNamespace(spec, routeNs): string[]` — імена backend-сервісів, у яких `namespace` дорівнює `metadata.namespace` маршруту (надлишкове поле).
|
|
83
|
+
- `kustomizePathRefsForExistenceCheck(obj): string[]` — унікальні локальні шляхи з `resources`/`bases`/`components`/`crds`/`patchesStrategicMerge`/`patches[].path`/`patchesJson6902[].path`/`configurations[]`/`replacements[].path`.
|
|
84
|
+
|
|
85
|
+
### Кустомайз: дескриптори ресурсів і `target`
|
|
86
|
+
|
|
87
|
+
- `shouldValidateKustomizePatchTarget(target): boolean` — чи статичний resolve застосовується (без `labelSelector`/`annotationSelector`).
|
|
88
|
+
- `kustomizePatchTargetMatchesDescriptor(target, res): boolean` — порівнює `target` із `KustomizeResourceDescriptor`.
|
|
89
|
+
- `kustomizeResourceCatalogMatchesPatchTarget(catalog, target): boolean` — чи хоч один дескриптор у `catalog` відповідає `target`.
|
|
90
|
+
- `kustomizeResourceDescriptorsIdentityEqual(a, b): boolean` — повна тотожність `{group, version, kind, name, namespace}`.
|
|
91
|
+
- `kustomizeResourceDescriptorFromManifest(obj, kustomizationDefaultNs): KustomizeResourceDescriptor \| null` — будує дескриптор з YAML-кореня; `Kustomization` та документи без `metadata.name` пропускаються; для кластерних `kind` `namespace = ''`.
|
|
92
|
+
- `collectResourceDescriptorsForKustomizationWalk(kustAbs, rootNorm, visitedKustomization): Promise<KustomizeResourceDescriptor[]>` — рекурсивний обхід `resources` / `bases` / `components` / `crds` (через вкладені `kustomization.yaml`); повторний вхід в один файл — порожній внесок.
|
|
93
|
+
- `kustomizationPatchPathsByTargetKind(kust): Record<string, string[]>` — для прод-overlay: групує модифіковані JSON-Pointer paths за `kind` ресурсу-цілі (з урахуванням Strategic Merge).
|
|
94
|
+
- `kustomizePatchModifiedPaths(patchText): string[]` — нормалізовані `path`-и з тексту inline patch (JSON6902).
|
|
95
|
+
|
|
96
|
+
### Манипуляції з YAML / автофікси
|
|
97
|
+
|
|
98
|
+
- `replaceBatchV1beta1ApiVersionInYamlText(raw): { changed: boolean, content: string }` — рядкова заміна `apiVersion: batch/v1beta1` → `batch/v1`, з повагою до EOL і коментарів.
|
|
99
|
+
- `cleanupKustomizationImagesInYamlText(raw): string` — зрізає `:tag` із `name` у блоку `images:` (digest не чіпає) і видаляє зайвий `newTag`, який збігається з відрізаним тегом.
|
|
100
|
+
- `splitImageNameTagDigest(image): { name, tag, digest }` — розбиває рядок образу.
|
|
101
|
+
- `imageReplaceDeploymentPatchInfo(patchObj): { deployName, containerIndex, value } \| null` — розпізнає JSON6902 `op: replace` на `…/containers/<N>/image` для конвертації у `images:`.
|
|
102
|
+
- `convertImagePatchesToImagesInKustomization(kustAbs, rootNorm): Promise<void>` — повна конвертація patch → `images:` для одного `kustomization.yaml` (включно з резолвом базового образу через дерево kustomize).
|
|
103
|
+
- `ensureResourceInKustomizationYaml(raw, resourceName): string` — додає `- <resourceName>` у блок `resources:` без переписування решти файлу (стабільна вставка з YAML-кваліфікатором).
|
|
104
|
+
- `regenerateLegacyNetworkPolicyDocsInFile(npAbs, fail): Promise<void>` — переписує legacy-документи `NetworkPolicy` (наприклад з `egress: [{}]`) у канонічну форму через snippet.
|
|
105
|
+
|
|
106
|
+
### NetworkPolicy
|
|
107
|
+
|
|
108
|
+
- `loadSnippetSpec(snippetName: 'deployment' \| 'statefulSet'): object` — читає snippet-файл з `../policy/network_policy/template/*.snippet.yaml` і повертає розпарсений `spec`; результат кешується в пам’яті процесу.
|
|
109
|
+
- `snippetNameForKind(kind): 'deployment' \| 'statefulSet'` — диспетчеризація через `KIND_TO_SNIPPET`; кидає `Error` на невідомий `kind`.
|
|
110
|
+
- `buildNetworkPolicyYaml(deployName, appLabel, kind, gclbPorts?): string` — повний YAML `NetworkPolicy` із modeline `$schema`, анотацією `nitra.dev/workload-kind`, опційним GCLB ingress-правилом.
|
|
111
|
+
- `collectHttpRouteIngressForWorkload(dir, appLabel, fail): Promise<{ ports: number[] } | null>` — відсортовані унікальні TCP-порти з backendRefs `HTTPRoute`, що адресують workload з міткою `appLabel`.
|
|
112
|
+
|
|
113
|
+
### Workload-helper-и
|
|
114
|
+
|
|
115
|
+
- `deploymentAppLabel(deployment): string` — мітка `app` з `spec.selector.matchLabels` (з fallback на pod-template).
|
|
116
|
+
- `workloadAppLabel(manifest): string` — узагальнено для `Deployment`/`StatefulSet`/`DaemonSet`/`Job`/`CronJob`.
|
|
117
|
+
- `findDeploymentDocInDir(dirPath): Promise<Record<string, unknown> | null>` — перший YAML-документ `kind: Deployment` у каталозі.
|
|
118
|
+
- `k8sEnvSegmentFromRelPath(relPath): string` — повертає сегмент каталогу після `/k8s/` (`base`, `dev`, `ua-qa`, `ua`, …).
|
|
119
|
+
- `isDevLikeK8sEnvSegment(segment): boolean` — `true` для `base`, `dev`, `*-qa`.
|
|
120
|
+
|
|
121
|
+
### Hasura
|
|
122
|
+
|
|
123
|
+
- `kustomizationTreeHasHasuraDeployment(kustAbs, rootNorm): Promise<boolean>` — `true`, якщо в Kustomize-дереві є Hasura-Deployment.
|
|
124
|
+
- `enabledApisValueFromPatchText(patchText): string | null` — витягує значення `HASURA_GRAPHQL_ENABLED_APIS` із inline JSON6902-патча.
|
|
125
|
+
- `hasuraEnabledApisOverrideValue(kust): string | null` — значення overlay-патча для ConfigMap-ключа.
|
|
126
|
+
|
|
127
|
+
### Прод-оверрайди
|
|
128
|
+
|
|
129
|
+
- `prodOverlayHpaPdbOverrideNeeds(rootNorm, kustAbs): Promise<{ hpaNames: Set<string>, pdbNames: Set<string> }>` — для прод-overlay визначає, для яких HPA/PDB потрібні `/spec/minReplicas`, `/spec/maxReplicas`, `/spec/minAvailable`.
|
|
130
|
+
- `kustomizeResourceTreeHpaPdbDeploymentFlags(kustAbs, rootNorm): Promise<{ hasHpa, hasPdb, hasDeployment }>` — прапорці наявності в дереві ресурсів.
|
|
131
|
+
|
|
132
|
+
### Перевірка компонентів
|
|
133
|
+
|
|
134
|
+
- `validateComponentsForBaseDeployment(baseDir, deployName, appLabel, root, fail, passFn): Promise<void>` — повна перевірка sibling-каталогу `components/` для одного `Deployment` у base.
|
|
135
|
+
|
|
136
|
+
### Точка входу
|
|
137
|
+
|
|
138
|
+
- `async check(cwd = process.cwd()): Promise<number>` — повний прогін `check k8s`; повертає `process.exitCode` (`0` при успіху, `1` при будь-якому `fail`).
|
|
139
|
+
|
|
140
|
+
## Функції
|
|
141
|
+
|
|
142
|
+
Через об'єм модуля нижче згруповано фрагменти за функціональним призначенням; для кожної функції-вершини наведено сигнатуру, ключові параметри, що повертає та помітні побічні ефекти.
|
|
143
|
+
|
|
144
|
+
### Точка входу
|
|
145
|
+
|
|
146
|
+
#### `check(cwd?)`
|
|
147
|
+
|
|
148
|
+
- **Сигнатура:** `async function check(cwd: string = process.cwd()): Promise<number>`
|
|
149
|
+
- **Параметри:** `cwd` — корінь репозиторію.
|
|
150
|
+
- **Повертає:** `Promise<number>` — `0` (успіх) або `1` (якщо реєструвався хоча б один `fail`); агрегація через `createCheckReporter()`.
|
|
151
|
+
- **Side effects:** читання/запис YAML-файлів (автозаміна `batch/v1beta1`, переписування `images:`, генерація `networkpolicy.yaml`, видалення `BackendConfig`-only файлів через `unlink`); виклик `runConftestBatch` (Rego-полісі під `npm/policy/k8s/*`).
|
|
152
|
+
- **Послідовність кроків:** `loadCursorIgnorePaths` → `rewriteBatchV1beta1ApiVersionInK8sYamlFiles` → `removeBackendConfigOnlyK8sYamlFiles` → `findK8sYamlFiles` → `autofixKustomizationImagesYaml` → `ensureNetworkPoliciesForK8sWorkloads` → `assertNoForbiddenK8sDevPaths` → `runAllK8sRego` → `checkK8sYamlFile` для кожного файла → серія `validate*` (svc-pair, Hasura HTTPRoute, kustomization path refs, patch targets, HPA/PDB only with base Deployment, ConfigMap name match, Hasura ConfigMap, HPA/PDB/topology, NetworkPolicy, прод-оверрайди, Hasura overlay enabled APIs).
|
|
153
|
+
|
|
154
|
+
#### `runAllK8sRego(root, yamlFiles, fail)` _(внутрішня)_
|
|
155
|
+
|
|
156
|
+
Запускає `runConftestBatch` для 8 цільових namespace: `k8s.manifest`, `k8s.gateway`, `k8s.hpa_pdb`, `k8s.network_policy` (з `templateData` snippet-ів), `k8s.kustomization`, `k8s.svc_yaml`, `k8s.svc_hl_yaml`, `k8s.base_kustomization`, `k8s.base_manifest`. Поки що файлами обмежує: kustomization-и — за basename, base-resource — за регексом `/k8s/base/`, інше — весь набір.
|
|
157
|
+
|
|
158
|
+
### Виявлення / фільтрація шляхів
|
|
159
|
+
|
|
160
|
+
- `pathHasK8sSegment(filePath, root?)` — `relative` від `root`, потім розбиття за `/` чи `\` і пошук компонента `k8s`; пустий `relative` → `false` (сам корінь репо). Без `root` — старий шлях для тестів.
|
|
161
|
+
- `isK8sYamlUnderBaseDirectory(relPosix)` — `splitParts.indexOf('k8s')` + перевірка `dirs.includes('base')` для каталогу між `k8s` і файлом.
|
|
162
|
+
- `isForbiddenK8sDevPath(rel)` — `rel.includes('/k8s/dev/')` (попередньо `\\` → `/`).
|
|
163
|
+
- `isBaseKustomizationPath(rel)` — `K8S_BASE_KUSTOMIZATION_PATH_RE` = `/(^|\/)k8s\/base\/kustomization\.yaml$/`.
|
|
164
|
+
- `isK8sBaseManifestYamlPath(rel, baseLower)` — не `kustomization.yaml` + `K8S_BASE_SEGMENT_RE` (`/(^|\/)k8s\/base\//`).
|
|
165
|
+
- `findK8sYamlFiles(root, ignorePaths?)` _(внутрішня)_ — `walkDir` із фільтром `pathHasK8sSegment` + `YAML_EXTENSION_RE`; виключає `.github/` (належить `ga.mdc`); сортує `localeCompare`.
|
|
166
|
+
|
|
167
|
+
### Modeline `$schema` та валідація URL
|
|
168
|
+
|
|
169
|
+
- `checkK8sYamlFile(abs, root, fail, pass)` _(внутрішня)_ — диспетчер на `.yml` (fail), `HttpBackendGroup` (`k8sYamlFirstDocIsAlbYcHttpBackendGroup` — modeline заборонено), без modeline (`pass` із підказкою «опційно», fail якщо modeline нижче), стандартний шлях (`checkK8sYamlFileWithSchemaModeline`).
|
|
170
|
+
- `checkK8sYamlFileWithSchemaModeline` — `MODELINE_RE` для першого рядка, `countSchemaModelines > 1` → fail, заборона `$schema=file:…`, перевірка `https://`, виклик `expectedSchemaUrl` і порівняння з фактом.
|
|
171
|
+
- `expectedSchemaUrl(filePath, doc)` — `kustomization.yaml` → `KUSTOMIZATION_SCHEMA` (`schemastore`); інакше через `expectedSchemaUrlForTypedManifest(doc, apiVersion, kind)`.
|
|
172
|
+
- `expectedSchemaUrlForTypedManifest` — спочатку `lookupExplicitK8sSchema` (за `apiVersion + kind + type`/`*`), далі `v1` → `${YANNH_BASE}<kind>-v1.json`, group у `YANNH_GROUPS` → `${YANNH_BASE}<kind>-<group-first-segment>-<version>.json`, інакше → `${DATREE_CRD_BASE}<group>/<kind>_<version>.json`.
|
|
173
|
+
- `EXPLICIT_K8S_SCHEMAS` — `Map` з ключем `apiVersion\0kind\0typeKey`; зараз містить `InfisicalSecret v1alpha1` (datree raw) і `Secret type kubernetes.io/basic-auth` (yannh).
|
|
174
|
+
|
|
175
|
+
### Структура Kustomize
|
|
176
|
+
|
|
177
|
+
- `kustomizationPatchesSortedViolation(obj)` — порядок `patches[]` за `compareStringTuplesEn([kind, name, namespace, path])` (`localeCompare('en', { sensitivity: 'base' })`); `length < 2` → `null`; повертає `Have: …; Expected: …` у людиночитній формі.
|
|
178
|
+
- `kustomizationInlinePatchOpsSortedViolation(patchText)` — парсить JSON6902 через `parseJson6902OpsFromText` (`yaml.parseDocument(...).toJSON()` → масив `{op, path}`); сортує **тільки** якщо всі `add`/`replace` і `path` попарно дизʼюнктні (`jsonPointerPathsAreDisjoint`).
|
|
179
|
+
- `kustomizePathRefsForExistenceCheck(obj)` — `pathsFromKustomizationObject` (resources/bases/components/crds/patchesStrategicMerge/`patches[].path`) + `patchesJson6902[].path` + `configurations[]` + `replacements[].path`; dedup через `Set`.
|
|
180
|
+
- `validateKustomizationPathRefsExistOnDisk` _(внутрішня)_ — для кожного `kustomization.yaml`: `validateKustomizationRef` (resolve, перевірка під коренем, `stat`, `.yaml`/`.yml` для файла).
|
|
181
|
+
- `validateKustomizationPatchTargetsResolved` _(внутрішня)_ + `validatePatchTargetsOneKustomizationFile` — будує `catalog: KustomizeResourceDescriptor[]` через `collectResourceDescriptorsForKustomizationWalk` (рекурсивно), порівнює `target` (`failIfExplicitPatchTargetsNotInCatalog`), реєструє надлишкові `group`/`version` (`failIfExplicitPatchTargetsHaveRedundantGroupVersion`), перевіряє файлові kind/name (`failIfYamlFileRootsMissingFromCatalog`, `failIfStrategicMergePatchesNotInCatalog`, `failIfPathOnlyPatchesNotInCatalog`).
|
|
182
|
+
- `validateKustomizationIncludesSvcHlWithSvc` _(внутрішня)_ + `kustomizationSvcYamlMissingSvcHlViolation` — у `pathRefs` `svc.yaml` має парний `svc-hl.yaml` за тим самим `resolve`-каталогом.
|
|
183
|
+
- `baseKustomizationNamespaceViolation(obj)` — `obj.namespace` має бути непорожнім рядком після `.trim()`.
|
|
184
|
+
|
|
185
|
+
### Resource resolve / дескриптори
|
|
186
|
+
|
|
187
|
+
- `kustomizeResourceDescriptorFromManifest(obj, kustomizationDefaultNs)` — пропускає `Kustomization` і документи без `metadata.name`; для кластерних `kind` `namespace = ''`; інакше — `metadata.namespace` або дефолт із батьківського kustomization.
|
|
188
|
+
- `collectResourceDescriptorsForKustomizationWalk(kustAbs, rootNorm, visitedKustomization)` — рекурсивний обхід `resources`/`bases`/`components`/`crds`. Для каталогу — спускається у вкладений `kustomization.yaml`; для файлу — парсить документи і будує дескриптор з YAML-кореня. `visitedKustomization` (`Set<string>`) запобігає повторному входу. Дефолтний `namespace` тягнеться з батьківського kustomize.
|
|
189
|
+
- `kustomizePatchTargetMatchesDescriptor`, `kustomizeResourceCatalogMatchesPatchTarget`, `kustomizeResourceDescriptorsIdentityEqual` — порівняння `target` (`group/version/kind/name/namespace`).
|
|
190
|
+
- `shouldValidateKustomizePatchTarget(target)` — `patchTargetUsesSelector(target) === false`.
|
|
191
|
+
|
|
192
|
+
### Resources (`Deployment` containers)
|
|
193
|
+
|
|
194
|
+
- `deploymentResourcesViolation(manifest, inK8sBaseLayer = false)` — обходить `spec.template.spec.containers[]`, для кожного — `deploymentContainerResourcesViolation`. Перевіряє наявність `resources.requests.cpu` і `.memory` (`isValidCpuRequestValue`, `isValidMemoryRequestValue`); у base — додатково `isBaseCanonCpuValue` (`0.02` як рядок чи число) і `isBaseCanonMemoryValue` (`/^128Mi$/iu`).
|
|
195
|
+
- Допускає `cpu` як число (`0.02`) і як рядок (`"0.02"`, `"500m"`); `memory` лише непорожній рядок Quantity. У повідомленнях про помилку друкує `JSON.stringify(value)`.
|
|
196
|
+
|
|
197
|
+
### Service / Gateway API
|
|
198
|
+
|
|
199
|
+
- `serviceSvcYamlClusterIpTypeViolation(manifest)` — `kind === 'Service'` + `spec.type === 'ClusterIP'`.
|
|
200
|
+
- `serviceSvcHlYamlHeadlessViolation(manifest)` — `metadata.name` має `endsWith('-hl')`, `spec.clusterIP === 'None'`.
|
|
201
|
+
- `healthCheckPolicyTargetRefHeadlessServiceViolation(manifest)` — `apiVersion === 'networking.gke.io/v1'`, `kind === 'HealthCheckPolicy'`; якщо `targetRef.kind` явно задано і ≠ `Service` → `null`; вимагає `name.endsWith('-hl')`.
|
|
202
|
+
- `collectGatewayApiRouteBackendServiceNames(spec)` / `collectGatewayApiRouteBackendRefsWithRedundantNamespace(spec, routeNs)` — обхід дерева `spec`, для кожного вузла-обʼєкта перевіряє `isGatewayApiBackendRefToService` (потрібен числовий `port`, `kind === 'Service'`/відсутнє, `group === ''`/`core`/відсутнє); другий ще порівнює `namespace === routeNs`.
|
|
203
|
+
|
|
204
|
+
### Hasura
|
|
205
|
+
|
|
206
|
+
- `isHasuraDeploymentManifest(manifest)` — `kind: Deployment` і хоч один `containers[i].image` або `initContainers[i].image` під регекс `HASURA_GRAPHQL_ENGINE_RE` (`(^|\/)hasura/graphql-engine(?::|$)`); digest `@…` ігнорується.
|
|
207
|
+
- `httpRouteHasuraCanonViolation(manifest)` — пошук канонічного блока з 4 правилами (`<prefix>/ql` redirect, `<prefix>/ql/` redirect, `PathPrefix <prefix>/ql` + URLRewrite на `/`, WebSocket з `RequestHeaderModifier` remove `Authorization`); префікс параметризовано (рядок до `/ql`); додаткові правила поверх канону дозволені.
|
|
208
|
+
- `validateHasuraConfigMapRemoteSchemaPermissions` _(внутрішня)_ — у `data` ConfigMap у каталогу з Hasura-Deployment має бути `HASURA_GRAPHQL_ENABLE_REMOTE_SCHEMA_PERMISSIONS=true` (рядок або булева).
|
|
209
|
+
- `validateHasuraOverlayEnabledApisOverride` _(внутрішня)_ — overlay має перевизначати `HASURA_GRAPHQL_ENABLED_APIS` на `'metadata,graphql'` (через JSON6902 на `/data/HASURA_GRAPHQL_ENABLED_APIS` або strategic merge).
|
|
210
|
+
- `kustomizationTreeHasHasuraDeployment(kustAbs, rootNorm)` — `true`, якщо у дереві ресурсів є Hasura-Deployment.
|
|
211
|
+
|
|
212
|
+
### HPA / PDB / Topology / NetworkPolicy
|
|
213
|
+
|
|
214
|
+
- `hpaManifestViolations(manifest, expectedDeployName, isDevLike)` — `validateHpaScaleTargetRef` (`scaleTargetRef.name === expectedDeployName`, `kind: Deployment`), `validateHpaReplicaLimits` (dev-like: `min === 1` && `max === 1`; прод: `min >= 2` && `max >= 2`), `validateHpaBehavior` (заборона будь-якого `behavior:`).
|
|
215
|
+
- `pdbManifestViolations(manifest, expectedAppLabel, isDevLike)` — `validatePdbMinAvailable` (dev-like: `0`; прод: `>= 1`), `validatePdbSelector` (`spec.selector.matchLabels.app === expectedAppLabel`).
|
|
216
|
+
- `deploymentTopologySpreadConstraintsViolation(manifest, expectedAppLabel)` — масив `topologySpreadConstraints` має містити канонічний елемент (`topologyKey: 'kubernetes.io/hostname'`, `whenUnsatisfiable: 'ScheduleAnyway'`, `maxSkew: 1`, `labelSelector.matchLabels.app === expectedAppLabel`).
|
|
217
|
+
- `validateComponentsForBaseDeployment(baseDir, deployName, appLabel, root, fail, passFn)` — перевіряє sibling `components/`: `kustomization.yaml` з `apiVersion: kustomize.config.k8s.io/v1alpha1, kind: Component`, `resources: [hpa.yaml, pdb.yaml]`; валідує `hpa.yaml` (dev-like `min=max=1`) і `pdb.yaml` (dev-like `minAvailable=0`).
|
|
218
|
+
- `validateKustomizeHpaPdbOnlyWithBaseDeployment` _(внутрішня)_ — заборонено HPA/PDB у дереві base; в overlay, що підключає `base`, HPA/PDB без узгодженого Deployment теж заборонено.
|
|
219
|
+
- `validateProdKustomizationOverrides` _(внутрішня)_ + `prodOverlayHpaPdbOverrideNeeds` — для прод-overlay перевіряє наявність JSON-Pointer-патчів `/spec/minReplicas`, `/spec/maxReplicas` (HPA) і `/spec/minAvailable` (PDB) у `patches[]`.
|
|
220
|
+
- `kustomizationPatchPathsByTargetKind(kust)` — групує модифіковані JSON-Pointer-шляхи з усіх `patches[]` за `kind` ресурсу-цілі (бере `target.kind` або з strategic merge — `kind`).
|
|
221
|
+
- `buildNetworkPolicyYaml(deployName, appLabel, kind, gclbPorts?)` — клонує `loadSnippetSpec(KIND_TO_SNIPPET[kind])`, підставляє `podSelector.matchLabels.app`, опційно додає GCLB ingress-правило (CIDR-и `35.191.0.0/16`, `130.211.0.0/22`, `10.0.0.0/8` + унікальні відсортовані TCP-порти), рендерить YAML з modeline `$schema=networkpolicy-networking-v1.json` (yannh).
|
|
222
|
+
- `collectHttpRouteIngressForWorkload(dir, appLabel, fail)` — у каталогу збирає `HTTPRoute` маніфести, для кожного `backendRef.name` зіставляє з `Service.metadata.name`, потім перевіряє `service.spec.selector.matchLabels.app === appLabel` і агрегує `port` як TCP. Результат — `{ ports: number[] }` (відсортовано, унікально) або `null`.
|
|
223
|
+
- `ensureNetworkPoliciesForK8sWorkloads` _(внутрішня)_ + `ensureNetworkPoliciesForWorkloadsInDir` — створює відсутні `networkpolicy.yaml` (multi-doc, якщо workload-ів кілька); legacy-документи (наприклад `egress: [{}]`) переписує через `regenerateLegacyNetworkPolicyDocsInFile`.
|
|
224
|
+
|
|
225
|
+
### Перетворення YAML
|
|
226
|
+
|
|
227
|
+
- `replaceBatchV1beta1ApiVersionInYamlText(raw)` — `rewriteLineBatchV1beta1ApiVersion` для кожного рядка; зберігає `\r\n`/`\n`; ігнорує рядки, що починаються з `#`; `BATCH_V1BETA1_API_VERSION_LINE_RE` ловить варіанти з `"`/`'`.
|
|
228
|
+
- `classifyBackendConfigManifestPresence(body)` — `parseAllDocuments(body)` → агрегує прапорці `hasBc`/`hasOther` через `updateBackendConfigKindFlags`; повертає `'only'`/`'mixed'`/`'none'`/`'unparsed'`.
|
|
229
|
+
- `cleanupKustomizationImagesInYamlText(raw)` — рядкова обробка блока `images:` (без YAML-rebuild): `findImagesBlockRange` (блок з відступу `KUSTOMIZATION_BLOCK_INDENT_RE`), `splitImagesBlockEntries` (елементи `- name:` за `KUSTOMIZATION_LIST_ITEM_RE`), `processImagesEntry` (зрізає `:tag` у `name` через `splitImageNameTagDigest`, видаляє `newTag` що дорівнює відрізаному).
|
|
230
|
+
- `convertImagePatchesToImagesInKustomization(kustAbs, rootNorm)` — будує `images:` із `patches[]` `op: replace` на `/spec/template/spec/containers/<N>/image` (`KUSTOMIZATION_DEPLOYMENT_CONTAINER_IMAGE_PATH_RE`); для кожного — резолвить базовий образ через `walkKustomizationForDeploymentImage` (обхід ресурсного дерева Kustomize), формує `name` (без тегу), `newName` (без тегу), `newTag` (лише якщо тег у patch.value відрізняється від базового); зайвий `patches[]` чистить.
|
|
231
|
+
- `regenerateLegacyNetworkPolicyDocsInFile(npAbs, fail)` — переписує файл, замінюючи legacy NetworkPolicy-документи на канонічні через `buildNetworkPolicyYaml`.
|
|
232
|
+
|
|
233
|
+
### Snippets
|
|
234
|
+
|
|
235
|
+
- `loadSnippetSpec(snippetName)` — `readFileSync(fileURLToPath(URL))` для `../policy/network_policy/template/deployment.snippet.yaml` або `…/stateful-set.snippet.yaml`; `parseDocument(raw).toJS().spec`; кеш у замиканні `_snippetCache`.
|
|
236
|
+
- `snippetNameForKind(kind)` — у `KIND_TO_SNIPPET`: `Deployment`/`Job`/`CronJob`/`DaemonSet` → `'deployment'`, `StatefulSet` → `'statefulSet'`; throw на невідомий.
|
|
237
|
+
|
|
238
|
+
### Допоміжні / утиліти
|
|
239
|
+
|
|
240
|
+
- `splitK8sApiVersion(apiVersion)` — для `v1` повертає `{ group: '', version: 'v1' }`; для `apps/v1` — `{ group: 'apps', version: 'v1' }`.
|
|
241
|
+
- `metadataNameTrimmed(meta)` / `metadataNamespaceTrimmed(meta)` — `.trim()` рядкового значення або `''`.
|
|
242
|
+
- `trimYamlScalarQuotes(raw)` — прибирає **парні** зовнішні `"`/`'` (`length >= 2` і однакові на кінцях).
|
|
243
|
+
- `stripTrailingNewlines(s)` — codePoint-варіант без regex (для sonarjs/slow-regex).
|
|
244
|
+
- `extractTopLevelManifestType(doc)` — для пошуку `type:` у документі (без повного YAML-парсера), для `EXPLICIT_K8S_SCHEMAS`.
|
|
245
|
+
- `collectJson6902OperationsFromPatchText(patchText)` — пробує YAML (`parseAllDocuments`), потім JSON (якщо починається з `[`); `op` приводиться до lowercase, `path` через `normalizeJsonPatchPath`.
|
|
246
|
+
- `noopFail = msg => msg` — дефолтний `fail` у `regenerateLegacyNetworkPolicyDocsInFile`.
|
|
247
|
+
|
|
248
|
+
## Залежності
|
|
249
|
+
|
|
250
|
+
### Зовнішні (Node.js / npm)
|
|
251
|
+
|
|
252
|
+
| Імпорт | Модуль | Призначення |
|
|
253
|
+
| ---------------------------------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------- |
|
|
254
|
+
| `existsSync`, `readFileSync` | `node:fs` | Синхронне читання snippet-шаблонів і перевірка вкладеного `kustomization.yaml`. |
|
|
255
|
+
| `readFile`, `readdir`, `stat`, `unlink`, `writeFile` | `node:fs/promises` | Асинхронні FS-операції з YAML-файлами (читання, запис автофіксів, видалення `BackendConfig`-only файлів, стат каталогів). |
|
|
256
|
+
| `basename`, `dirname`, `join`, `relative`, `resolve` | `node:path` | Маніпуляції зі шляхами (резолв kustomization-посилань, відносні шляхи для повідомлень). |
|
|
257
|
+
| `fileURLToPath` | `node:url` | Конвертація `import.meta.url`-URL snippet-файла у шлях. |
|
|
258
|
+
| `isSeq`, `parseAllDocuments`, `parseDocument`, `stringify` | `yaml` (npm) | Парсинг multi-doc YAML, рендер NetworkPolicy YAML, `toJSON()`/`toJS()` для роботи з обʼєктним поданням. |
|
|
259
|
+
|
|
260
|
+
### Внутрішні (репозиторій)
|
|
261
|
+
|
|
262
|
+
| Імпорт | Модуль | Призначення |
|
|
263
|
+
| ----------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
|
264
|
+
| `createCheckReporter` | `../../../scripts/lib/check-reporter.mjs` | Збір pass/fail повідомлень і обчислення `process.exitCode`. |
|
|
265
|
+
| `loadCursorIgnorePaths` | `../../../scripts/lib/load-cursor-config.mjs` | Завантаження списку ігнор-шляхів з cursor-конфіга для `findK8sYamlFiles`. |
|
|
266
|
+
| `runConftestBatch` | `../../../scripts/lib/run-conftest-batch.mjs` | Запуск Rego-полісі (`npm/policy/k8s/*`) одним батчем на namespace; авторитативне ядро пер-документних перевірок (Plan B). |
|
|
267
|
+
| `walkDir` | `../../../scripts/utils/walkDir.mjs` | Обхід дерева файлів з ігнор-списком. |
|
|
268
|
+
|
|
269
|
+
### Файли активів
|
|
270
|
+
|
|
271
|
+
- `../policy/network_policy/template/deployment.snippet.yaml` — канон NetworkPolicy для `Deployment`/`Job`/`CronJob`/`DaemonSet`.
|
|
272
|
+
- `../policy/network_policy/template/stateful-set.snippet.yaml` — канон NetworkPolicy для `StatefulSet`.
|
|
273
|
+
|
|
274
|
+
### Прив'язки до правил / Rego
|
|
275
|
+
|
|
276
|
+
- `.cursor/rules/n-k8s.mdc` (`k8s.mdc`) — людиночитна специфікація правил.
|
|
277
|
+
- `npm/policy/k8s/manifest`, `…/gateway`, `…/hpa_pdb`, `…/network_policy`, `…/kustomization`, `…/svc_yaml`, `…/svc_hl_yaml`, `…/base_kustomization`, `…/base_manifest` — Rego-полісі для пер-документних перевірок (виклик через `runAllK8sRego`).
|
|
278
|
+
|
|
279
|
+
## Потік виконання / Використання
|
|
280
|
+
|
|
281
|
+
### Запуск з командного рядка
|
|
282
|
+
|
|
283
|
+
Команда викликається із кореня репозиторію скриптами вищого рівня (`bun run check` / `n-cursor check k8s`):
|
|
284
|
+
|
|
285
|
+
```javascript
|
|
286
|
+
import { check } from './manifests.mjs'
|
|
287
|
+
|
|
288
|
+
const exitCode = await check(process.cwd())
|
|
289
|
+
process.exit(exitCode)
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Послідовність всередині `check()`
|
|
293
|
+
|
|
294
|
+
1. **Підготовка.** `createCheckReporter()` створює `pass`/`fail`-колбеки і лічильник помилок. `loadCursorIgnorePaths(root)` повертає список каталогів, які треба ігнорувати під час обходу.
|
|
295
|
+
2. **Автозаміна `apiVersion`.** `rewriteBatchV1beta1ApiVersionInK8sYamlFiles` обходить всі YAML під `k8s` і записує оновлені файли (`batch/v1beta1` → `batch/v1`); коментарі та лапки збережено.
|
|
296
|
+
3. **Видалення `BackendConfig`-only.** `removeBackendConfigOnlyK8sYamlFiles` через `classifyBackendConfigManifestPresence` визначає файли, що містять лише `kind: BackendConfig`, і викликає `unlink`. Змішані з іншими `kind` файли — `fail` (потрібна ручна сегментація).
|
|
297
|
+
4. **Збір файлів.** `findK8sYamlFiles` повертає відсортований список абсолютних шляхів `*.yaml`/`*.yml` під сегментом `k8s`.
|
|
298
|
+
5. **Автофікси перед валідацією.** `autofixKustomizationImagesYaml` (конвертація patch → `images:` + чистка `images:`); `ensureNetworkPoliciesForK8sWorkloads` (генерація відсутніх `networkpolicy.yaml`).
|
|
299
|
+
6. **Швидкі заборони.** `assertNoForbiddenK8sDevPaths` — `…/k8s/dev/…` дає негайний `fail`.
|
|
300
|
+
7. **Rego-полісі.** `runAllK8sRego(root, yamlFiles, fail)` запускає `runConftestBatch` для 8 namespace (`k8s.manifest`, `k8s.gateway`, `k8s.hpa_pdb`, `k8s.network_policy` з `templateData`, `k8s.kustomization`, `k8s.svc_yaml`, `k8s.svc_hl_yaml`, `k8s.base_kustomization`, `k8s.base_manifest`). Це авторитативне per-document ядро (заборона `Ingress`/`autoscaling/v1`, GCP-анотації, namespace, ресурс-патерни тощо).
|
|
301
|
+
8. **Modeline / `$schema`.** Для кожного файла `checkK8sYamlFile` робить: `.yml` → fail (перейменуй); `HttpBackendGroup` (alb.yc.io) → modeline заборонено; без modeline і без modeline нижче — `pass` (опційно); інакше — `checkK8sYamlFileWithSchemaModeline` (рівно один modeline у першому рядку, `https://`, відповідність `expectedSchemaUrl`).
|
|
302
|
+
9. **Кросфайлові валідації.** Послідовно:
|
|
303
|
+
- `validateSvcYamlAndSvcHlPairs` — пара `svc.yaml`/`svc-hl.yaml` у каталогу (наявність файла, відповідність імен/портів).
|
|
304
|
+
- `validateHasuraHttpRouteCanon` — канон `HTTPRoute` для Hasura-Deployment у тому ж каталозі.
|
|
305
|
+
- `validateKustomizationIncludesSvcHlWithSvc` — обидва файли підключено у `kustomization.yaml`.
|
|
306
|
+
- `validateKustomizationPathRefsExistOnDisk` — кожне локальне посилання у `kustomization.yaml` існує на диску.
|
|
307
|
+
- `validateKustomizationPatchTargetsResolved` — `patches[].target` / `patchesJson6902[].target` мають відповідник у каталозі ресурсів; додатково — заборона зайвих `group`/`version` без колізії GVK + name.
|
|
308
|
+
- `validateKustomizeHpaPdbOnlyWithBaseDeployment` — HPA/PDB у base-дереві заборонені; в overlay HPA/PDB допустимі лише якщо у naслідуваному base є Deployment.
|
|
309
|
+
- `validateConfigMapNameMatchesDeployment` — ConfigMap у `k8s/base/configmap.yaml` має ім’я, на яке посилається Deployment.
|
|
310
|
+
- `validateHasuraConfigMapRemoteSchemaPermissions` — `HASURA_GRAPHQL_ENABLE_REMOTE_SCHEMA_PERMISSIONS=true` для Hasura.
|
|
311
|
+
- `validateDeploymentHpaPdbAndTopology` — для кожного `Deployment` у base: канонічний `topologySpreadConstraints` + sibling `components/` із `hpa.yaml`/`pdb.yaml`/`kustomization.yaml` (Component).
|
|
312
|
+
- `validateNetworkPoliciesForK8sWorkloads` — кожен workload (`Deployment`/`StatefulSet`/`DaemonSet`/`Job`/`CronJob`) має `networkpolicy.yaml` поруч; правила egress (`kube-dns`, TCP 80/443 → `0.0.0.0/0`, інше — `namespaceSelector: {}`); ingress відповідає snippet + опційне GCLB-правило.
|
|
313
|
+
- `validateProdKustomizationOverrides` — у прод-overlay є `/spec/minReplicas`, `/spec/maxReplicas`, `/spec/minAvailable` патчі для HPA/PDB.
|
|
314
|
+
- `validateHasuraOverlayEnabledApisOverride` — overlay-патч на `HASURA_GRAPHQL_ENABLED_APIS = 'metadata,graphql'`.
|
|
315
|
+
10. **Повернення коду виходу.** `reporter.getExitCode()` — `0` якщо `fail` не реєструвався, інакше `1`.
|
|
316
|
+
|
|
317
|
+
### Імпорт окремих утиліт
|
|
318
|
+
|
|
319
|
+
Окремі експорти (наприклад `expectedSchemaUrl`, `kustomizationPatchesSortedViolation`, `deploymentResourcesViolation`, `buildNetworkPolicyYaml`, `replaceBatchV1beta1ApiVersionInYamlText`, `splitK8sApiVersion`) використовуються:
|
|
320
|
+
|
|
321
|
+
- юніт-тестами під `tests/` поруч із модулем;
|
|
322
|
+
- допоміжними скриптами / автоматизаціями `n-cursor`;
|
|
323
|
+
- іншими правилами/полісі, які перевикористовують класифікатори (`isClusterScopedKubernetesKind`, `isHasuraDeploymentManifest`) і constants (`KIND_TO_SNIPPET`, `HPA_FILENAME`, `PDB_FILENAME`, `NETWORK_POLICY_FILENAME`, `WORKLOAD_KINDS_WITH_NETWORK_POLICY`, `COMPONENTS_DIR`, `HASURA_REQUIRED_ENV_KEYS`).
|
|
324
|
+
|
|
325
|
+
### Reporting
|
|
326
|
+
|
|
327
|
+
Усі `fail(msg)` колбеки додають повідомлення у спільний агрегатор `createCheckReporter`. Повідомлення мають префікс відносного шляху файла (`relative(root, abs).replaceAll('\\', '/')`), щоб у CI логи були переносимі. Reporter обчислює `process.exitCode = 1` при наявності хоча б одного fail; `pass` повідомлення друкуються у звіт як inform.
|
|
328
|
+
|
|
329
|
+
### Контракти між шарами JS та Rego
|
|
330
|
+
|
|
331
|
+
JS-функції модуля **не дублюють** перевірки, винесені у Rego (Plan B). Закоментовані секції в коді (`// Plan B: …`) явно фіксують, які функції-перевірки видалено зі скрипту й перенесено у `npm/policy/k8s/*`. JS лишає лише: cross-file orchestration, modeline-перевірку, перевірку існування шляхів і FS-автофікси.
|
|
332
|
+
|
|
333
|
+
## Rebuild Test
|
|
334
|
+
|
|
335
|
+
- Чи модуль експортує точку входу `check(cwd)`, що повертає `Promise<number>`? **Так** — рядок 6696 (`export async function check(cwd = process.cwd())`).
|
|
336
|
+
- Чи перевіряється `kind: Deployment` контейнерний `resources.requests`? **Так** — `deploymentResourcesViolation` (експорт на рядку 2267) + `deploymentContainerResourcesViolation`.
|
|
337
|
+
- Чи перевірка `$schema` modeline покриває kustomization, yannh, datree, явну таблицю? **Так** — `expectedSchemaUrl` + `expectedSchemaUrlForTypedManifest` + `EXPLICIT_K8S_SCHEMAS`.
|
|
338
|
+
- Чи перевизначаються константи base-канону `0.02`/`128Mi` поруч із дефолтами `0.5`/`512Mi`? **Так** — `K8S_BASE_CONTAINER_*_REQUEST` і `DEFAULT_CONTAINER_*_REQUEST`.
|
|
339
|
+
- Чи генерація `NetworkPolicy` використовує snippet-шаблони з `../policy/network_policy/template/`? **Так** — `NETWORK_POLICY_SNIPPET_URLS` і `loadSnippetSpec`.
|
|
340
|
+
- Чи передбачені автофікси `batch/v1beta1` → `batch/v1` і `BackendConfig`-only-видалення? **Так** — `replaceBatchV1beta1ApiVersionInYamlText` і `removeBackendConfigOnlyK8sYamlFiles`.
|
|
341
|
+
- Чи делеговано пер-документне ядро у Rego? **Так** — `runAllK8sRego` з 8 namespace + коментарі «Plan B».
|
|
342
|
+
- Чи `pathHasK8sSegment` приймає опційний `root` для relativize? **Так** — щоб уникнути false-positive у репо з компонентою `k8s` у самому корені.
|
|
343
|
+
- Чи `findK8sYamlFiles` виключає `.github/`? **Так** — належить правилу `ga.mdc`.
|
|
344
|
+
- Чи `isHasuraDeploymentManifest` дивиться і `containers`, і `initContainers`? **Так** — `containerListHasHasuraImage(p.containers) || containerListHasHasuraImage(p.initContainers)`.
|
|
@@ -3682,7 +3682,9 @@ async function validateHasuraConfigMapRemoteSchemaPermissions(root, yamlFilesAbs
|
|
|
3682
3682
|
fail(`${rel}: ${v.message}`)
|
|
3683
3683
|
}
|
|
3684
3684
|
if (violations.length === 0) {
|
|
3685
|
-
passFn(
|
|
3685
|
+
passFn(
|
|
3686
|
+
`Hasura-ConfigMap (${paired.length}) містить обов'язкові env [${HASURA_REQUIRED_ENV_KEYS.join(', ')}] (rego)`
|
|
3687
|
+
)
|
|
3686
3688
|
}
|
|
3687
3689
|
}
|
|
3688
3690
|
|
|
@@ -5041,7 +5043,9 @@ async function validateHasuraOverlayEnabledApisOverride(root, yamlFilesAbs, fail
|
|
|
5041
5043
|
if (!(await kustomizationTreeHasHasuraDeployment(kustAbs, rootNorm))) continue
|
|
5042
5044
|
const value = hasuraEnabledApisOverrideValue(kust)
|
|
5043
5045
|
if (value === HASURA_OVERLAY_ENABLED_APIS) {
|
|
5044
|
-
passFn(
|
|
5046
|
+
passFn(
|
|
5047
|
+
`${rel}: overlay '${segment}' перевизначає HASURA_GRAPHQL_ENABLED_APIS="${HASURA_OVERLAY_ENABLED_APIS}" (k8s.mdc)`
|
|
5048
|
+
)
|
|
5045
5049
|
} else if (value === null) {
|
|
5046
5050
|
fail(
|
|
5047
5051
|
`${rel}: overlay '${segment}' має у patches[] перевизначати data.HASURA_GRAPHQL_ENABLED_APIS до "${HASURA_OVERLAY_ENABLED_APIS}" (pgdump лише для base/dev) (k8s.mdc)`
|
package/rules/k8s/k8s.mdc
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: K8s YAML — $schema (yaml-language-server); lint-k8s (kubeconform, kubescape); check-k8s
|
|
3
|
-
version: '1.
|
|
3
|
+
version: '1.43'
|
|
4
4
|
globs: "**/k8s/**/*.yaml"
|
|
5
5
|
alwaysApply: false
|
|
6
6
|
---
|
|
@@ -422,7 +422,7 @@ images:
|
|
|
422
422
|
- **`hpa.yaml`** — `autoscaling/v2`, `HorizontalPodAutoscaler`, **без** `metadata.namespace` (namespace задає kustomization-споживач), `spec.scaleTargetRef.name` **= `metadata.name`** Deployment з base, dev-like значення `minReplicas: 1`, `maxReplicas: 1`.
|
|
423
423
|
- **`pdb.yaml`** — `policy/v1`, `PodDisruptionBudget`, **без** `metadata.namespace`, `spec.selector.matchLabels.app` **= `spec.selector.matchLabels.app`** Deployment, dev-like `minAvailable: 0`.
|
|
424
424
|
|
|
425
|
-
**Канонічний `base/networkpolicy.yaml`** — `networking.k8s.io/v1`, `NetworkPolicy`, **без** `metadata.namespace` (namespace додає `base/kustomization.yaml`); один або кілька документів (`---`) — по одному на кожен workload (**Deployment** / **StatefulSet** / **DaemonSet** / **Job** / **CronJob**) у тому ж `base/`; `metadata.name` **= `metadata.name`** workload, `spec.podSelector.matchLabels.app` **= мітка `app`** workload. **Ingress:** `from.podSelector: {}` (інші Pod у namespace). **Egress (усі workload-и):** kube-dns через `kube-system` namespaceSelector (UDP/TCP 53); link-local DNS `169.254.0.0/16` (UDP/TCP 53, GKE NodeLocal DNSCache); **TCP 80 і 443** на `0.0.0.0/0` (HTTP/HTTPS назовні); **in-cluster** — `to.namespaceSelector: {}` з **явним списком TCP-портів** (`80, 443, 5432, 3306, 1433, 6379, 8080, 4317, 4318`; трафік на `*.svc` / Pod-и в кластері). **StatefulSet** додатково має egress/ingress `to/from.podSelector: {}` для intra-replica реплікації. Заборонено: `egress: [{}]`; `to.namespaceSelector: {}` без `ports:` (catch-all). Додаткові правила можна дописати поряд — superset-підхід. Канон — два **повних** snippet-файли (без merge у runtime; JS-генератор/rego обирають один за `kind` workload-у через анотацію `metadata.annotations['nitra.dev/workload-kind']`): [deployment.snippet.yaml](./policy/network_policy/template/deployment.snippet.yaml) (для `Deployment`/`Job`/`CronJob`/`DaemonSet`) та [stateful-set.snippet.yaml](./policy/network_policy/template/stateful-set.snippet.yaml) (для `StatefulSet`; містить deployment-канон + intra-replica правила). Якщо документа для workload немає — **`check k8s`** дописує його автоматично.
|
|
425
|
+
**Канонічний `base/networkpolicy.yaml`** — `networking.k8s.io/v1`, `NetworkPolicy`, **без** `metadata.namespace` (namespace додає `base/kustomization.yaml`); один або кілька документів (`---`) — по одному на кожен workload (**Deployment** / **StatefulSet** / **DaemonSet** / **Job** / **CronJob**) у тому ж `base/`; `metadata.name` **= `metadata.name`** workload, `spec.podSelector.matchLabels.app` **= мітка `app`** workload. **Ingress:** `from.podSelector: {}` (інші Pod у namespace). **Egress (усі workload-и):** kube-dns через `kube-system` namespaceSelector (UDP/TCP 53); link-local DNS `169.254.0.0/16` (UDP/TCP 53, GKE NodeLocal DNSCache); **TCP 80 і 443** на `0.0.0.0/0` (HTTP/HTTPS назовні); **in-cluster** — `to.namespaceSelector: {}` з **явним списком TCP-портів** (`80, 443, 5432, 3306, 1433, 6379, 8080, 4222, 4317, 4318`; трафік на `*.svc` / Pod-и в кластері). **StatefulSet** додатково має egress/ingress `to/from.podSelector: {}` для intra-replica реплікації. Заборонено: `egress: [{}]`; `to.namespaceSelector: {}` без `ports:` (catch-all). Додаткові правила можна дописати поряд — superset-підхід. Канон — два **повних** snippet-файли (без merge у runtime; JS-генератор/rego обирають один за `kind` workload-у через анотацію `metadata.annotations['nitra.dev/workload-kind']`): [deployment.snippet.yaml](./policy/network_policy/template/deployment.snippet.yaml) (для `Deployment`/`Job`/`CronJob`/`DaemonSet`) та [stateful-set.snippet.yaml](./policy/network_policy/template/stateful-set.snippet.yaml) (для `StatefulSet`; містить deployment-канон + intra-replica правила). Якщо документа для workload немає — **`check k8s`** дописує його автоматично.
|
|
426
426
|
|
|
427
427
|
Інші назви каталогу (`scale/`, `hpa-component/`, `pdb-component/`) — fail.
|
|
428
428
|
|
|
@@ -605,6 +605,8 @@ spec:
|
|
|
605
605
|
port: 6379
|
|
606
606
|
- protocol: TCP
|
|
607
607
|
port: 8080
|
|
608
|
+
- protocol: TCP
|
|
609
|
+
port: 4222
|
|
608
610
|
- protocol: TCP
|
|
609
611
|
port: 4317
|
|
610
612
|
- protocol: TCP
|