# lacastrilf/controller architecture

> Architecture diagram of the GitHub repository lacastrilf/controller, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-28). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/lacastrilf/controller
- Repository: https://github.com/lacastrilf/controller

## Overview

This is a configurable autoscaling controller. An operator selects modes at startup; the controller loads mode and infrastructure settings, starts periodic runners, evaluates metrics against thresholds, then scales the configured EC2 tier or Kubernetes deployment while enforcing capacity bounds and cooldowns. CloudWatch supplies metrics, and EC2 scale-up also registers targets with the load balancer and waits for health. The README is empty, and several modules are represented only by the file tree, so their internal behavior and unwired capabilities are not expanded.

Main entry points: [`cmd/controller/main.go`](https://github.com/lacastrilf/controller/blob/main/cmd/controller/main.go) (Startup wiring), [`internal/controller/controller.go`](https://github.com/lacastrilf/controller/blob/main/internal/controller/controller.go) (Periodic runner), [`internal/evaluator/mode_rules.go`](https://github.com/lacastrilf/controller/blob/main/internal/evaluator/mode_rules.go) (Mode rules), [`internal/utils/yaml.go`](https://github.com/lacastrilf/controller/blob/main/internal/utils/yaml.go) (YAML loader)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_startup["Startup and config"]
  node_entry["Startup wiring<br/>[main.go]"]
  node_yaml["YAML loader<br/>[yaml.go]"]
  node_modes["Mode config<br/>[modes.go]"]
  node_infra["Infrastructure config<br/>[infra.go]"]
  node_modefile["Mode definitions<br/>[modes.yaml]"]
  node_inffile["Infrastructure definitions<br/>[infra.yaml]"]
end

subgraph group_decision["Evaluation"]
  node_runner["Periodic runner<br/>[controller.go]"]
  node_rules["Mode rules<br/>[mode_rules.go]"]
  node_collector["Metric provider<br/>[collector.go]"]
  node_cloudwatch["CloudWatch queries<br/>[cloudwatch.go]"]
  node_techniques["Metric techniques"]
  node_cwservice["CloudWatch"]
end

subgraph group_actions["Scaling actions"]
  node_executor["Executor interface<br/>[executor.go]"]
  node_ec2exec["EC2 scaling<br/>[ec2.go]"]
  node_k8sexec["Kubernetes scaling<br/>[kubernetes.go]"]
  node_aws["AWS EC2"]
  node_elb["Load balancer"]
  node_kubernetes["Kubernetes API"]
end

subgraph group_ops["Operations"]
  node_logger["Decision logger<br/>[logger.go]"]
  node_logdest["Console and JSONL<br/>[controller.jsonl]"]
  node_state["Resource state types"]
end

node_operator(("Operator"))

node_operator -->|"selects modes"| node_entry
node_entry -->|"loads config"| node_yaml
node_yaml -->|"reads"| node_modefile
node_yaml -->|"reads"| node_inffile
node_entry -->|"starts runners"| node_runner
node_entry -->|"constructs"| node_ec2exec
node_entry -->|"constructs"| node_k8sexec
node_entry -->|"configures"| node_rules
node_entry -->|"configures"| node_cloudwatch
node_runner -->|"reads capacity"| node_executor
node_runner -->|"evaluates"| node_rules
node_runner -->|"scales"| node_executor
node_runner -->|"records decisions"| node_logger
node_rules -->|"requests metrics"| node_collector
node_rules -->|"applies"| node_techniques
node_cloudwatch -->|"queries"| node_cwservice
node_ec2exec -->|"describes and changes"| node_aws
node_ec2exec -->|"registers and checks targets"| node_elb
node_k8sexec -->|"reads and updates deployment"| node_kubernetes
node_logger -->|"writes"| node_logdest

click node_entry "https://github.com/lacastrilf/controller/blob/main/cmd/controller/main.go"
click node_yaml "https://github.com/lacastrilf/controller/blob/main/internal/utils/yaml.go"
click node_modes "https://github.com/lacastrilf/controller/blob/main/internal/config/modes.go"
click node_infra "https://github.com/lacastrilf/controller/blob/main/internal/config/infra.go"
click node_runner "https://github.com/lacastrilf/controller/blob/main/internal/controller/controller.go"
click node_rules "https://github.com/lacastrilf/controller/blob/main/internal/evaluator/mode_rules.go"
click node_collector "https://github.com/lacastrilf/controller/blob/main/internal/collector/collector.go"
click node_cloudwatch "https://github.com/lacastrilf/controller/blob/main/internal/collector/cloudwatch.go"
click node_techniques "https://github.com/lacastrilf/controller/tree/main/internal/techniques"
click node_executor "https://github.com/lacastrilf/controller/blob/main/internal/executor/executor.go"
click node_ec2exec "https://github.com/lacastrilf/controller/blob/main/internal/executor/ec2.go"
click node_k8sexec "https://github.com/lacastrilf/controller/blob/main/internal/executor/kubernetes.go"
click node_logger "https://github.com/lacastrilf/controller/blob/main/internal/logger/logger.go"
click node_logdest "https://github.com/lacastrilf/controller/blob/main/controller.jsonl"
click node_state "https://github.com/lacastrilf/controller/tree/main/internal/state"
click node_modefile "https://github.com/lacastrilf/controller/blob/main/config/modes.yaml"
click node_inffile "https://github.com/lacastrilf/controller/blob/main/config/infra.yaml"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_entry,node_yaml,node_modes,node_infra,node_modefile,node_inffile toneBlue
class node_runner,node_rules,node_collector,node_cloudwatch,node_techniques,node_cwservice toneAmber
class node_executor,node_ec2exec,node_k8sexec,node_aws,node_elb,node_kubernetes toneMint
class node_logger,node_logdest,node_state toneRose
class node_operator toneIndigo
```

## Components

### Startup and config

- [Startup wiring](https://github.com/lacastrilf/controller/blob/main/cmd/controller/main.go): `cmd/controller/main.go`
- [YAML loader](https://github.com/lacastrilf/controller/blob/main/internal/utils/yaml.go): `internal/utils/yaml.go`
- [Mode config](https://github.com/lacastrilf/controller/blob/main/internal/config/modes.go): `internal/config/modes.go`
- [Infrastructure config](https://github.com/lacastrilf/controller/blob/main/internal/config/infra.go): `internal/config/infra.go`
- [Mode definitions](https://github.com/lacastrilf/controller/blob/main/config/modes.yaml): `config/modes.yaml`
- [Infrastructure definitions](https://github.com/lacastrilf/controller/blob/main/config/infra.yaml): `config/infra.yaml`

### Evaluation

- [Periodic runner](https://github.com/lacastrilf/controller/blob/main/internal/controller/controller.go): `internal/controller/controller.go`
- [Mode rules](https://github.com/lacastrilf/controller/blob/main/internal/evaluator/mode_rules.go): `internal/evaluator/mode_rules.go`
- [Metric provider](https://github.com/lacastrilf/controller/blob/main/internal/collector/collector.go): `internal/collector/collector.go`
- [CloudWatch queries](https://github.com/lacastrilf/controller/blob/main/internal/collector/cloudwatch.go): `internal/collector/cloudwatch.go`
- [Metric techniques](https://github.com/lacastrilf/controller/tree/main/internal/techniques): `internal/techniques`
- **CloudWatch**

### Scaling actions

- [Executor interface](https://github.com/lacastrilf/controller/blob/main/internal/executor/executor.go): `internal/executor/executor.go`
- [EC2 scaling](https://github.com/lacastrilf/controller/blob/main/internal/executor/ec2.go): `internal/executor/ec2.go`
- [Kubernetes scaling](https://github.com/lacastrilf/controller/blob/main/internal/executor/kubernetes.go): `internal/executor/kubernetes.go`
- **AWS EC2**
- **Load balancer**
- **Kubernetes API**

### Operations

- [Decision logger](https://github.com/lacastrilf/controller/blob/main/internal/logger/logger.go): `internal/logger/logger.go`
- [Console and JSONL](https://github.com/lacastrilf/controller/blob/main/controller.jsonl): `controller.jsonl`
- [Resource state types](https://github.com/lacastrilf/controller/tree/main/internal/state): `internal/state`

### Other components

- **Operator**

## Connections

- Operator → Startup wiring: selects modes
- Startup wiring → YAML loader: loads config
- YAML loader → Mode definitions: reads
- YAML loader → Infrastructure definitions: reads
- Startup wiring → Periodic runner: starts runners
- Startup wiring → EC2 scaling: constructs
- Startup wiring → Kubernetes scaling: constructs
- Startup wiring → Mode rules: configures
- Startup wiring → CloudWatch queries: configures
- Periodic runner → Executor interface: reads capacity
- Periodic runner → Mode rules: evaluates
- Periodic runner → Executor interface: scales
- Periodic runner → Decision logger: records decisions
- Mode rules → Metric provider: requests metrics
- Mode rules → Metric techniques: applies
- CloudWatch queries → CloudWatch: queries
- EC2 scaling → AWS EC2: describes and changes
- EC2 scaling → Load balancer: registers and checks targets
- Kubernetes scaling → Kubernetes API: reads and updates deployment
- Decision logger → Console and JSONL: writes
