nvoi 0.1.5 → 0.1.7
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.
- checksums.yaml +4 -4
- data/.claude/todo/refactor/00-overview.md +171 -0
- data/.claude/todo/refactor/01-objects.md +96 -0
- data/.claude/todo/refactor/02-utils.md +143 -0
- data/.claude/todo/refactor/03-external-cloud.md +164 -0
- data/.claude/todo/refactor/04-external-dns.md +104 -0
- data/.claude/todo/refactor/05-external.md +133 -0
- data/.claude/todo/refactor/06-cli.md +123 -0
- data/.claude/todo/refactor/07-cli-deploy-command.md +177 -0
- data/.claude/todo/refactor/08-cli-deploy-steps.md +201 -0
- data/.claude/todo/refactor/09-cli-delete-command.md +169 -0
- data/.claude/todo/refactor/10-cli-exec-command.md +157 -0
- data/.claude/todo/refactor/11-cli-credentials-command.md +190 -0
- data/.claude/todo/refactor/12-cli-db-command.md +128 -0
- data/.claude/todo/refactor/_target.md +79 -0
- data/.claude/todo/refactor-execution/00-entrypoint.md +49 -0
- data/.claude/todo/refactor-execution/01-objects.md +42 -0
- data/.claude/todo/refactor-execution/02-utils.md +41 -0
- data/.claude/todo/refactor-execution/03-external-cloud.md +38 -0
- data/.claude/todo/refactor-execution/04-external-dns.md +35 -0
- data/.claude/todo/refactor-execution/05-external-other.md +46 -0
- data/.claude/todo/refactor-execution/06-cli-deploy.md +45 -0
- data/.claude/todo/refactor-execution/07-cli-delete.md +43 -0
- data/.claude/todo/refactor-execution/08-cli-exec.md +30 -0
- data/.claude/todo/refactor-execution/09-cli-credentials.md +34 -0
- data/.claude/todo/refactor-execution/10-cli-db.md +31 -0
- data/.claude/todo/refactor-execution/11-cli-router.md +44 -0
- data/.claude/todo/refactor-execution/12-cleanup.md +120 -0
- data/.claude/todo/refactor-execution/_monitoring-strategy.md +126 -0
- data/.claude/todo/scaleway.impl.md +644 -0
- data/.claude/todo/scaleway.reference.md +520 -0
- data/.claude/todos.md +550 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +46 -5
- data/Rakefile +1 -1
- data/doc/config-schema.yaml +44 -11
- data/examples/golang/deploy.enc +0 -0
- data/examples/golang/main.go +18 -0
- data/exe/nvoi +3 -1
- data/ingest +0 -0
- data/lib/nvoi/cli/config/command.rb +219 -0
- data/lib/nvoi/cli/credentials/edit/command.rb +384 -0
- data/lib/nvoi/cli/credentials/show/command.rb +35 -0
- data/lib/nvoi/cli/db/command.rb +308 -0
- data/lib/nvoi/cli/delete/command.rb +75 -0
- data/lib/nvoi/cli/delete/steps/detach_volumes.rb +98 -0
- data/lib/nvoi/cli/delete/steps/teardown_dns.rb +50 -0
- data/lib/nvoi/cli/delete/steps/teardown_firewall.rb +46 -0
- data/lib/nvoi/cli/delete/steps/teardown_network.rb +30 -0
- data/lib/nvoi/cli/delete/steps/teardown_server.rb +50 -0
- data/lib/nvoi/cli/delete/steps/teardown_tunnel.rb +44 -0
- data/lib/nvoi/cli/delete/steps/teardown_volume.rb +61 -0
- data/lib/nvoi/cli/deploy/command.rb +184 -0
- data/lib/nvoi/cli/deploy/steps/build_image.rb +27 -0
- data/lib/nvoi/cli/deploy/steps/cleanup_images.rb +42 -0
- data/lib/nvoi/cli/deploy/steps/configure_tunnel.rb +102 -0
- data/lib/nvoi/cli/deploy/steps/deploy_service.rb +399 -0
- data/lib/nvoi/cli/deploy/steps/provision_network.rb +44 -0
- data/lib/nvoi/cli/deploy/steps/provision_server.rb +143 -0
- data/lib/nvoi/cli/deploy/steps/provision_volume.rb +171 -0
- data/lib/nvoi/cli/deploy/steps/setup_k3s.rb +490 -0
- data/lib/nvoi/cli/exec/command.rb +173 -0
- data/lib/nvoi/cli/logs/command.rb +66 -0
- data/lib/nvoi/cli/onboard/command.rb +761 -0
- data/lib/nvoi/cli/unlock/command.rb +72 -0
- data/lib/nvoi/cli.rb +339 -141
- data/lib/nvoi/config_api/actions/app.rb +53 -0
- data/lib/nvoi/config_api/actions/compute_provider.rb +55 -0
- data/lib/nvoi/config_api/actions/database.rb +70 -0
- data/lib/nvoi/config_api/actions/domain_provider.rb +40 -0
- data/lib/nvoi/config_api/actions/env.rb +32 -0
- data/lib/nvoi/config_api/actions/init.rb +67 -0
- data/lib/nvoi/config_api/actions/secret.rb +32 -0
- data/lib/nvoi/config_api/actions/server.rb +66 -0
- data/lib/nvoi/config_api/actions/service.rb +52 -0
- data/lib/nvoi/config_api/actions/volume.rb +40 -0
- data/lib/nvoi/config_api/base.rb +38 -0
- data/lib/nvoi/config_api/result.rb +26 -0
- data/lib/nvoi/config_api.rb +93 -0
- data/lib/nvoi/errors.rb +68 -50
- data/lib/nvoi/external/cloud/aws.rb +450 -0
- data/lib/nvoi/external/cloud/base.rb +99 -0
- data/lib/nvoi/external/cloud/factory.rb +48 -0
- data/lib/nvoi/external/cloud/hetzner.rb +402 -0
- data/lib/nvoi/external/cloud/scaleway.rb +559 -0
- data/lib/nvoi/external/cloud.rb +15 -0
- data/lib/nvoi/external/containerd.rb +86 -0
- data/lib/nvoi/external/database/mysql.rb +84 -0
- data/lib/nvoi/external/database/postgres.rb +82 -0
- data/lib/nvoi/external/database/provider.rb +65 -0
- data/lib/nvoi/external/database/sqlite.rb +72 -0
- data/lib/nvoi/external/database.rb +22 -0
- data/lib/nvoi/external/dns/cloudflare.rb +310 -0
- data/lib/nvoi/external/kubectl.rb +65 -0
- data/lib/nvoi/external/ssh.rb +106 -0
- data/lib/nvoi/objects/config_override.rb +60 -0
- data/lib/nvoi/objects/configuration.rb +483 -0
- data/lib/nvoi/objects/database.rb +56 -0
- data/lib/nvoi/objects/dns.rb +14 -0
- data/lib/nvoi/objects/firewall.rb +11 -0
- data/lib/nvoi/objects/network.rb +11 -0
- data/lib/nvoi/objects/server.rb +14 -0
- data/lib/nvoi/objects/service_spec.rb +26 -0
- data/lib/nvoi/objects/tunnel.rb +14 -0
- data/lib/nvoi/objects/volume.rb +17 -0
- data/lib/nvoi/utils/config_loader.rb +172 -0
- data/lib/nvoi/utils/constants.rb +61 -0
- data/lib/nvoi/{credentials/manager.rb → utils/credential_store.rb} +16 -16
- data/lib/nvoi/{credentials → utils}/crypto.rb +8 -5
- data/lib/nvoi/{config → utils}/env_resolver.rb +10 -2
- data/lib/nvoi/utils/logger.rb +84 -0
- data/lib/nvoi/{config/naming.rb → utils/namer.rb} +37 -25
- data/lib/nvoi/{deployer → utils}/retry.rb +23 -3
- data/lib/nvoi/utils/templates.rb +62 -0
- data/lib/nvoi/version.rb +1 -1
- data/lib/nvoi.rb +27 -55
- data/templates/app-ingress.yaml.erb +3 -1
- data/templates/error-backend.yaml.erb +134 -0
- metadata +121 -44
- data/examples/golang/deploy.yml +0 -54
- data/lib/nvoi/cloudflare/client.rb +0 -287
- data/lib/nvoi/config/config.rb +0 -248
- data/lib/nvoi/config/loader.rb +0 -102
- data/lib/nvoi/config/ssh_keys.rb +0 -82
- data/lib/nvoi/config/types.rb +0 -274
- data/lib/nvoi/constants.rb +0 -59
- data/lib/nvoi/credentials/editor.rb +0 -272
- data/lib/nvoi/deployer/cleaner.rb +0 -36
- data/lib/nvoi/deployer/image_builder.rb +0 -23
- data/lib/nvoi/deployer/infrastructure.rb +0 -126
- data/lib/nvoi/deployer/orchestrator.rb +0 -146
- data/lib/nvoi/deployer/service_deployer.rb +0 -311
- data/lib/nvoi/deployer/tunnel_manager.rb +0 -57
- data/lib/nvoi/deployer/types.rb +0 -8
- data/lib/nvoi/k8s/renderer.rb +0 -44
- data/lib/nvoi/k8s/templates.rb +0 -29
- data/lib/nvoi/logger.rb +0 -72
- data/lib/nvoi/providers/aws.rb +0 -403
- data/lib/nvoi/providers/base.rb +0 -111
- data/lib/nvoi/providers/hetzner.rb +0 -288
- data/lib/nvoi/providers/hetzner_client.rb +0 -170
- data/lib/nvoi/remote/docker_manager.rb +0 -203
- data/lib/nvoi/remote/ssh_executor.rb +0 -72
- data/lib/nvoi/remote/volume_manager.rb +0 -103
- data/lib/nvoi/service/delete.rb +0 -234
- data/lib/nvoi/service/deploy.rb +0 -80
- data/lib/nvoi/service/exec.rb +0 -144
- data/lib/nvoi/service/provider.rb +0 -36
- data/lib/nvoi/steps/application_deployer.rb +0 -26
- data/lib/nvoi/steps/database_provisioner.rb +0 -60
- data/lib/nvoi/steps/k3s_cluster_setup.rb +0 -105
- data/lib/nvoi/steps/k3s_provisioner.rb +0 -351
- data/lib/nvoi/steps/server_provisioner.rb +0 -43
- data/lib/nvoi/steps/services_provisioner.rb +0 -29
- data/lib/nvoi/steps/tunnel_configurator.rb +0 -66
- data/lib/nvoi/steps/volume_provisioner.rb +0 -154
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 91c0d6ae24cfc163dd6c00008e5199cfdca4b9864ed6c2b56644b58b90d04ca6
|
|
4
|
+
data.tar.gz: 319109891843c14ae0dfe4c66553bdf06a5bf5a1d009855f97f0c6ffc17bccc6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 34b0c1e73b479bb2e10356b27f397a7c34dc9476bd7244490450163736fc7106bd28143ec91bfba1aa27a16c5b1f15d722cfd09d98d7a4155ce7dd752ff30949
|
|
7
|
+
data.tar.gz: 9706c433e608299ac10f71ff257a9d73a0e4f97bab126d3b99d0050474c426dde79fb793204dc55d9369b0654bfba162621106c34d3791fb4e9fb7fed651d8e2
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# Refactor Overview
|
|
2
|
+
|
|
3
|
+
## Target Structure
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
lib/nvoi/
|
|
7
|
+
├── cli.rb # Thor routing only (~50 lines)
|
|
8
|
+
│
|
|
9
|
+
├── cli/
|
|
10
|
+
│ ├── deploy/
|
|
11
|
+
│ │ ├── command.rb
|
|
12
|
+
│ │ └── steps/
|
|
13
|
+
│ │ ├── provision_network.rb
|
|
14
|
+
│ │ ├── provision_server.rb
|
|
15
|
+
│ │ ├── provision_volume.rb
|
|
16
|
+
│ │ ├── setup_k3s.rb
|
|
17
|
+
│ │ ├── configure_tunnel.rb
|
|
18
|
+
│ │ ├── build_image.rb
|
|
19
|
+
│ │ ├── deploy_service.rb
|
|
20
|
+
│ │ └── cleanup_images.rb
|
|
21
|
+
│ │
|
|
22
|
+
│ ├── delete/
|
|
23
|
+
│ │ ├── command.rb
|
|
24
|
+
│ │ └── steps/
|
|
25
|
+
│ │ ├── teardown_tunnel.rb
|
|
26
|
+
│ │ ├── teardown_dns.rb
|
|
27
|
+
│ │ ├── detach_volumes.rb
|
|
28
|
+
│ │ ├── teardown_server.rb
|
|
29
|
+
│ │ ├── teardown_volume.rb
|
|
30
|
+
│ │ ├── teardown_firewall.rb
|
|
31
|
+
│ │ └── teardown_network.rb
|
|
32
|
+
│ │
|
|
33
|
+
│ ├── exec/
|
|
34
|
+
│ │ └── command.rb
|
|
35
|
+
│ │
|
|
36
|
+
│ └── credentials/
|
|
37
|
+
│ ├── edit/
|
|
38
|
+
│ │ └── command.rb
|
|
39
|
+
│ └── show/
|
|
40
|
+
│ └── command.rb
|
|
41
|
+
│
|
|
42
|
+
├── external/
|
|
43
|
+
│ ├── cloud/
|
|
44
|
+
│ │ ├── base.rb
|
|
45
|
+
│ │ ├── hetzner.rb
|
|
46
|
+
│ │ ├── aws.rb
|
|
47
|
+
│ │ ├── scaleway.rb
|
|
48
|
+
│ │ └── factory.rb
|
|
49
|
+
│ ├── dns/
|
|
50
|
+
│ │ └── cloudflare.rb
|
|
51
|
+
│ ├── ssh.rb
|
|
52
|
+
│ ├── kubectl.rb
|
|
53
|
+
│ └── containerd.rb
|
|
54
|
+
│
|
|
55
|
+
├── objects/
|
|
56
|
+
│ ├── server.rb
|
|
57
|
+
│ ├── network.rb
|
|
58
|
+
│ ├── firewall.rb
|
|
59
|
+
│ ├── volume.rb
|
|
60
|
+
│ ├── tunnel.rb
|
|
61
|
+
│ ├── dns.rb
|
|
62
|
+
│ ├── service_spec.rb
|
|
63
|
+
│ └── config.rb
|
|
64
|
+
│
|
|
65
|
+
└── utils/
|
|
66
|
+
├── namer.rb
|
|
67
|
+
├── env_resolver.rb
|
|
68
|
+
├── config_loader.rb
|
|
69
|
+
├── crypto.rb
|
|
70
|
+
├── templates.rb
|
|
71
|
+
├── logger.rb
|
|
72
|
+
├── constants.rb
|
|
73
|
+
├── errors.rb
|
|
74
|
+
└── retry.rb
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Refactor Order
|
|
80
|
+
|
|
81
|
+
| # | File | Description | Depends On |
|
|
82
|
+
| --- | -------------------------- | ------------------------- | --------------- |
|
|
83
|
+
| 01 | objects.md | Domain entities (Structs) | Nothing |
|
|
84
|
+
| 02 | utils.md | Shared helpers | Objects |
|
|
85
|
+
| 03 | external-cloud.md | Cloud provider adapters | Objects, Utils |
|
|
86
|
+
| 04 | external-dns.md | Cloudflare adapter | Objects, Utils |
|
|
87
|
+
| 05 | external.md | SSH, kubectl, containerd | Objects, Utils |
|
|
88
|
+
| 06 | cli.md | Thor router | Commands |
|
|
89
|
+
| 07 | cli-deploy-command.md | Deploy orchestration | External, Utils |
|
|
90
|
+
| 08 | cli-deploy-steps.md | Deploy step details | External, Utils |
|
|
91
|
+
| 09 | cli-delete-command.md | Delete orchestration | External, Utils |
|
|
92
|
+
| 10 | cli-exec-command.md | Exec command | External, Utils |
|
|
93
|
+
| 11 | cli-credentials-command.md | Credentials commands | Utils |
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Line Count Summary
|
|
98
|
+
|
|
99
|
+
### Current State (~4200 lines)
|
|
100
|
+
|
|
101
|
+
| Category | Lines |
|
|
102
|
+
| --------------------------------- | ----- |
|
|
103
|
+
| Config types + loading | ~550 |
|
|
104
|
+
| Credentials | ~330 |
|
|
105
|
+
| Providers | ~1380 |
|
|
106
|
+
| Cloudflare | ~350 |
|
|
107
|
+
| Remote (SSH, Docker, Volume) | ~430 |
|
|
108
|
+
| K8s (templates, renderer) | ~75 |
|
|
109
|
+
| Steps | ~750 |
|
|
110
|
+
| Deployer | ~580 |
|
|
111
|
+
| Service (CLI entry) | ~460 |
|
|
112
|
+
| Utils (logger, constants, errors) | ~200 |
|
|
113
|
+
| CLI | ~190 |
|
|
114
|
+
|
|
115
|
+
### Target State (~3800 lines)
|
|
116
|
+
|
|
117
|
+
| Category | Lines | Change |
|
|
118
|
+
| ---------------- | ----- | ---------------- |
|
|
119
|
+
| objects/ | ~400 | consolidated |
|
|
120
|
+
| utils/ | ~600 | merged |
|
|
121
|
+
| external/ | ~1000 | merged providers |
|
|
122
|
+
| cli/deploy/ | ~1200 | flattened |
|
|
123
|
+
| cli/delete/ | ~300 | separated |
|
|
124
|
+
| cli/exec/ | ~150 | simplified |
|
|
125
|
+
| cli/credentials/ | ~100 | simplified |
|
|
126
|
+
| cli.rb | ~50 | routing only |
|
|
127
|
+
|
|
128
|
+
**Net reduction: ~400 lines (10%)**
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## DRY Wins
|
|
133
|
+
|
|
134
|
+
1. **Hostname builder** - 3 duplications → 1 in `utils/namer.rb`
|
|
135
|
+
2. **Provider + Client merge** - 4 files → 3 files
|
|
136
|
+
3. **TunnelManager absorption** - eliminated wrapper
|
|
137
|
+
4. **Config loader + SSH key merge** - 2 files → 1 file
|
|
138
|
+
5. **Crypto + Manager merge** - 2 files → 1 file
|
|
139
|
+
6. **Templates + Binding merge** - 2 files → 1 file
|
|
140
|
+
7. **Thin wrapper removal** - `ApplicationDeployer`, `Editor` → gone
|
|
141
|
+
8. **Struct consolidation** - scattered → `objects/`
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Migration Strategy
|
|
146
|
+
|
|
147
|
+
### Phase 1: Foundation (01-02)
|
|
148
|
+
|
|
149
|
+
Create `objects/` and `utils/`. No breaking changes yet.
|
|
150
|
+
Other code keeps working, just uses new locations.
|
|
151
|
+
|
|
152
|
+
### Phase 2: External Adapters (03-05)
|
|
153
|
+
|
|
154
|
+
Move and merge providers. Update imports.
|
|
155
|
+
Still backward compatible with old namespaces via aliases if needed.
|
|
156
|
+
|
|
157
|
+
### Phase 3: Commands (07-11)
|
|
158
|
+
|
|
159
|
+
Create new command structure.
|
|
160
|
+
Old `service/*.rb` files still work during transition.
|
|
161
|
+
|
|
162
|
+
### Phase 4: Router (06)
|
|
163
|
+
|
|
164
|
+
Switch `cli.rb` to new commands.
|
|
165
|
+
Delete old files.
|
|
166
|
+
|
|
167
|
+
### Phase 5: Cleanup
|
|
168
|
+
|
|
169
|
+
- Remove empty directories
|
|
170
|
+
- Remove old requires from `lib/nvoi.rb`
|
|
171
|
+
- Update tests
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# 01 - Objects (Domain Entities)
|
|
2
|
+
|
|
3
|
+
## Priority: FIRST
|
|
4
|
+
|
|
5
|
+
Objects have no dependencies. Everything else depends on them.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Current State
|
|
10
|
+
|
|
11
|
+
Scattered across multiple files:
|
|
12
|
+
|
|
13
|
+
| Object | Current Location | Lines |
|
|
14
|
+
| ------------------------------------------------------------- | ---------------------- | ----- |
|
|
15
|
+
| `Server`, `Network`, `Firewall`, `Volume` | `providers/base.rb` | ~20 |
|
|
16
|
+
| `ServerCreateOptions`, `VolumeCreateOptions` | `providers/base.rb` | ~5 |
|
|
17
|
+
| `Tunnel`, `Zone`, `DNSRecord` | `cloudflare/client.rb` | ~10 |
|
|
18
|
+
| `TunnelInfo` | `deployer/types.rb` | ~3 |
|
|
19
|
+
| `ServiceSpec` | `config/types.rb` | ~20 |
|
|
20
|
+
| `MountOptions`, `ContainerRunOptions`, `WaitForHealthOptions` | `remote/*.rb` | ~10 |
|
|
21
|
+
| Config types (15+ classes) | `config/types.rb` | ~290 |
|
|
22
|
+
|
|
23
|
+
**Total: ~360 lines scattered across 5 files**
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Target Structure
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
lib/nvoi/objects/
|
|
31
|
+
├── server.rb # Server, ServerCreateOptions
|
|
32
|
+
├── network.rb # Network
|
|
33
|
+
├── firewall.rb # Firewall
|
|
34
|
+
├── volume.rb # Volume, VolumeCreateOptions, MountOptions
|
|
35
|
+
├── tunnel.rb # Tunnel, TunnelInfo
|
|
36
|
+
├── dns.rb # Zone, DNSRecord
|
|
37
|
+
├── service_spec.rb # ServiceSpec (K8s deployment spec)
|
|
38
|
+
└── config.rb # All config types consolidated
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## DRY Opportunities
|
|
44
|
+
|
|
45
|
+
### 1. Config Types Consolidation
|
|
46
|
+
|
|
47
|
+
Current `config/types.rb` has 15+ classes. Keep them but in `objects/config.rb`.
|
|
48
|
+
|
|
49
|
+
### 2. Struct vs Class
|
|
50
|
+
|
|
51
|
+
Many objects are simple Structs. Keep them as Structs:
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
# objects/server.rb
|
|
55
|
+
module Nvoi
|
|
56
|
+
module Objects
|
|
57
|
+
Server = Struct.new(:id, :name, :status, :public_ipv4, keyword_init: true)
|
|
58
|
+
ServerCreateOptions = Struct.new(:name, :type, :image, :location, :user_data, :network_id, :firewall_id, keyword_init: true)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 3. TunnelInfo Duplication
|
|
64
|
+
|
|
65
|
+
`TunnelInfo` in `deployer/types.rb` is basically `Tunnel` + extra fields. Merge:
|
|
66
|
+
|
|
67
|
+
```ruby
|
|
68
|
+
# objects/tunnel.rb
|
|
69
|
+
module Nvoi
|
|
70
|
+
module Objects
|
|
71
|
+
Tunnel = Struct.new(:id, :name, :token, keyword_init: true)
|
|
72
|
+
TunnelInfo = Struct.new(:service_name, :hostname, :tunnel_id, :tunnel_token, :port, keyword_init: true)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Migration Steps
|
|
80
|
+
|
|
81
|
+
1. Create `lib/nvoi/objects/` directory
|
|
82
|
+
2. Extract Structs from `providers/base.rb` → `objects/server.rb`, `objects/network.rb`, etc.
|
|
83
|
+
3. Extract Structs from `cloudflare/client.rb` → `objects/tunnel.rb`, `objects/dns.rb`
|
|
84
|
+
4. Move `deployer/types.rb` → `objects/tunnel.rb` (merge TunnelInfo)
|
|
85
|
+
5. Move `config/types.rb` → `objects/config.rb`
|
|
86
|
+
6. Extract `MountOptions` from `remote/volume_manager.rb` → `objects/volume.rb`
|
|
87
|
+
7. Update all requires in `lib/nvoi.rb`
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Estimated Effort
|
|
92
|
+
|
|
93
|
+
- **Lines to move:** ~360
|
|
94
|
+
- **Files created:** 8
|
|
95
|
+
- **Files deleted:** 1 (`deployer/types.rb`)
|
|
96
|
+
- **Files modified:** 4 (remove struct definitions)
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# 02 - Utils (Shared Helpers)
|
|
2
|
+
|
|
3
|
+
## Priority: SECOND
|
|
4
|
+
|
|
5
|
+
Utils depend only on Objects. Everything else uses them.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Current State
|
|
10
|
+
|
|
11
|
+
| Utility | Current Location | Lines | Purpose |
|
|
12
|
+
| ----------------- | ------------------------ | ----- | ---------------------------------- |
|
|
13
|
+
| `ResourceNamer` | `config/naming.rb` | 197 | Generate consistent resource names |
|
|
14
|
+
| `EnvResolver` | `config/env_resolver.rb` | 64 | Merge env vars from config |
|
|
15
|
+
| `SSHKeyLoader` | `config/ssh_keys.rb` | ~80 | Load SSH keys from config |
|
|
16
|
+
| `ConfigLoader` | `config/loader.rb` | 103 | Load and parse config file |
|
|
17
|
+
| `Crypto` | `credentials/crypto.rb` | ~100 | AES encryption/decryption |
|
|
18
|
+
| `Manager` | `credentials/manager.rb` | ~150 | Credential file management |
|
|
19
|
+
| `Templates` | `k8s/templates.rb` | ~30 | ERB template loading |
|
|
20
|
+
| `TemplateBinding` | `k8s/renderer.rb` | ~20 | ERB binding helper |
|
|
21
|
+
| `Logger` | `logger.rb` | 73 | Colored console output |
|
|
22
|
+
| `Constants` | `constants.rb` | 60 | Magic numbers |
|
|
23
|
+
| `Errors` | `errors.rb` | 70 | Error class hierarchy |
|
|
24
|
+
| `Retry` | `deployer/retry.rb` | ~30 | Retry logic |
|
|
25
|
+
|
|
26
|
+
**Total: ~980 lines across 12 files**
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Target Structure
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
lib/nvoi/utils/
|
|
34
|
+
├── namer.rb # ResourceNamer
|
|
35
|
+
├── env_resolver.rb # EnvResolver
|
|
36
|
+
├── config_loader.rb # ConfigLoader + SSHKeyLoader (merge)
|
|
37
|
+
├── crypto.rb # Crypto + Manager (merge)
|
|
38
|
+
├── templates.rb # Templates + TemplateBinding
|
|
39
|
+
├── logger.rb # Logger
|
|
40
|
+
├── constants.rb # Constants
|
|
41
|
+
├── errors.rb # All error classes
|
|
42
|
+
└── retry.rb # Retry logic
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## DRY Opportunities
|
|
48
|
+
|
|
49
|
+
### 1. Merge ConfigLoader + SSHKeyLoader
|
|
50
|
+
|
|
51
|
+
Both deal with config initialization. Single file:
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
# utils/config_loader.rb
|
|
55
|
+
module Nvoi
|
|
56
|
+
module Utils
|
|
57
|
+
class ConfigLoader
|
|
58
|
+
def load(path)
|
|
59
|
+
# decrypt, parse YAML, load SSH keys, validate
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 2. Merge Crypto + Manager
|
|
67
|
+
|
|
68
|
+
`Manager` is just `Crypto` + file I/O. Combine:
|
|
69
|
+
|
|
70
|
+
```ruby
|
|
71
|
+
# utils/crypto.rb
|
|
72
|
+
module Nvoi
|
|
73
|
+
module Utils
|
|
74
|
+
class Crypto
|
|
75
|
+
def encrypt(plaintext) ... end
|
|
76
|
+
def decrypt(ciphertext) ... end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
class CredentialStore
|
|
80
|
+
def initialize(crypto) ... end
|
|
81
|
+
def read ... end
|
|
82
|
+
def write(content) ... end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 3. Merge Templates + TemplateBinding
|
|
89
|
+
|
|
90
|
+
Both in k8s/ but are generic ERB utilities:
|
|
91
|
+
|
|
92
|
+
```ruby
|
|
93
|
+
# utils/templates.rb
|
|
94
|
+
module Nvoi
|
|
95
|
+
module Utils
|
|
96
|
+
class TemplateRenderer
|
|
97
|
+
def render(name, data) ... end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 4. Hostname Builder Duplication
|
|
104
|
+
|
|
105
|
+
`build_hostname(subdomain, domain)` appears in:
|
|
106
|
+
|
|
107
|
+
- `steps/tunnel_configurator.rb`
|
|
108
|
+
- `service/delete.rb`
|
|
109
|
+
- `deployer/service_deployer.rb`
|
|
110
|
+
|
|
111
|
+
Extract to namer:
|
|
112
|
+
|
|
113
|
+
```ruby
|
|
114
|
+
# utils/namer.rb
|
|
115
|
+
def hostname(subdomain, domain)
|
|
116
|
+
subdomain.nil? || subdomain.empty? || subdomain == "@" ? domain : "#{subdomain}.#{domain}"
|
|
117
|
+
end
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Migration Steps
|
|
123
|
+
|
|
124
|
+
1. Create `lib/nvoi/utils/` directory
|
|
125
|
+
2. Move `logger.rb` → `utils/logger.rb` (no changes)
|
|
126
|
+
3. Move `constants.rb` → `utils/constants.rb` (no changes)
|
|
127
|
+
4. Move `errors.rb` → `utils/errors.rb` (no changes)
|
|
128
|
+
5. Merge `config/naming.rb` → `utils/namer.rb` + add `hostname` method
|
|
129
|
+
6. Merge `config/env_resolver.rb` → `utils/env_resolver.rb`
|
|
130
|
+
7. Merge `config/loader.rb` + `config/ssh_keys.rb` → `utils/config_loader.rb`
|
|
131
|
+
8. Merge `credentials/crypto.rb` + `credentials/manager.rb` → `utils/crypto.rb`
|
|
132
|
+
9. Merge `k8s/templates.rb` + `k8s/renderer.rb` → `utils/templates.rb`
|
|
133
|
+
10. Move `deployer/retry.rb` → `utils/retry.rb`
|
|
134
|
+
11. Update all requires
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Estimated Effort
|
|
139
|
+
|
|
140
|
+
- **Lines to consolidate:** ~980
|
|
141
|
+
- **Files created:** 9
|
|
142
|
+
- **Files deleted:** 12 (all current locations)
|
|
143
|
+
- **DRY savings:** ~50 lines (hostname duplication, merged classes)
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# 03 - External: Cloud Providers
|
|
2
|
+
|
|
3
|
+
## Priority: THIRD
|
|
4
|
+
|
|
5
|
+
External adapters depend on Objects and Utils.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Current State
|
|
10
|
+
|
|
11
|
+
| File | Lines | Purpose |
|
|
12
|
+
| ------------------------------ | ----- | ---------------------------- |
|
|
13
|
+
| `providers/base.rb` | 112 | Abstract interface + Structs |
|
|
14
|
+
| `providers/hetzner.rb` | 289 | Hetzner Cloud implementation |
|
|
15
|
+
| `providers/hetzner_client.rb` | ~200 | Hetzner HTTP client |
|
|
16
|
+
| `providers/aws.rb` | ~250 | AWS implementation |
|
|
17
|
+
| `providers/scaleway.rb` | ~280 | Scaleway implementation |
|
|
18
|
+
| `providers/scaleway_client.rb` | ~200 | Scaleway HTTP client |
|
|
19
|
+
| `service/provider.rb` | ~50 | Provider factory helper |
|
|
20
|
+
|
|
21
|
+
**Total: ~1380 lines across 7 files**
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Target Structure
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
lib/nvoi/external/cloud/
|
|
29
|
+
├── base.rb # Abstract interface (methods only, no Structs)
|
|
30
|
+
├── hetzner.rb # Hetzner (merge provider + client)
|
|
31
|
+
├── aws.rb # AWS
|
|
32
|
+
├── scaleway.rb # Scaleway (merge provider + client)
|
|
33
|
+
└── factory.rb # Provider initialization helper
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## What Each Provider Does
|
|
39
|
+
|
|
40
|
+
All providers implement:
|
|
41
|
+
|
|
42
|
+
```ruby
|
|
43
|
+
# Network operations
|
|
44
|
+
find_or_create_network(name)
|
|
45
|
+
get_network_by_name(name)
|
|
46
|
+
delete_network(id)
|
|
47
|
+
|
|
48
|
+
# Firewall operations
|
|
49
|
+
find_or_create_firewall(name)
|
|
50
|
+
get_firewall_by_name(name)
|
|
51
|
+
delete_firewall(id)
|
|
52
|
+
|
|
53
|
+
# Server operations
|
|
54
|
+
find_server(name)
|
|
55
|
+
list_servers
|
|
56
|
+
create_server(opts)
|
|
57
|
+
wait_for_server(server_id, max_attempts)
|
|
58
|
+
delete_server(id)
|
|
59
|
+
|
|
60
|
+
# Volume operations
|
|
61
|
+
create_volume(opts)
|
|
62
|
+
get_volume(id)
|
|
63
|
+
get_volume_by_name(name)
|
|
64
|
+
delete_volume(id)
|
|
65
|
+
attach_volume(volume_id, server_id)
|
|
66
|
+
detach_volume(volume_id)
|
|
67
|
+
|
|
68
|
+
# Validation
|
|
69
|
+
validate_instance_type(instance_type)
|
|
70
|
+
validate_region(region)
|
|
71
|
+
validate_credentials
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## DRY Opportunities
|
|
77
|
+
|
|
78
|
+
### 1. Merge Provider + Client
|
|
79
|
+
|
|
80
|
+
Current pattern:
|
|
81
|
+
|
|
82
|
+
- `hetzner.rb` = high-level operations
|
|
83
|
+
- `hetzner_client.rb` = HTTP calls
|
|
84
|
+
|
|
85
|
+
Merge into single file. The "client" is just private methods:
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
# external/cloud/hetzner.rb
|
|
89
|
+
module Nvoi
|
|
90
|
+
module External
|
|
91
|
+
module Cloud
|
|
92
|
+
class Hetzner < Base
|
|
93
|
+
def find_server(name) ... end # public
|
|
94
|
+
|
|
95
|
+
private
|
|
96
|
+
|
|
97
|
+
def get(path) ... end # HTTP helpers
|
|
98
|
+
def post(path, body) ... end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 2. Extract Common HTTP Client
|
|
106
|
+
|
|
107
|
+
All providers do similar HTTP work. Extract base:
|
|
108
|
+
|
|
109
|
+
```ruby
|
|
110
|
+
# external/cloud/base.rb
|
|
111
|
+
class Base
|
|
112
|
+
private
|
|
113
|
+
|
|
114
|
+
def http_get(url, headers = {}) ... end
|
|
115
|
+
def http_post(url, body, headers = {}) ... end
|
|
116
|
+
def handle_response(response) ... end
|
|
117
|
+
end
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 3. Provider Factory
|
|
121
|
+
|
|
122
|
+
Current `service/provider.rb` has `ProviderHelper` module. Move to:
|
|
123
|
+
|
|
124
|
+
```ruby
|
|
125
|
+
# external/cloud/factory.rb
|
|
126
|
+
module Nvoi
|
|
127
|
+
module External
|
|
128
|
+
module Cloud
|
|
129
|
+
def self.for(config)
|
|
130
|
+
case config.provider_name
|
|
131
|
+
when "hetzner" then Hetzner.new(config.hetzner.api_token)
|
|
132
|
+
when "aws" then AWS.new(config.aws)
|
|
133
|
+
when "scaleway" then Scaleway.new(config.scaleway)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### 4. Struct Extraction (already in 01-objects.md)
|
|
142
|
+
|
|
143
|
+
Remove `Server`, `Network`, etc. from `base.rb` → use from `objects/`
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Migration Steps
|
|
148
|
+
|
|
149
|
+
1. Create `lib/nvoi/external/cloud/` directory
|
|
150
|
+
2. Create `base.rb` with interface only (no Structs)
|
|
151
|
+
3. Merge `hetzner.rb` + `hetzner_client.rb` → `external/cloud/hetzner.rb`
|
|
152
|
+
4. Move `aws.rb` → `external/cloud/aws.rb`
|
|
153
|
+
5. Merge `scaleway.rb` + `scaleway_client.rb` → `external/cloud/scaleway.rb`
|
|
154
|
+
6. Move `service/provider.rb` → `external/cloud/factory.rb`
|
|
155
|
+
7. Update requires to use `Objects::Server`, etc.
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Estimated Effort
|
|
160
|
+
|
|
161
|
+
- **Lines to consolidate:** ~1380
|
|
162
|
+
- **Files created:** 5
|
|
163
|
+
- **Files deleted:** 7
|
|
164
|
+
- **DRY savings:** ~100 lines (merged clients, shared HTTP base)
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# 04 - External: DNS Provider (Cloudflare)
|
|
2
|
+
|
|
3
|
+
## Priority: THIRD (parallel with cloud)
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Current State
|
|
8
|
+
|
|
9
|
+
| File | Lines | Purpose |
|
|
10
|
+
| ---------------------------- | ----- | -------------------------- |
|
|
11
|
+
| `cloudflare/client.rb` | 288 | Cloudflare API client |
|
|
12
|
+
| `deployer/tunnel_manager.rb` | 58 | Tunnel setup orchestration |
|
|
13
|
+
|
|
14
|
+
**Total: ~346 lines across 2 files**
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Target Structure
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
lib/nvoi/external/dns/
|
|
22
|
+
└── cloudflare.rb # Full Cloudflare client (tunnels + DNS)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## What Cloudflare Client Does
|
|
28
|
+
|
|
29
|
+
### Tunnel Operations
|
|
30
|
+
|
|
31
|
+
- `create_tunnel(name)` → Tunnel
|
|
32
|
+
- `find_tunnel(name)` → Tunnel | nil
|
|
33
|
+
- `get_tunnel_token(tunnel_id)` → String
|
|
34
|
+
- `update_tunnel_configuration(tunnel_id, hostname, service_url)`
|
|
35
|
+
- `verify_tunnel_configuration(tunnel_id, hostname, service_url, attempts)`
|
|
36
|
+
- `delete_tunnel(tunnel_id)`
|
|
37
|
+
|
|
38
|
+
### DNS Operations
|
|
39
|
+
|
|
40
|
+
- `find_zone(domain)` → Zone | nil
|
|
41
|
+
- `find_dns_record(zone_id, name, type)` → DNSRecord | nil
|
|
42
|
+
- `create_dns_record(zone_id, name, type, content, proxied:)`
|
|
43
|
+
- `update_dns_record(zone_id, record_id, name, type, content, proxied:)`
|
|
44
|
+
- `create_or_update_dns_record(...)` → convenience method
|
|
45
|
+
- `delete_dns_record(zone_id, record_id)`
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## DRY Opportunities
|
|
50
|
+
|
|
51
|
+
### 1. Absorb TunnelManager into Cloudflare Client
|
|
52
|
+
|
|
53
|
+
`TunnelManager.setup_tunnel` does:
|
|
54
|
+
|
|
55
|
+
1. Find or create tunnel
|
|
56
|
+
2. Get token
|
|
57
|
+
3. Configure ingress
|
|
58
|
+
4. Verify configuration
|
|
59
|
+
5. Create DNS record
|
|
60
|
+
|
|
61
|
+
This is just a convenience method. Move into client:
|
|
62
|
+
|
|
63
|
+
```ruby
|
|
64
|
+
# external/dns/cloudflare.rb
|
|
65
|
+
class Cloudflare
|
|
66
|
+
# Existing low-level methods...
|
|
67
|
+
|
|
68
|
+
# High-level convenience
|
|
69
|
+
def setup_tunnel(name, hostname, service_url, domain)
|
|
70
|
+
tunnel = find_tunnel(name) || create_tunnel(name)
|
|
71
|
+
token = tunnel.token || get_tunnel_token(tunnel.id)
|
|
72
|
+
update_tunnel_configuration(tunnel.id, hostname, service_url)
|
|
73
|
+
verify_tunnel_configuration(tunnel.id, hostname, service_url, Constants::TUNNEL_CONFIG_VERIFY_ATTEMPTS)
|
|
74
|
+
|
|
75
|
+
zone = find_zone(domain)
|
|
76
|
+
create_or_update_dns_record(zone.id, hostname, "CNAME", "#{tunnel.id}.cfargotunnel.com")
|
|
77
|
+
|
|
78
|
+
Objects::TunnelInfo.new(tunnel_id: tunnel.id, tunnel_token: token)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### 2. Remove Struct Definitions
|
|
84
|
+
|
|
85
|
+
Move `Tunnel`, `Zone`, `DNSRecord` to `objects/` (done in 01-objects.md)
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Migration Steps
|
|
90
|
+
|
|
91
|
+
1. Create `lib/nvoi/external/dns/` directory
|
|
92
|
+
2. Move `cloudflare/client.rb` → `external/dns/cloudflare.rb`
|
|
93
|
+
3. Merge `deployer/tunnel_manager.rb` into Cloudflare as `setup_tunnel` method
|
|
94
|
+
4. Remove Struct definitions (use from `objects/`)
|
|
95
|
+
5. Update namespace from `Cloudflare::Client` to `External::DNS::Cloudflare`
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Estimated Effort
|
|
100
|
+
|
|
101
|
+
- **Lines to consolidate:** ~346
|
|
102
|
+
- **Files created:** 1
|
|
103
|
+
- **Files deleted:** 2
|
|
104
|
+
- **DRY savings:** ~20 lines (TunnelManager overhead)
|