Files
tf_provider/docs/20_discovery/postgres-service.md
T

9.4 KiB

PostgreSQL Service Analysis & Implementation Plan

Date: 2026-01-27
Artifacts Analyzed: pg.har (Traffic), pg.html (Form Schema)

1. Service Overview

PostgreSQL "Database as a Service" in Nubes.

  • Service Type: Stateful Application
  • Lifecycle Constraint: Strict Quarantine (14 days).
    • Like the VM resource, this service cannot be immediately deleted.
    • Attempting to delete an active instance returns: Услуга ПРОМ. Не в состоянии ПРИОСТАНОВЛЕНА более 14 дней.
    • Implication for Terraform: The Delete operation in the provider must likely perform a Suspend instead, or Terraform will require the user to manually suspend and wait 14 days before a successful destroy (which is bad UX).
    • Strategy Reference: Similar to nubes_vm, destroy should trigger suspend.

2. Resource Parameter Mapping

Extracted from pg.html (labels) and pg.har (values/IDs).

Terraform Argument Label (UI) API Key (instanceOperationCfsParams) Type ID Notes
nodes_count Количество узлов resourceInstances Int 80
cpu Квота ядра пода (mili) resourceCPU Int 81 500 = 0.5 CPU
ram Квота памяти пода (MB) resourceMemory Int 82
disk_size Размер диска для базы данных (GB) resourceDisk Int 83
version Версия PostgreSQL appVersion String 310 "17", "16", etc.
enable_external_master Выделение белого ip для master ноды needExternalAddressMaster Bool 145
ip_space_master Имя ipSpace для публикации VIP master ipSpaceNameMaster String 102 Req if external master=true
enable_external_slave Выделение белого ip для slave ноды needExternalAddressSlave Bool 146
ip_space_slave Имя ipSpace для публикации VIP slave ipSpaceNameSlave String --- Req if external slave=true (ID mismatch in artifacts, verify)
backup_schedule ext_BACKUP_SCHEDULE ext_BACKUP_SCHEDULE String 265 Cron format
backup_retention ext_BACKUP_NUM_TO_RETAIN ext_BACKUP_NUM_TO_RETAIN Int 266
config_json jsonParameters jsonParameters JSON 311 Postgres runtime config
enable_pooler_master enablePgPoolerMaster enablePgPoolerMaster Bool --- ID needs verification
enable_pooler_slave enablePgPoolerSlave enablePgPoolerSlave Bool --- ID needs verification
allow_no_ssl allowNoSSL allowNoSSL Bool --- ID needs verification
dns_name (Inferred from HAR) dnsRecord (Likely) String 102 In HAR k8s-3... was sent as ID 102, which matches ipSpaceNameMaster or DNS? Needs check.

Note: Some IDs (Pooler, SSL, IP Space Slave) were visible in HTML but their submission IDs need confirmation from a full submission log or deduction.

Mismatches/Detailed Logic

  • ID 102: In HAR, svcOperationCfsParamId: 102 sent value k8s-3.ext.nubes.ru. This looks like a DNS name or IP Space name. HTML label is "Имя ipSpace...".
  • ID 23: instanceOperationUid? No, HAR shows paramId 23 with UUID value. Check if this is account_id or similar.

3. Implementation Plan

Resource Schema (nubes_postgres)

resource "nubes_postgres" "db" {
  organization_uuid = "..."
  vdc_uuid          = "..." # If applicable, or just organization context
  
  name          = "my-pg"
  version       = "17"
  cpu           = 500
  ram           = 512
  disk_gb       = 10
  nodes         = 1
  
  # Network
  external_master = false
  # ...
  
  # Backup
  backup_schedule  = "0 0 * * *"
  backup_retention = 7
  
  # Advanced
  config = jsonencode({
    "max_connections" = 100
  })
}

Lifecycle Logic

  • Create: POST /instanceOperationCfsParams with mapped IDs.
  • Read: GET /instances/{id} -> Parse cfsParams from instanceConfig.
  • Delete:
    • Check explainedStatus.
    • If active: Call suspend. State remains in Terraform (or marked as tainted? No, usually we just update state to show suspended or remove if we consider suspend=deleted).
    • Given the "quarantine", Terraform destroy cannot fully remove the resource.
    • Decision: destroy will execute suspend. The resource will arguably still exist in the cloud. Terraform state should probably be removed to simulate "deletion" from the Infrastructure as Code perspective, alerting the user via logs that actual deletion requires 14 days wait.

4. Next Steps

  1. Create internal/provider/postgres_resource.go (skeleton exists?).
  2. Implement Create method with correct param IDs.
  3. specific testing of the Suspend workflow.

5. Technical Implementation Details (For AI Agent)

A. API Request Pattern

Analysis of pg.har reveals that parameters are NOT sent in a single JSON body. The client sends multiple sequential POST requests to /api/v1/index.cfm/instanceOperationCfsParams.

Payload Schema per Parameter:

{
  "paramValue": "1",          // The value (stringified)
  "instanceOperationUid": "...", // The operation ID (from the create instance response)
  "svcOperationCfsParamId": 80   // The specific ID mapped above
}

Implementation Strategy: The provider must loop through the defined parameters and make individual API calls for each one using the client.CreateInstanceParam (or similar existing method).

B. Code References

  • Lifecycle Logic: See internal/provider/vm_resource.go. This resource implements the "Suspend instead of Delete" logic required for quarantine-constrained resources.
  • API Client: Check internal/provider/client_impl.go for SendCfsParam or similar helpers.

C. Implementation Order (User Request)

PRIORITY 1: Documentation First The user wants to visualize parameters on the documentation site before code implementation.

  1. Create Documentation File:
    • Path: docs/registry/resources/postgres.md
    • Content: Description of the resource, schema table (Inputs determined in Section 2), and an example usage block.
  2. Update Navigation:
    • File: mkdocs.yml
    • Action: Add - Postgres: resources/postgres.md under Resources.
  3. Review: Ask user to check the visual representation.
  4. Codegen: Only then proceed to Go implementation.

6. Live Instance Analysis (2026-01-27)

User provided a full text dump of a running PostgreSQL instance (test-org-pg-1769262059).

Key Findings:

  1. Quarantine Confirmation:

    • Operation Log: delete failed with "Услуга ПРОМ. Не в состоянии ПРИОСТАНОВЛЕНА более 14 дней".
    • This confirms terraform destroy MUST call suspend and remove state, warning the user.
  2. Sensitive Outputs (Credentials):

    • adminUser: postgres
    • adminPass: (Provided in plain text in UI/API response)
    • standbyUser / standbyPass: For HA configurations.
  3. Connection Info:

    • internalConnect.master: internal K8s DNS (e.g., postgresqlk8s-master...svc.).
    • externalConnect: JSON object with master and slave keys, each containing ip, fqdn, uuid, isExternal.
  4. Dependencies:

    • Explicit dependency on an S3 Bucket (s3Uid: 6d6061cb-...).
    • UI shows: "Экземпляр зависит от: S3 Object Storage".
    • Implication: The Terraform resource likely needs an s3_bucket_id input argument.
  5. Constraints:

    • Disk Shrink Forbidden: Operation log shows error "ERROR | Ресурсы под Disk меньше чем в текущем экземпляре".
    • Terraform validation must prevent reducing disk_size.
  6. New Parameters Identified:

    • resourceRealm: k8s-3.ext.nubes.ru (Likely corresponds to ID 102 inferred earlier).
    • monitoring: Contains Grafana URL.

    7. API Diff Check (2026-02-18)

    Based on service metadata for Postgres (svcId 90) across prod/test/dev.

    Operations

    • prod: create, delete, modify, recovery, restart, resume, suspend
    • test/dev: all prod ops plus create_user, delete_user, create_database, delete_database

    Input Params (operation-level)

    • create: identical param set across prod/test/dev (21 params)
    • modify/delete/restart/resume/suspend: identical across prod/test/dev
    • recovery: prod missing resourceCPU, resourceDisk, resourceInstances, resourceMemory, resourceRealm compared to test/dev

    Outputs

    • Output fields are not declared in service metadata. Only visible on instance state (state_out, state_params).

    8. YAML Generator Check (service_params_gen)

    Generator reads service metadata via:

    • /index.cfm?endpoint=/services/{svcId}
    • /index.cfm?endpoint=/serviceOperation/{svcOperationId}

    Limitations found:

    • Only collects params for create and modify operations.
    • Does not include create_user, delete_user, create_database, delete_database even when present in API (test/dev).
    • Outputs are hardcoded defaults, not pulled from API.