chore: commit all changes
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
terraform {
|
terraform {
|
||||||
required_providers {
|
required_providers {
|
||||||
nubes = {
|
nubes = {
|
||||||
source = "terra.k8c.ru/nubes-test/nubes"
|
source = "registry.kube5s.ru/nubes-test/nubes"
|
||||||
version = "5.0.64"
|
version = "5.1.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -22,6 +22,10 @@ variable "realm" {
|
|||||||
sensitive = true
|
sensitive = true
|
||||||
description = "resource_realm parameter for nubes_postgres resource"
|
description = "resource_realm parameter for nubes_postgres resource"
|
||||||
}
|
}
|
||||||
|
variable "s3_user_uid" {
|
||||||
|
type = string
|
||||||
|
description = "S3 user UUID"
|
||||||
|
}
|
||||||
|
|
||||||
provider "nubes" {
|
provider "nubes" {
|
||||||
api_token = var.api_token
|
api_token = var.api_token
|
||||||
|
|||||||
@@ -1,50 +1,48 @@
|
|||||||
resource "nubes_postgres" "npg" {
|
resource "nubes_postgres" "npg" {
|
||||||
resource_name = "pgtst01"
|
resource_name = "pgtst01"
|
||||||
|
|
||||||
startup_configuration = jsonencode({
|
startup_configuration = {
|
||||||
resourceRealm = var.realm
|
resource_realm = var.realm
|
||||||
})
|
|
||||||
|
|
||||||
cluster_configuration = jsonencode({
|
|
||||||
cpu = "500"
|
|
||||||
memory = "512"
|
|
||||||
replicas = "1"
|
|
||||||
disk = "10"
|
|
||||||
})
|
|
||||||
|
|
||||||
access_configuration = jsonencode({
|
|
||||||
masterIpSpace = "no-needed"
|
|
||||||
masterAccessList = ["10.0.0.0/8"]
|
|
||||||
slaveIpSpace = "no-needed"
|
|
||||||
slaveAccessList = []
|
|
||||||
})
|
|
||||||
|
|
||||||
postgres_configuration = jsonencode({
|
|
||||||
version = "17"
|
|
||||||
sslRequired = true
|
|
||||||
poolerMaster = false
|
|
||||||
poolerSlave = false
|
|
||||||
})
|
|
||||||
|
|
||||||
postgres_conf = jsonencode([
|
|
||||||
{
|
|
||||||
paramName = "log_connections"
|
|
||||||
paramValue = "''"
|
|
||||||
}
|
}
|
||||||
])
|
|
||||||
|
|
||||||
backup_configuration = jsonencode({
|
cluster_configuration = {
|
||||||
s3Uid = var.s3_uid
|
cpu = 500
|
||||||
retain = "14"
|
memory = 512
|
||||||
|
replicas = 1
|
||||||
|
disk = 10
|
||||||
|
}
|
||||||
|
|
||||||
|
access_configuration = {
|
||||||
|
master_ip_space = "no-needed"
|
||||||
|
master_access_list = jsonencode(["10.0.0.0/8"])
|
||||||
|
slave_ip_space = "no-needed"
|
||||||
|
slave_access_list = jsonencode([])
|
||||||
|
}
|
||||||
|
|
||||||
|
postgres_configuration = {
|
||||||
|
version = "17"
|
||||||
|
ssl_required = true
|
||||||
|
pooler_master = false
|
||||||
|
pooler_slave = false
|
||||||
|
}
|
||||||
|
|
||||||
|
postgres_conf = jsonencode([{
|
||||||
|
param_name = "log_connections"
|
||||||
|
param_value = ""
|
||||||
|
}])
|
||||||
|
|
||||||
|
backup_configuration = {
|
||||||
|
s3_uid = var.s3_uid
|
||||||
|
retain = 14
|
||||||
schedule = "0 0 * * *"
|
schedule = "0 0 * * *"
|
||||||
})
|
}
|
||||||
|
|
||||||
autoscale_configuration = jsonencode({
|
autoscale_configuration = {
|
||||||
enabled = false
|
enabled = false
|
||||||
schedule = "0"
|
schedule = 0
|
||||||
percent = "10"
|
percent = 10
|
||||||
quota = "100"
|
quota = 100
|
||||||
})
|
}
|
||||||
|
|
||||||
operation_timeout = "11m"
|
operation_timeout = "11m"
|
||||||
adopt_existing_on_create = true
|
adopt_existing_on_create = true
|
||||||
|
|||||||
@@ -8,22 +8,22 @@ resource "nubes_postgres_user" "pg_user_0" {
|
|||||||
adopt_existing_on_create = true
|
adopt_existing_on_create = true
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "nubes_postgres_user" "pg_user_1" {
|
# resource "nubes_postgres_user" "pg_user_1" {
|
||||||
postgres_id = nubes_postgres.npg.id
|
# postgres_id = nubes_postgres.npg.id
|
||||||
username = "user1"
|
# username = "user1"
|
||||||
role = "ddl_user"
|
# role = "ddl_user"
|
||||||
adopt_existing_on_create = true
|
# adopt_existing_on_create = true
|
||||||
}
|
# }
|
||||||
|
|
||||||
# =============================================================================
|
# # =============================================================================
|
||||||
# PostgreSQL — базы данных (3 шт.)
|
# # PostgreSQL — базы данных (3 шт.)
|
||||||
# =============================================================================
|
# # =============================================================================
|
||||||
resource "nubes_postgres_database" "pg_db_1" {
|
# resource "nubes_postgres_database" "pg_db_1" {
|
||||||
postgres_id = nubes_postgres.npg.id
|
# postgres_id = nubes_postgres.npg.id
|
||||||
db_name = "dbapp1"
|
# db_name = "dbapp1"
|
||||||
db_owner = nubes_postgres_user.pg_user_1.username
|
# db_owner = nubes_postgres_user.pg_user_1.username
|
||||||
adopt_existing_on_create = true
|
# adopt_existing_on_create = true
|
||||||
}
|
# }
|
||||||
|
|
||||||
resource "nubes_postgres_database" "pg_db_2" {
|
resource "nubes_postgres_database" "pg_db_2" {
|
||||||
postgres_id = nubes_postgres.npg.id
|
postgres_id = nubes_postgres.npg.id
|
||||||
@@ -32,9 +32,18 @@ resource "nubes_postgres_database" "pg_db_2" {
|
|||||||
adopt_existing_on_create = true
|
adopt_existing_on_create = true
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "nubes_postgres_database" "pg_db_3" {
|
# resource "nubes_postgres_database" "pg_db_3" {
|
||||||
postgres_id = nubes_postgres.npg.id
|
# postgres_id = nubes_postgres.npg.id
|
||||||
db_name = "dbapp3"
|
# db_name = "dbapp3"
|
||||||
db_owner = nubes_postgres_user.pg_user_1.username
|
# db_owner = nubes_postgres_user.pg_user_1.username
|
||||||
|
# adopt_existing_on_create = true
|
||||||
|
# }
|
||||||
|
|
||||||
|
# S3 bucket — замени "buck0" на своё имя везде ниже
|
||||||
|
resource "nubes_s3bucket" "bukka0" { # ← замени buck0 на своё имя ресурса
|
||||||
|
resource_name = "btst" # ← замени buck0 на своё имя ресурса
|
||||||
|
#s3_user_uid = "naeel-s3"
|
||||||
|
s3_user_uid = var.s3_user_uid
|
||||||
|
bucket_name = "buck01" # ← замени buck0 на своё имя бакета
|
||||||
adopt_existing_on_create = true
|
adopt_existing_on_create = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ TOKEN_FILE="secrets/dev.token"
|
|||||||
VERSION="3.1.0"
|
VERSION="3.1.0"
|
||||||
|
|
||||||
# Registry/S3 settings
|
# Registry/S3 settings
|
||||||
REGISTRY_HOST="terra.k8c.ru"
|
REGISTRY_HOST="registry.kube5s.ru"
|
||||||
REGISTRY_HOSTNAME="terra.k8c.ru"
|
REGISTRY_HOSTNAME="registry.kube5s.ru"
|
||||||
NAMESPACE="nubes-dev"
|
NAMESPACE="nubes-dev"
|
||||||
PROVIDER_NAME="nubes"
|
PROVIDER_NAME="nubes"
|
||||||
S3_BUCKET="terraform-registry"
|
S3_BUCKET="terraform-registry"
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ TOKEN_FILE="secrets/prod.token"
|
|||||||
VERSION="2.1.0"
|
VERSION="2.1.0"
|
||||||
|
|
||||||
# Registry/S3 settings
|
# Registry/S3 settings
|
||||||
REGISTRY_HOST="terra.k8c.ru"
|
REGISTRY_HOST="registry.kube5s.ru"
|
||||||
REGISTRY_HOSTNAME="terra.k8c.ru"
|
REGISTRY_HOSTNAME="registry.kube5s.ru"
|
||||||
NAMESPACE="nubes-prod"
|
NAMESPACE="nubes-prod"
|
||||||
PROVIDER_NAME="nubes"
|
PROVIDER_NAME="nubes"
|
||||||
S3_BUCKET="terraform-registry"
|
S3_BUCKET="terraform-registry"
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ NUBES_API_ENDPOINT="https://lk-api-gateway-test.ngcloud.ru/api/v1/svc"
|
|||||||
TOKEN_FILE="secrets/test.token"
|
TOKEN_FILE="secrets/test.token"
|
||||||
|
|
||||||
# Version
|
# Version
|
||||||
VERSION="5.1.0"
|
VERSION="5.1.2"
|
||||||
|
|
||||||
# Docs generation — ONLY from docs_gen/<stand>/ (never from docs/)
|
# Docs generation — ONLY from docs_gen/<stand>/ (never from docs/)
|
||||||
DOCS_GEN_DIR="provider/docs_gen/test"
|
DOCS_GEN_DIR="provider/docs_gen/test"
|
||||||
|
|
||||||
# Registry/S3 settings
|
# Registry/S3 settings
|
||||||
REGISTRY_HOST="terra.k8c.ru"
|
REGISTRY_HOST="registry.kube5s.ru"
|
||||||
REGISTRY_HOSTNAME="terra.k8c.ru"
|
REGISTRY_HOSTNAME="registry.kube5s.ru"
|
||||||
NAMESPACE="nubes-test"
|
NAMESPACE="nubes-test"
|
||||||
PROVIDER_NAME="nubes"
|
PROVIDER_NAME="nubes"
|
||||||
S3_BUCKET="terraform-registry"
|
S3_BUCKET="terraform-registry"
|
||||||
|
|||||||
@@ -305,6 +305,10 @@ func NestedJSONExpr(p types.Param, varPrefix string) string {
|
|||||||
for _, sp := range p.SubParams {
|
for _, sp := range p.SubParams {
|
||||||
field := varName + "." + ToCamel(sp.Code)
|
field := varName + "." + ToCamel(sp.Code)
|
||||||
var valExpr string
|
var valExpr string
|
||||||
|
// IsJson проверяем до Type — для json полей Type="string", но сериализация другая.
|
||||||
|
if sp.IsJson {
|
||||||
|
valExpr = fmt.Sprintf(`%s.ValueString()`, field)
|
||||||
|
} else {
|
||||||
switch strings.ToLower(sp.Type) {
|
switch strings.ToLower(sp.Type) {
|
||||||
case "bool":
|
case "bool":
|
||||||
valExpr = fmt.Sprintf(`fmt.Sprintf("%%v", %s.ValueBool())`, field)
|
valExpr = fmt.Sprintf(`fmt.Sprintf("%%v", %s.ValueBool())`, field)
|
||||||
@@ -313,6 +317,7 @@ func NestedJSONExpr(p types.Param, varPrefix string) string {
|
|||||||
default:
|
default:
|
||||||
valExpr = fmt.Sprintf(`fmt.Sprintf("\"%%s\"", %s.ValueString())`, field)
|
valExpr = fmt.Sprintf(`fmt.Sprintf("\"%%s\"", %s.ValueString())`, field)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
pairs = append(pairs, fmt.Sprintf(`"%s": %s`, sp.Code, valExpr))
|
pairs = append(pairs, fmt.Sprintf(`"%s": %s`, sp.Code, valExpr))
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("resources_core.BuildJSON(map[string]string{%s})", strings.Join(pairs, ", "))
|
return fmt.Sprintf("resources_core.BuildJSON(map[string]string{%s})", strings.Join(pairs, ", "))
|
||||||
|
|||||||
@@ -0,0 +1,134 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""LLM-генератор документации для Nubes Terraform Provider.
|
||||||
|
Читает YAML-спеки, отправляет в LLM, сохраняет Markdown.
|
||||||
|
"""
|
||||||
|
import json, os, sys, time, yaml
|
||||||
|
from pathlib import Path
|
||||||
|
from urllib.request import Request, urlopen
|
||||||
|
from urllib.error import URLError
|
||||||
|
|
||||||
|
API_URL = "https://api.aillm.ru/v1/chat/completions"
|
||||||
|
API_KEY = "sk-ucI5YvOticoOQ9Kuj5K9mQ"
|
||||||
|
MODEL = "gpt-oss-120b"
|
||||||
|
|
||||||
|
PROMPT = """Ты — генератор документации Terraform-провайдера Nubes Cloud.
|
||||||
|
Отвечай ТОЛЬКО Markdown-кодом. Никаких пояснений до или после.
|
||||||
|
|
||||||
|
⛔ ЖЁСТКИЕ ПРАВИЛА (нарушать нельзя):
|
||||||
|
|
||||||
|
1. НЕ ВЫДУМЫВАЙ параметры. Только те, что есть в YAML.
|
||||||
|
Если у параметра нет description — напиши "—".
|
||||||
|
НИКОГДА не придумывай password, role, encoding и т.п.
|
||||||
|
|
||||||
|
2. Action-операции. ТОЛЬКО redeploy включается в документацию.
|
||||||
|
restart, recovery, reconcile — ИСКЛЮЧИТЬ.
|
||||||
|
|
||||||
|
3. Subresource-операции. Каждый subresource → отдельная секция.
|
||||||
|
Имя ресурса: nubes_{service}_{subresource}.
|
||||||
|
|
||||||
|
4. Lifecycle. suspend_on_destroy=true → "terraform destroy = Suspend".
|
||||||
|
adopt_existing_on_create → "terraform apply может подхватить существующий".
|
||||||
|
|
||||||
|
5. Outputs. Все поля из outputs.params. vault_secrets помечать как 🔒.
|
||||||
|
|
||||||
|
6. MAN. Если service_man есть — вставить как есть в секцию ## MAN.
|
||||||
|
|
||||||
|
7. ВЛОЖЕННЫЕ ПАРАМЕТРЫ (map-fixed/array-map-fixed).
|
||||||
|
Для каждого map-fixed параметра — показывать ВСЕ его sub_params как вложенную таблицу.
|
||||||
|
Для array-map-fixed — показывать структуру элемента.
|
||||||
|
Пример:
|
||||||
|
### clusterConfiguration (map-fixed)
|
||||||
|
| Параметр | Тип | Обязательный | По умолчанию | Описание |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| cpu | integer > 0 | да | 500 | Количество CPU в милликорах |
|
||||||
|
| memory | integer > 0 | да | 512 | Память в MB |
|
||||||
|
|
||||||
|
ФОРМАТ:
|
||||||
|
# Resource nubes_{name}
|
||||||
|
## MAN (если есть)
|
||||||
|
## Instance Operations (таблица)
|
||||||
|
## Create Parameters (таблица — для каждого map-fixed показывать sub_params)
|
||||||
|
## Modify Parameters (таблица)
|
||||||
|
## Subresources (таблица по каждому)
|
||||||
|
## Lifecycle
|
||||||
|
## Outputs (таблица)
|
||||||
|
|
||||||
|
YAML-спек:
|
||||||
|
```yaml
|
||||||
|
{yaml_content}
|
||||||
|
```"""
|
||||||
|
|
||||||
|
def call_llm(prompt_text: str) -> str:
|
||||||
|
data = json.dumps({
|
||||||
|
"model": MODEL,
|
||||||
|
"messages": [{"role": "user", "content": prompt_text}],
|
||||||
|
"temperature": 0.1,
|
||||||
|
"max_tokens": 8192,
|
||||||
|
}).encode()
|
||||||
|
req = Request(API_URL, data=data, headers={
|
||||||
|
"Authorization": f"Bearer {API_KEY}",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
})
|
||||||
|
for attempt in range(3):
|
||||||
|
try:
|
||||||
|
with urlopen(req, timeout=120) as resp:
|
||||||
|
result = json.loads(resp.read())
|
||||||
|
return result["choices"][0]["message"]["content"]
|
||||||
|
except Exception as e:
|
||||||
|
print(f" retry {attempt+1}/3: {e}", file=sys.stderr)
|
||||||
|
time.sleep(5)
|
||||||
|
raise RuntimeError("LLM failed after 3 retries")
|
||||||
|
|
||||||
|
def strip_service_man(yaml_text: str) -> str:
|
||||||
|
"""Убирает service_man (HTML-руководство) из YAML для сокращения токенов."""
|
||||||
|
lines = yaml_text.split('\n')
|
||||||
|
out = []
|
||||||
|
skip = False
|
||||||
|
for line in lines:
|
||||||
|
if line.strip().startswith('service_man:'):
|
||||||
|
out.append('service_man: "" # omitted for LLM token limit')
|
||||||
|
skip = True
|
||||||
|
continue
|
||||||
|
if skip:
|
||||||
|
# service_man может быть многострочным (HTML с отступами)
|
||||||
|
if line and line[0] not in (' ', '\t') and ':' in line:
|
||||||
|
skip = False
|
||||||
|
out.append(line)
|
||||||
|
continue
|
||||||
|
out.append(line)
|
||||||
|
return '\n'.join(out)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
yaml_dir = sys.argv[1] if len(sys.argv) > 1 else "generated/test/resources_yaml"
|
||||||
|
docs_dir = sys.argv[2] if len(sys.argv) > 2 else "generated/test/docs_llm"
|
||||||
|
|
||||||
|
os.makedirs(docs_dir, exist_ok=True)
|
||||||
|
yamls = sorted(Path(yaml_dir).glob("*.yaml"))
|
||||||
|
print(f"Processing {len(yamls)} services...")
|
||||||
|
|
||||||
|
failed = []
|
||||||
|
for i, yf in enumerate(yamls):
|
||||||
|
svc_name = yf.stem.split("_", 1)[1] if "_" in yf.stem else yf.stem
|
||||||
|
print(f" [{i+1}/{len(yamls)}] {svc_name}...", end=" ", flush=True)
|
||||||
|
|
||||||
|
yaml_text = strip_service_man(yf.read_text())
|
||||||
|
prompt = PROMPT.replace("{yaml_content}", yaml_text)
|
||||||
|
|
||||||
|
try:
|
||||||
|
md = call_llm(prompt)
|
||||||
|
out = Path(docs_dir) / f"{yf.stem}.md"
|
||||||
|
out.write_text(md)
|
||||||
|
print("OK")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"FAILED: {e}")
|
||||||
|
failed.append(svc_name)
|
||||||
|
|
||||||
|
time.sleep(2) # rate limit
|
||||||
|
|
||||||
|
if failed:
|
||||||
|
print(f"\nFailed ({len(failed)}): {', '.join(failed)}")
|
||||||
|
else:
|
||||||
|
print(f"\nAll {len(yamls)} OK")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
Ntazetdinov@nubes.ru
|
||||||
|
https://api.aillm.ru/
|
||||||
|
sk-ucI5YvOticoOQ9Kuj5K9mQ
|
||||||
|
|
||||||
|
|
||||||
|
Deepseek flash
|
||||||
|
sk-78ec529c1eba4ba69995091046c9fa33
|
||||||
|
|
||||||
|
cicd
|
||||||
|
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoLWFwaSIsInN1YiI6IjAxOTllMzI1LTFjZGYtN2NkYS05MzE5LWU1MzAyYTg1ZTI5MSIsImV4cCI6MTc5ODI3MTUyMSwiaWF0IjoxNzgyNzE5NTIxLCJqdGkiOiI5NjQ2MDlmYy05ZGZiLTQ1YjMtYjk0NS1lNmE0NmUzMTA0MzQiLCJhdXRoX3RpbWUiOjAsInR5cCI6IiIsImF6cCI6IiIsInNlc3Npb25fc3RhdGUiOiIiLCJhY3IiOiIiLCJhbGxvd2VkLW9yaWdpbnMiOm51bGwsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6bnVsbH0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpudWxsfX0sInNjb3BlIjoiIiwic2lkIjoiIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoiIiwiQ2xpZW50SUQiOiJXWjAxMzI1IiwiY29tcGFueV9pZCI6IjNlNjRhYWM2LWRjZmMtNDA4Mi04OGRjLWRhMTljODY1NTVhNSIsImNvbXBhbnlfbmFtZSI6ItCi0LXRgdGCIiwidG9rZW5fdHlwZSI6InRlY2giLCJpZHBfdXNyX3VpZCI6IjAxOTllMzI1LTFjZGYtN2NkYS05MzE5LWU1MzAyYTg1ZTI5MSIsImxvZ2luIjoidGF6ZXRAbmFyb2QucnUiLCJmaXJzdG5hbWUiOiLQndCw0LjQu9GMIiwibWlkZGxlbmFtZSI6ItCk0LDRgNC40YHQvtCy0LjRhyDQotC10YHRgtC-0LLQsNGPINGD0YfQtdGC0LrQsCIsImxhc3RuYW1lIjoi0KLQsNC30LXRgtC00LjQvdC-0LIiLCJncm91cHMiOm51bGwsInByZWZlcnJlZF91c2VybmFtZSI6IiIsImdpdmVuX25hbWUiOiIiLCJmYW1pbHlfbmFtZSI6IiIsImVtYWlsIjoidGF6ZXRAbmFyb2QucnUifQ.T2cSkKGlorUTr_ICpInwrZZ2Sqk_D-RHpibrj1VI-7Bg7CPvIKJ7n1QF9bJc9uqWH9cwQczrNsA8sROU3lnqUaa88hl_rMfP7UM_u8X_iG-_pKYD8tsckmmcos6keh2I9muSZ9Viy9LvLCZv3fY6nzMp2YT-KCQh-EDGZPgHSAToWs1uqiaKi99K-OcqckvaFNUsYbpLPVfnD_6UnDDKUmPjP4Ib24R4Z5qlmwUAxmgC6BfUcuqgk-2Mdj37ulWvdlBLd9ZoJv4jAvRffzclv2w-Qa8p3BEooC8wlZjTC3PU-ULR-Cd_N61Y31lkd953kkKE3_yGIQCbwCPYus1TiA
|
||||||
|
|
||||||
|
gitea
|
||||||
|
1999993c70d97cc588cca420e59ac45d5290b734
|
||||||
Reference in New Issue
Block a user