@nitra/cursor 1.8.113 → 1.8.114
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 +9 -0
- package/package.json +1 -1
- package/scripts/check-k8s.mjs +107 -0
package/mdc/k8s.mdc
CHANGED
|
@@ -214,6 +214,15 @@ spec:
|
|
|
214
214
|
|
|
215
215
|
Якщо в `k8s/base/` є **`configmap.yaml`** і **Deployment**, і цей Deployment посилається рівно на **один** ConfigMap — `metadata.name` ConfigMap має збігатися з `metadata.name` Deployment. Точні умови перевірки — **`check-k8s.mjs`**.
|
|
216
216
|
|
|
217
|
+
## ConfigMap для Hasura-Deployment
|
|
218
|
+
|
|
219
|
+
Якщо в `k8s/base/` поруч із **`configmap.yaml`** є **Deployment** з образом **`hasura/graphql-engine`**, у `data` ConfigMap **обов'язково** має бути ключ **`HASURA_GRAPHQL_ENABLE_REMOTE_SCHEMA_PERMISSIONS`** зі значенням **`"true"`**. Точні умови перевірки — **`check-k8s.mjs`**.
|
|
220
|
+
|
|
221
|
+
```yaml
|
|
222
|
+
data:
|
|
223
|
+
HASURA_GRAPHQL_ENABLE_REMOTE_SCHEMA_PERMISSIONS: 'true'
|
|
224
|
+
```
|
|
225
|
+
|
|
217
226
|
## Kustomize: структура каталогів (`base` / overlays)
|
|
218
227
|
|
|
219
228
|
Трансформуй дерева **`**/k8s`**, щоб **винести спільне** через [Kustomize](https://kustomize.io/): один канонічний **`base`** і тонкі **overlays** для інших середовищ.
|
package/package.json
CHANGED
package/scripts/check-k8s.mjs
CHANGED
|
@@ -56,6 +56,11 @@
|
|
|
56
56
|
* Dockerfile — правило docker.mdc, скрипт check-docker.mjs.
|
|
57
57
|
*
|
|
58
58
|
* **Структура `HTTPRoute` для Hasura-Deployment:** звіряється канон 4 правил у **`spec.rules`** (редиректи **`<prefix>/ql`** і **`<prefix>/ql/`** на **`<prefix>/ql/console`** 302, **`PathPrefix <prefix>/ql`** + **URLRewrite** на **`/`**, окреме WebSocket-правило з **`RequestHeaderModifier`** remove **`Authorization`**). **Префікс параметризовано** (рядок перед **`/ql`** у першому Hasura-правилі). **Прив'язка** — за **`metadata.name`** у тому ж каталозі, що й **Deployment** з образом **`hasura/graphql-engine`** (див. k8s.mdc). **Додаткові правила** поверх канону дозволені.
|
|
59
|
+
*
|
|
60
|
+
* **ConfigMap для Hasura-Deployment:** якщо в `k8s/base/` є `configmap.yaml` і поруч Deployment з образом
|
|
61
|
+
* **`hasura/graphql-engine`**, то в `data` ConfigMap обов'язково має бути ключ
|
|
62
|
+
* **`HASURA_GRAPHQL_ENABLE_REMOTE_SCHEMA_PERMISSIONS`** зі значенням **`"true"`** (приймається булеве `true`
|
|
63
|
+
* або рядок `"true"`, без регістрової залежності).
|
|
59
64
|
*/
|
|
60
65
|
import { existsSync } from 'node:fs'
|
|
61
66
|
import { readFile, readdir, stat, unlink } from 'node:fs/promises'
|
|
@@ -1959,6 +1964,49 @@ export function isHasuraDeploymentManifest(manifest) {
|
|
|
1959
1964
|
return containerListHasHasuraImage(p.containers) || containerListHasHasuraImage(p.initContainers)
|
|
1960
1965
|
}
|
|
1961
1966
|
|
|
1967
|
+
/**
|
|
1968
|
+
* Обов'язковий ключ у **`data`** ConfigMap для Hasura-Deployment (узгоджено з k8s.mdc).
|
|
1969
|
+
*/
|
|
1970
|
+
export const HASURA_REMOTE_SCHEMA_PERMISSIONS_KEY = 'HASURA_GRAPHQL_ENABLE_REMOTE_SCHEMA_PERMISSIONS'
|
|
1971
|
+
|
|
1972
|
+
/**
|
|
1973
|
+
* Чи значення поля `data.<key>` у ConfigMap читається як логічне **true**.
|
|
1974
|
+
* ConfigMap у Kubernetes тримає значення як рядки, але в YAML часто пишуть без лапок —
|
|
1975
|
+
* тому приймаємо і булевий **true**, і рядок **"true"** (без регістрової залежності).
|
|
1976
|
+
* @param {unknown} v значення з `data[HASURA_REMOTE_SCHEMA_PERMISSIONS_KEY]`
|
|
1977
|
+
* @returns {boolean} true, якщо значення — `true` або рядок `'true'`
|
|
1978
|
+
*/
|
|
1979
|
+
function isConfigMapValueTrue(v) {
|
|
1980
|
+
if (v === true) return true
|
|
1981
|
+
if (typeof v === 'string' && v.trim().toLowerCase() === 'true') return true
|
|
1982
|
+
return false
|
|
1983
|
+
}
|
|
1984
|
+
|
|
1985
|
+
/**
|
|
1986
|
+
* Чи порушує ConfigMap вимогу щодо **`HASURA_GRAPHQL_ENABLE_REMOTE_SCHEMA_PERMISSIONS: "true"`** (k8s.mdc).
|
|
1987
|
+
* Перевірка застосовна, коли в тому ж каталозі є Hasura-Deployment (див. `isHasuraDeploymentManifest`).
|
|
1988
|
+
* @param {unknown} manifest корінь YAML-документа ConfigMap
|
|
1989
|
+
* @returns {string | null} текст порушення або null, якщо не ConfigMap / ключ є і значення `true`
|
|
1990
|
+
*/
|
|
1991
|
+
export function hasuraConfigMapRemoteSchemaPermissionsViolation(manifest) {
|
|
1992
|
+
if (manifest === null || manifest === undefined || typeof manifest !== 'object' || Array.isArray(manifest))
|
|
1993
|
+
return null
|
|
1994
|
+
const rec = /** @type {Record<string, unknown>} */ (manifest)
|
|
1995
|
+
if (rec.kind !== 'ConfigMap') return null
|
|
1996
|
+
const data = rec.data
|
|
1997
|
+
if (data === null || data === undefined || typeof data !== 'object' || Array.isArray(data)) {
|
|
1998
|
+
return `data.${HASURA_REMOTE_SCHEMA_PERMISSIONS_KEY}: додай ключ зі значенням "true" (Deployment з hasura/graphql-engine — див. k8s.mdc)`
|
|
1999
|
+
}
|
|
2000
|
+
const d = /** @type {Record<string, unknown>} */ (data)
|
|
2001
|
+
if (!Object.hasOwn(d, HASURA_REMOTE_SCHEMA_PERMISSIONS_KEY)) {
|
|
2002
|
+
return `data.${HASURA_REMOTE_SCHEMA_PERMISSIONS_KEY}: додай ключ зі значенням "true" (Deployment з hasura/graphql-engine — див. k8s.mdc)`
|
|
2003
|
+
}
|
|
2004
|
+
if (!isConfigMapValueTrue(d[HASURA_REMOTE_SCHEMA_PERMISSIONS_KEY])) {
|
|
2005
|
+
return `data.${HASURA_REMOTE_SCHEMA_PERMISSIONS_KEY}: значення має бути "true" (зараз: ${JSON.stringify(d[HASURA_REMOTE_SCHEMA_PERMISSIONS_KEY])}) (див. k8s.mdc)`
|
|
2006
|
+
}
|
|
2007
|
+
return null
|
|
2008
|
+
}
|
|
2009
|
+
|
|
1962
2010
|
const K8S_YAML_EXT_RE = /\.ya?ml$/iu
|
|
1963
2011
|
|
|
1964
2012
|
/**
|
|
@@ -3305,6 +3353,63 @@ async function validateConfigMapNameMatchesDeployment(root, yamlFilesAbs, fail,
|
|
|
3305
3353
|
}
|
|
3306
3354
|
}
|
|
3307
3355
|
|
|
3356
|
+
/**
|
|
3357
|
+
* Знаходить перший документ **ConfigMap** у файлі (з `metadata.name`).
|
|
3358
|
+
* @param {string} absPath абсолютний шлях до YAML-файлу
|
|
3359
|
+
* @returns {Promise<Record<string, unknown> | null>} об'єкт ConfigMap або null
|
|
3360
|
+
*/
|
|
3361
|
+
async function readFirstConfigMapDoc(absPath) {
|
|
3362
|
+
let raw
|
|
3363
|
+
try {
|
|
3364
|
+
raw = await readFile(absPath, 'utf8')
|
|
3365
|
+
} catch {
|
|
3366
|
+
return null
|
|
3367
|
+
}
|
|
3368
|
+
let docs
|
|
3369
|
+
try {
|
|
3370
|
+
docs = parseAllDocuments(raw)
|
|
3371
|
+
} catch {
|
|
3372
|
+
return null
|
|
3373
|
+
}
|
|
3374
|
+
for (const doc of docs) {
|
|
3375
|
+
if (doc.errors.length > 0) continue
|
|
3376
|
+
const obj = doc.toJSON()
|
|
3377
|
+
if (obj !== null && typeof obj === 'object' && !Array.isArray(obj)) {
|
|
3378
|
+
const rec = /** @type {Record<string, unknown>} */ (obj)
|
|
3379
|
+
if (rec.kind === 'ConfigMap') return rec
|
|
3380
|
+
}
|
|
3381
|
+
}
|
|
3382
|
+
return null
|
|
3383
|
+
}
|
|
3384
|
+
|
|
3385
|
+
/**
|
|
3386
|
+
* Для кожного `k8s/base/configmap.yaml`, у каталозі якого поруч є Hasura-Deployment,
|
|
3387
|
+
* вимагає у `data` ключ **`HASURA_GRAPHQL_ENABLE_REMOTE_SCHEMA_PERMISSIONS`** зі значенням **`"true"`** (k8s.mdc).
|
|
3388
|
+
* @param {string} root корінь репозиторію
|
|
3389
|
+
* @param {string[]} yamlFilesAbs yaml під k8s
|
|
3390
|
+
* @param {(msg: string) => void} fail callback при помилці
|
|
3391
|
+
* @param {(msg: string) => void} passFn callback при успіху
|
|
3392
|
+
*/
|
|
3393
|
+
async function validateHasuraConfigMapRemoteSchemaPermissions(root, yamlFilesAbs, fail, passFn) {
|
|
3394
|
+
const cmFiles = yamlFilesAbs.filter(abs => {
|
|
3395
|
+
const rel = relative(root, abs).replaceAll('\\', '/')
|
|
3396
|
+
return CONFIGMAP_BASE_PATH_RE.test(`/${rel}`) || rel === 'k8s/base/configmap.yaml'
|
|
3397
|
+
})
|
|
3398
|
+
for (const cmAbs of cmFiles) {
|
|
3399
|
+
const rel = relative(root, cmAbs).replaceAll('\\', '/') || cmAbs
|
|
3400
|
+
const deployment = await findDeploymentDocInDir(dirname(cmAbs))
|
|
3401
|
+
if (deployment === null || !isHasuraDeploymentManifest(deployment)) continue
|
|
3402
|
+
const cm = await readFirstConfigMapDoc(cmAbs)
|
|
3403
|
+
if (cm === null) continue
|
|
3404
|
+
const violation = hasuraConfigMapRemoteSchemaPermissionsViolation(cm)
|
|
3405
|
+
if (violation !== null) {
|
|
3406
|
+
fail(`${rel}: ${violation}`)
|
|
3407
|
+
} else {
|
|
3408
|
+
passFn(`${rel}: ${HASURA_REMOTE_SCHEMA_PERMISSIONS_KEY}="true" для Hasura-Deployment (k8s.mdc)`)
|
|
3409
|
+
}
|
|
3410
|
+
}
|
|
3411
|
+
}
|
|
3412
|
+
|
|
3308
3413
|
/**
|
|
3309
3414
|
* Перевіряє відповідність проєкту правилам k8s.mdc.
|
|
3310
3415
|
* @returns {Promise<number>} 0 — все OK, 1 — є проблеми
|
|
@@ -3348,5 +3453,7 @@ export async function check() {
|
|
|
3348
3453
|
|
|
3349
3454
|
await validateConfigMapNameMatchesDeployment(root, yamlFiles, fail, pass)
|
|
3350
3455
|
|
|
3456
|
+
await validateHasuraConfigMapRemoteSchemaPermissions(root, yamlFiles, fail, pass)
|
|
3457
|
+
|
|
3351
3458
|
return reporter.getExitCode()
|
|
3352
3459
|
}
|