infra/.planning/codebase/CONVENTIONS.md
2026-02-23 20:54:27 +00:00

8.2 KiB

Coding Conventions

Analysis Date: 2026-02-23

Naming Patterns

Terraform Files:

  • main.tf - Primary resource definitions and module calls
  • terragrunt.hcl - Stack-specific Terragrunt configuration
  • variables.tf - Variable declarations for a stack
  • providers.tf - Generated by Terragrunt root terragrunt.hcl
  • backend.tf - Generated by Terragrunt for state backend configuration

Terraform Variables:

  • snake_case for variable names: var.tls_secret_name, var.dbaas_root_password
  • snake_case for resource names: resource "kubernetes_namespace" "nextcloud"
  • snake_case for local values: local.tiers
  • UPPERCASE for environment-like globals in shell: KUBECONFIG_PATH, PASS_COUNT

Resource/Module Names:

  • kebab-case for Kubernetes resources: nextcloud, whiteboard, kms-web-page
  • Leading underscore for prefixed resource names (internal/private pattern): resource names with underscores are module-internal
  • Descriptive names matching functionality: kubernetes_namespace, kubernetes_deployment, helm_release

Shell Functions:

  • snake_case for function names: parse_args(), count_lines(), check_nodes()
  • CamelCase for utility color variables: RED, GREEN, YELLOW, BLUE, BOLD, NC

Go Package/Test Names:

  • Package-level test functions: TestContainsVideoMarkers(), TestIsDirectVideoContentType()
  • Table-driven test pattern with struct fields: name, body, ct, want

Code Style

Terraform Formatting:

  • Use terraform fmt -recursive for consistent formatting
  • No explicit linter/formatter config file (tflint/terraform-lint not present)
  • Indentation: 2 spaces (standard Terraform convention)
  • Multi-line strings use heredoc syntax: <<EOT ... EOT for YAML/config blocks

Bash Script Style:

  • Shebang: #!/usr/bin/env bash
  • Safety flags: set -euo pipefail (exit on error, undefined vars, pipe failures)
  • Comments use # --- separator for section dividers
  • Comments use # --- for grouping related variables/functions
  • One-liner functions defined as: function_name() { [[ condition ]] && action; }
  • Multiline functions use explicit function body with local keyword for variables

Terraform Style:

  • Comments for major sections use # =============================================================================
  • Comments for subsections use # --------- -------
  • Inline comments explain why, not what: # anything secret is fine (explaining arbitrary choice)
  • Module calls include comments above describing purpose: # --- Core ---, # --- dbaas ---

Import Organization

Terraform:

  • Locals (tier definitions) defined at top of main.tf
  • Variables declared in order: core/required first, then by feature area (dbaas, traefik, etc.)
  • Modules called after variables, grouped by functional area with comment headers
  • Resources defined after modules

Go:

  • Standard imports from testing package
  • No grouping (single simple import)

Bash:

  • Source definitions at top (colors, globals, helper functions)
  • Argument parsing in dedicated parse_args() function
  • Main logic organized by check sections with section() calls

Error Handling

Terraform:

  • No explicit error handling (declarative; errors cause apply failure)
  • Dependency management via depends_on for explicit ordering
  • dependency blocks in terragrunt for cross-stack dependencies
  • skip_outputs = true used when only needing ordering, not outputs

Bash:

  • Inline error checks: command 2>&1) || { fail "message"; return 0; }
  • set -euo pipefail prevents silent failures and undefined var issues
  • Error status captured: $? implicit via || pattern
  • Graceful degradation with fallback values or skip-able steps

Go:

  • Standard testing error reporting: t.Errorf() with formatted messages
  • Table-driven test pattern allows multiple related test cases
  • Error messages include actual vs expected: got = %v, want = %v

Logging

Framework: Not formally configured; uses echo and echo -e for output

Bash Logging Patterns:

  • Color-coded output with status prefixes: ${BLUE}[INFO]${NC}, ${GREEN}[PASS]${NC}, ${YELLOW}[WARN]${NC}, ${RED}[FAIL]${NC}
  • Helper functions: info(), pass(), warn(), fail() - each increments counters and respects --quiet flag
  • Section headers: section() for verbose output, section_always() for always-shown sections
  • Conditional logging: functions check $JSON, $QUIET flags and skip output as needed
  • JSON output option available via json_add() for machine-readable logging
  • Detail strings accumulated in variables for final reporting

Terraform Logging:

  • Relies on Terraform's built-in CLI output
  • Human-readable variable values in descriptions (Terraform renders these on errors)

Comments

When to Comment:

Terraform:

  • Section dividers: Major logical groups separated by # =============================================================================
  • Feature group headers: # --- Feature Name --- before variable/module blocks
  • Commented-out code: Temporarily disabled resources/modules include explanation (e.g., "Do not use until issue #X is solved")
  • Clarifying arbitrary choices: # anything secret is fine explains non-obvious variable usage

Bash:

  • Function-level comments: Each check function has purpose on first line
  • Complex logic: Comments before conditional blocks explain intent
  • Inline comments for edge cases: # Skip nodes where metrics are not yet available
  • Header comments: Scripts include usage documentation at top

JSDoc/TSDoc:

  • Not used in this codebase (Terraform, Bash, Go only)

Function Design

Size:

  • Terraform modules typically 20-50 lines for simple services, variable declaration blocks 30-100+ lines
  • Bash functions average 20-40 lines, check functions 10-30 lines
  • Go test functions 10-60 lines (table + loop)

Parameters:

  • Terraform: via variable declarations and module input variables
  • Bash: positional parameters passed via $1, $2, etc. with validation in parse_args()
  • Go: test functions accept *testing.T parameter

Return Values:

  • Terraform: no explicit returns; resource state is the "return"
  • Bash: return 0 for success, implicit via echo output for values, status codes for error handling
  • Go: functions tested for boolean returns or calculated values

Variables:

  • Terraform: module variables, locals, and resource attributes (computed values)
  • Bash: Global state tracked via counters (PASS_COUNT, WARN_COUNT, FAIL_COUNT), local variables in functions with local keyword
  • Go: table-driven tests use struct fields (no getter/setter pattern)

Module Design

Exports:

  • Terraform: outputs typically omitted unless another stack depends on them (implicit via dependency blocks)
  • Modules called with source = "./modules/<name>" or source = "../../modules/kubernetes/<name>"
  • Module version pinning used for Terraform registry modules: version = "0.1.5"

Barrel Files:

  • Not applicable (no aggregating re-exports in this codebase)
  • Directories: stacks/<service>/ is a unit, stacks/platform/modules/<service>/ groups related modules

Module Organization:

  • Single responsibility per module directory
  • Each module typically contains: main.tf (resources) and optional variables.tf for input variables
  • Shared Kubernetes utility modules in modules/kubernetes/: ingress_factory/, setup_tls_secret/
  • Platform services grouped in stacks/platform/modules/<service>/

Special Patterns

Locals for Configuration:

  • Tier definitions centralized as map in locals (each service defines same tiers locally)
    locals {
      tiers = {
        core    = "0-core"
        cluster = "1-cluster"
        gpu     = "2-gpu"
        edge    = "3-edge"
        aux     = "4-aux"
      }
    }
    
  • Tier applied to kubernetes_namespace labels and priority_class_name for resource governance

Inline Config Blocks:

  • YAML/config data stored in <<EOT ... EOT heredoc blocks within data maps
  • Example: MetalLB address pool config in ConfigMap data

File Inclusion:

  • templatefile() used for dynamic YAML values: templatefile("${path.module}/chart_values.yaml", { var1 = value })
  • file() used for static file content in ConfigMap data

Convention analysis: 2026-02-23