nvoi 0.1.5 → 0.1.6
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/_target.md +79 -0
- data/.claude/todo/scaleway.impl.md +644 -0
- data/.claude/todo/scaleway.reference.md +520 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +12 -2
- 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/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 +49 -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 +100 -0
- data/lib/nvoi/cli/deploy/steps/deploy_service.rb +396 -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 +481 -0
- data/lib/nvoi/cli/exec/command.rb +173 -0
- data/lib/nvoi/cli.rb +83 -142
- 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/env.rb +32 -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/volume.rb +40 -0
- data/lib/nvoi/config_api/base.rb +44 -0
- data/lib/nvoi/config_api/result.rb +26 -0
- data/lib/nvoi/config_api.rb +70 -0
- data/lib/nvoi/errors.rb +68 -50
- data/lib/nvoi/external/cloud/aws.rb +425 -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 +376 -0
- data/lib/nvoi/external/cloud/scaleway.rb +533 -0
- data/lib/nvoi/external/cloud.rb +15 -0
- data/lib/nvoi/external/containerd.rb +82 -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 +292 -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 +463 -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} +28 -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 +10 -54
- data/templates/error-backend.yaml.erb +134 -0
- metadata +97 -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
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
# Scaleway API Reference Documentation
|
|
2
|
+
|
|
3
|
+
## 1. Authentication
|
|
4
|
+
|
|
5
|
+
- **Base URL**: `https://api.scaleway.com`
|
|
6
|
+
- **Auth Header**: `X-Auth-Token: <secret_key>` (NOT Bearer token)
|
|
7
|
+
- **Content-Type**: `application/json`
|
|
8
|
+
|
|
9
|
+
## 2. API Structure
|
|
10
|
+
|
|
11
|
+
Scaleway uses **zoned** and **regional** APIs:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
# Zoned APIs (Instances, Block Storage)
|
|
15
|
+
https://api.scaleway.com/instance/v1/zones/{zone}/servers
|
|
16
|
+
https://api.scaleway.com/block/v1alpha1/zones/{zone}/volumes
|
|
17
|
+
|
|
18
|
+
# Regional APIs (VPC/Private Networks)
|
|
19
|
+
https://api.scaleway.com/vpc/v2/regions/{region}/private-networks
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Zones
|
|
23
|
+
- `fr-par-1`, `fr-par-2`, `fr-par-3`
|
|
24
|
+
- `nl-ams-1`, `nl-ams-2`, `nl-ams-3`
|
|
25
|
+
- `pl-waw-1`, `pl-waw-2`, `pl-waw-3`
|
|
26
|
+
|
|
27
|
+
### Regions
|
|
28
|
+
- `fr-par` (Paris)
|
|
29
|
+
- `nl-ams` (Amsterdam)
|
|
30
|
+
- `pl-waw` (Warsaw)
|
|
31
|
+
|
|
32
|
+
### Zone to Region Mapping
|
|
33
|
+
- `fr-par-1`, `fr-par-2`, `fr-par-3` → `fr-par`
|
|
34
|
+
- `nl-ams-1`, `nl-ams-2`, `nl-ams-3` → `nl-ams`
|
|
35
|
+
- `pl-waw-1`, `pl-waw-2`, `pl-waw-3` → `pl-waw`
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 3. Servers (Instances) API
|
|
40
|
+
|
|
41
|
+
### Endpoints
|
|
42
|
+
|
|
43
|
+
| Operation | Method | Path |
|
|
44
|
+
|-----------|--------|------|
|
|
45
|
+
| List servers | GET | `/instance/v1/zones/{zone}/servers` |
|
|
46
|
+
| Get server | GET | `/instance/v1/zones/{zone}/servers/{id}` |
|
|
47
|
+
| Create server | POST | `/instance/v1/zones/{zone}/servers` |
|
|
48
|
+
| Delete server | DELETE | `/instance/v1/zones/{zone}/servers/{id}` |
|
|
49
|
+
| Server action | POST | `/instance/v1/zones/{zone}/servers/{id}/action` |
|
|
50
|
+
| List server types | GET | `/instance/v1/zones/{zone}/products/servers` |
|
|
51
|
+
| List images | GET | `/instance/v1/zones/{zone}/images` |
|
|
52
|
+
|
|
53
|
+
### Create Server Request Body
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"name": "my-server",
|
|
58
|
+
"commercial_type": "DEV1-S",
|
|
59
|
+
"image": "881d7a33-4cfa-4046-b5cf-c33cb9c62fb6",
|
|
60
|
+
"project": "697ef834-9bd0-4181-ae29-b0bcd0e574ae",
|
|
61
|
+
"enable_ipv6": false,
|
|
62
|
+
"boot_type": "local",
|
|
63
|
+
"tags": ["tag1", "tag2"],
|
|
64
|
+
"security_group": "sg-uuid"
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Server Response Structure
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"server": {
|
|
73
|
+
"id": "uuid",
|
|
74
|
+
"name": "my-server",
|
|
75
|
+
"state": "running",
|
|
76
|
+
"commercial_type": "DEV1-S",
|
|
77
|
+
"public_ip": {
|
|
78
|
+
"id": "ip-uuid",
|
|
79
|
+
"address": "51.15.x.x",
|
|
80
|
+
"dynamic": false
|
|
81
|
+
},
|
|
82
|
+
"private_ip": null,
|
|
83
|
+
"volumes": {},
|
|
84
|
+
"security_group": {
|
|
85
|
+
"id": "sg-uuid",
|
|
86
|
+
"name": "sg-name"
|
|
87
|
+
},
|
|
88
|
+
"tags": [],
|
|
89
|
+
"zone": "fr-par-1"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Server States
|
|
95
|
+
- `stopped`
|
|
96
|
+
- `stopping`
|
|
97
|
+
- `starting`
|
|
98
|
+
- `running`
|
|
99
|
+
- `locked`
|
|
100
|
+
|
|
101
|
+
### Server Action Request
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"action": "poweron"
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Available actions: `poweron`, `poweroff`, `reboot`, `terminate`
|
|
110
|
+
|
|
111
|
+
### List Server Types Response
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"servers": {
|
|
116
|
+
"DEV1-S": {
|
|
117
|
+
"monthly_price": 0.0,
|
|
118
|
+
"hourly_price": 0.0,
|
|
119
|
+
"alt_names": [],
|
|
120
|
+
"per_volume_constraint": {
|
|
121
|
+
"l_ssd": {
|
|
122
|
+
"min_size": 20000000000,
|
|
123
|
+
"max_size": 80000000000
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
"volumes_constraint": {
|
|
127
|
+
"min_size": 20000000000,
|
|
128
|
+
"max_size": 80000000000
|
|
129
|
+
},
|
|
130
|
+
"ncpus": 2,
|
|
131
|
+
"ram": 2147483648,
|
|
132
|
+
"arch": "x86_64",
|
|
133
|
+
"baremetal": false
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Common Commercial Types
|
|
140
|
+
- `DEV1-S`, `DEV1-M`, `DEV1-L`, `DEV1-XL`
|
|
141
|
+
- `GP1-XS`, `GP1-S`, `GP1-M`, `GP1-L`, `GP1-XL`
|
|
142
|
+
- `PRO2-XXS`, `PRO2-XS`, `PRO2-S`, `PRO2-M`, `PRO2-L`
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## 4. Security Groups API
|
|
147
|
+
|
|
148
|
+
### Endpoints
|
|
149
|
+
|
|
150
|
+
| Operation | Method | Path |
|
|
151
|
+
|-----------|--------|------|
|
|
152
|
+
| List | GET | `/instance/v1/zones/{zone}/security_groups` |
|
|
153
|
+
| Get | GET | `/instance/v1/zones/{zone}/security_groups/{id}` |
|
|
154
|
+
| Create | POST | `/instance/v1/zones/{zone}/security_groups` |
|
|
155
|
+
| Update | PUT | `/instance/v1/zones/{zone}/security_groups/{id}` |
|
|
156
|
+
| Delete | DELETE | `/instance/v1/zones/{zone}/security_groups/{id}` |
|
|
157
|
+
| List rules | GET | `/instance/v1/zones/{zone}/security_groups/{id}/rules` |
|
|
158
|
+
| Create rule | POST | `/instance/v1/zones/{zone}/security_groups/{id}/rules` |
|
|
159
|
+
| Delete rule | DELETE | `/instance/v1/zones/{zone}/security_groups/{id}/rules/{rule_id}` |
|
|
160
|
+
|
|
161
|
+
### Create Security Group Request
|
|
162
|
+
|
|
163
|
+
```json
|
|
164
|
+
{
|
|
165
|
+
"name": "my-firewall",
|
|
166
|
+
"description": "SSH access",
|
|
167
|
+
"organization": "org-uuid",
|
|
168
|
+
"project": "project-uuid",
|
|
169
|
+
"stateful": true,
|
|
170
|
+
"inbound_default_policy": "drop",
|
|
171
|
+
"outbound_default_policy": "accept",
|
|
172
|
+
"enable_default_security": true
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Security Group Response
|
|
177
|
+
|
|
178
|
+
```json
|
|
179
|
+
{
|
|
180
|
+
"security_group": {
|
|
181
|
+
"id": "uuid",
|
|
182
|
+
"name": "my-firewall",
|
|
183
|
+
"description": "SSH access",
|
|
184
|
+
"enable_default_security": true,
|
|
185
|
+
"inbound_default_policy": "drop",
|
|
186
|
+
"outbound_default_policy": "accept",
|
|
187
|
+
"organization": "org-uuid",
|
|
188
|
+
"project": "project-uuid",
|
|
189
|
+
"stateful": true,
|
|
190
|
+
"state": "available",
|
|
191
|
+
"servers": [],
|
|
192
|
+
"zone": "fr-par-1"
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Create Rule Request
|
|
198
|
+
|
|
199
|
+
```json
|
|
200
|
+
{
|
|
201
|
+
"protocol": "TCP",
|
|
202
|
+
"direction": "inbound",
|
|
203
|
+
"action": "accept",
|
|
204
|
+
"ip_range": "0.0.0.0/0",
|
|
205
|
+
"dest_port_from": 22,
|
|
206
|
+
"dest_port_to": 22,
|
|
207
|
+
"position": 1,
|
|
208
|
+
"editable": true
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Rule Protocols
|
|
213
|
+
- `TCP`
|
|
214
|
+
- `UDP`
|
|
215
|
+
- `ICMP`
|
|
216
|
+
- `ANY`
|
|
217
|
+
|
|
218
|
+
### Rule Directions
|
|
219
|
+
- `inbound`
|
|
220
|
+
- `outbound`
|
|
221
|
+
|
|
222
|
+
### Rule Actions
|
|
223
|
+
- `accept`
|
|
224
|
+
- `drop`
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## 5. Private Networks (VPC) API
|
|
229
|
+
|
|
230
|
+
### Endpoints
|
|
231
|
+
|
|
232
|
+
| Operation | Method | Path |
|
|
233
|
+
|-----------|--------|------|
|
|
234
|
+
| List | GET | `/vpc/v2/regions/{region}/private-networks` |
|
|
235
|
+
| Get | GET | `/vpc/v2/regions/{region}/private-networks/{id}` |
|
|
236
|
+
| Create | POST | `/vpc/v2/regions/{region}/private-networks` |
|
|
237
|
+
| Update | PATCH | `/vpc/v2/regions/{region}/private-networks/{id}` |
|
|
238
|
+
| Delete | DELETE | `/vpc/v2/regions/{region}/private-networks/{id}` |
|
|
239
|
+
|
|
240
|
+
### Create Private Network Request
|
|
241
|
+
|
|
242
|
+
```json
|
|
243
|
+
{
|
|
244
|
+
"name": "my-network",
|
|
245
|
+
"project_id": "project-uuid",
|
|
246
|
+
"subnets": ["10.0.1.0/24"],
|
|
247
|
+
"vpc_id": "vpc-uuid",
|
|
248
|
+
"tags": ["tag1"]
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Private Network Response
|
|
253
|
+
|
|
254
|
+
```json
|
|
255
|
+
{
|
|
256
|
+
"id": "pn-uuid",
|
|
257
|
+
"name": "my-network",
|
|
258
|
+
"organization_id": "org-uuid",
|
|
259
|
+
"project_id": "project-uuid",
|
|
260
|
+
"region": "fr-par",
|
|
261
|
+
"subnets": [
|
|
262
|
+
{
|
|
263
|
+
"id": "subnet-uuid",
|
|
264
|
+
"subnet": "10.0.1.0/24",
|
|
265
|
+
"created_at": "2024-01-01T00:00:00Z",
|
|
266
|
+
"updated_at": "2024-01-01T00:00:00Z"
|
|
267
|
+
}
|
|
268
|
+
],
|
|
269
|
+
"vpc_id": "vpc-uuid",
|
|
270
|
+
"dhcp_enabled": true,
|
|
271
|
+
"created_at": "2024-01-01T00:00:00Z",
|
|
272
|
+
"updated_at": "2024-01-01T00:00:00Z",
|
|
273
|
+
"tags": []
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### List Response
|
|
278
|
+
|
|
279
|
+
```json
|
|
280
|
+
{
|
|
281
|
+
"private_networks": [...],
|
|
282
|
+
"total_count": 1
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## 6. Private NICs API (Instance to Network Attachment)
|
|
289
|
+
|
|
290
|
+
### Endpoints
|
|
291
|
+
|
|
292
|
+
| Operation | Method | Path |
|
|
293
|
+
|-----------|--------|------|
|
|
294
|
+
| List | GET | `/instance/v1/zones/{zone}/servers/{server_id}/private_nics` |
|
|
295
|
+
| Get | GET | `/instance/v1/zones/{zone}/servers/{server_id}/private_nics/{nic_id}` |
|
|
296
|
+
| Create | POST | `/instance/v1/zones/{zone}/servers/{server_id}/private_nics` |
|
|
297
|
+
| Update | PATCH | `/instance/v1/zones/{zone}/servers/{server_id}/private_nics/{nic_id}` |
|
|
298
|
+
| Delete | DELETE | `/instance/v1/zones/{zone}/servers/{server_id}/private_nics/{nic_id}` |
|
|
299
|
+
|
|
300
|
+
### Create Private NIC Request
|
|
301
|
+
|
|
302
|
+
```json
|
|
303
|
+
{
|
|
304
|
+
"private_network_id": "pn-uuid",
|
|
305
|
+
"ip_ids": []
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Private NIC Response
|
|
310
|
+
|
|
311
|
+
```json
|
|
312
|
+
{
|
|
313
|
+
"private_nic": {
|
|
314
|
+
"id": "nic-uuid",
|
|
315
|
+
"server_id": "server-uuid",
|
|
316
|
+
"private_network_id": "pn-uuid",
|
|
317
|
+
"mac_address": "02:00:00:00:00:01",
|
|
318
|
+
"state": "available",
|
|
319
|
+
"tags": []
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### Private NIC States
|
|
325
|
+
- `available`
|
|
326
|
+
- `syncing`
|
|
327
|
+
- `syncing_error`
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## 7. Block Storage API
|
|
332
|
+
|
|
333
|
+
### Endpoints
|
|
334
|
+
|
|
335
|
+
| Operation | Method | Path |
|
|
336
|
+
|-----------|--------|------|
|
|
337
|
+
| List | GET | `/block/v1alpha1/zones/{zone}/volumes` |
|
|
338
|
+
| Get | GET | `/block/v1alpha1/zones/{zone}/volumes/{id}` |
|
|
339
|
+
| Create | POST | `/block/v1alpha1/zones/{zone}/volumes` |
|
|
340
|
+
| Update | PATCH | `/block/v1alpha1/zones/{zone}/volumes/{id}` |
|
|
341
|
+
| Delete | DELETE | `/block/v1alpha1/zones/{zone}/volumes/{id}` |
|
|
342
|
+
|
|
343
|
+
### Create Volume Request
|
|
344
|
+
|
|
345
|
+
```json
|
|
346
|
+
{
|
|
347
|
+
"name": "my-volume",
|
|
348
|
+
"perf_iops": 5000,
|
|
349
|
+
"from_empty": {
|
|
350
|
+
"size": 53687091200
|
|
351
|
+
},
|
|
352
|
+
"project_id": "project-uuid",
|
|
353
|
+
"tags": []
|
|
354
|
+
}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Volume Response
|
|
358
|
+
|
|
359
|
+
```json
|
|
360
|
+
{
|
|
361
|
+
"id": "vol-uuid",
|
|
362
|
+
"name": "my-volume",
|
|
363
|
+
"type": "sbs_5k",
|
|
364
|
+
"size": 53687091200,
|
|
365
|
+
"project_id": "project-uuid",
|
|
366
|
+
"zone": "fr-par-1",
|
|
367
|
+
"specs": {
|
|
368
|
+
"perf_iops": 5000,
|
|
369
|
+
"class": "sbs"
|
|
370
|
+
},
|
|
371
|
+
"status": "available",
|
|
372
|
+
"created_at": "2024-01-01T00:00:00Z",
|
|
373
|
+
"updated_at": "2024-01-01T00:00:00Z",
|
|
374
|
+
"references": [],
|
|
375
|
+
"parent_snapshot_id": null,
|
|
376
|
+
"tags": []
|
|
377
|
+
}
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
### Volume IOPS Options
|
|
381
|
+
- `5000` - Standard
|
|
382
|
+
- `15000` - High performance
|
|
383
|
+
|
|
384
|
+
### Volume Statuses
|
|
385
|
+
- `unknown_status`
|
|
386
|
+
- `creating`
|
|
387
|
+
- `available`
|
|
388
|
+
- `in_use`
|
|
389
|
+
- `deleting`
|
|
390
|
+
- `error`
|
|
391
|
+
- `snapshotting`
|
|
392
|
+
- `resizing`
|
|
393
|
+
- `locked`
|
|
394
|
+
|
|
395
|
+
### Attaching Volumes to Instances
|
|
396
|
+
|
|
397
|
+
Volume attachment is done via Instance API by updating the server's volumes:
|
|
398
|
+
|
|
399
|
+
```
|
|
400
|
+
PATCH /instance/v1/zones/{zone}/servers/{server_id}
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
```json
|
|
404
|
+
{
|
|
405
|
+
"volumes": {
|
|
406
|
+
"0": {
|
|
407
|
+
"id": "root-volume-uuid"
|
|
408
|
+
},
|
|
409
|
+
"1": {
|
|
410
|
+
"id": "block-volume-uuid"
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
**Important Notes:**
|
|
417
|
+
- Since April 2024, Block API cannot create volumes attached to instances
|
|
418
|
+
- Volumes must be attached via Instance API
|
|
419
|
+
- Include ALL volumes (including root) when updating
|
|
420
|
+
|
|
421
|
+
---
|
|
422
|
+
|
|
423
|
+
## 8. VPC API
|
|
424
|
+
|
|
425
|
+
### Endpoints
|
|
426
|
+
|
|
427
|
+
| Operation | Method | Path |
|
|
428
|
+
|-----------|--------|------|
|
|
429
|
+
| List | GET | `/vpc/v2/regions/{region}/vpcs` |
|
|
430
|
+
| Get | GET | `/vpc/v2/regions/{region}/vpcs/{id}` |
|
|
431
|
+
| Create | POST | `/vpc/v2/regions/{region}/vpcs` |
|
|
432
|
+
| Update | PATCH | `/vpc/v2/regions/{region}/vpcs/{id}` |
|
|
433
|
+
| Delete | DELETE | `/vpc/v2/regions/{region}/vpcs/{id}` |
|
|
434
|
+
|
|
435
|
+
### Create VPC Request
|
|
436
|
+
|
|
437
|
+
```json
|
|
438
|
+
{
|
|
439
|
+
"name": "my-vpc",
|
|
440
|
+
"project_id": "project-uuid",
|
|
441
|
+
"tags": [],
|
|
442
|
+
"enable_routing": true
|
|
443
|
+
}
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### VPC Response
|
|
447
|
+
|
|
448
|
+
```json
|
|
449
|
+
{
|
|
450
|
+
"id": "vpc-uuid",
|
|
451
|
+
"name": "my-vpc",
|
|
452
|
+
"organization_id": "org-uuid",
|
|
453
|
+
"project_id": "project-uuid",
|
|
454
|
+
"region": "fr-par",
|
|
455
|
+
"tags": [],
|
|
456
|
+
"is_default": false,
|
|
457
|
+
"routing_enabled": true,
|
|
458
|
+
"created_at": "2024-01-01T00:00:00Z",
|
|
459
|
+
"updated_at": "2024-01-01T00:00:00Z",
|
|
460
|
+
"private_network_count": 0
|
|
461
|
+
}
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
|
|
466
|
+
## 9. Error Response Format
|
|
467
|
+
|
|
468
|
+
```json
|
|
469
|
+
{
|
|
470
|
+
"type": "invalid_request_error",
|
|
471
|
+
"message": "Validation Error",
|
|
472
|
+
"fields": {
|
|
473
|
+
"name": ["name is required"]
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
### HTTP Status Codes
|
|
479
|
+
- `200` - Success
|
|
480
|
+
- `201` - Created
|
|
481
|
+
- `204` - No Content (successful delete)
|
|
482
|
+
- `400` - Bad Request
|
|
483
|
+
- `401` - Unauthorized
|
|
484
|
+
- `403` - Forbidden
|
|
485
|
+
- `404` - Not Found
|
|
486
|
+
- `409` - Conflict
|
|
487
|
+
- `422` - Unprocessable Entity
|
|
488
|
+
- `429` - Rate Limited
|
|
489
|
+
- `500` - Internal Server Error
|
|
490
|
+
|
|
491
|
+
---
|
|
492
|
+
|
|
493
|
+
## 10. Pagination
|
|
494
|
+
|
|
495
|
+
List endpoints support pagination:
|
|
496
|
+
|
|
497
|
+
```
|
|
498
|
+
GET /instance/v1/zones/{zone}/servers?page=1&per_page=50
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
Response includes:
|
|
502
|
+
```json
|
|
503
|
+
{
|
|
504
|
+
"servers": [...],
|
|
505
|
+
"total_count": 100
|
|
506
|
+
}
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
---
|
|
510
|
+
|
|
511
|
+
## 11. Sources
|
|
512
|
+
|
|
513
|
+
- [Scaleway Instance API](https://www.scaleway.com/en/developers/api/instances/)
|
|
514
|
+
- [Scaleway VPC API](https://www.scaleway.com/en/developers/api/vpc/)
|
|
515
|
+
- [Scaleway Block Storage API](https://www.scaleway.com/en/developers/api/block/)
|
|
516
|
+
- [Scaleway CLI - Instance](https://cli.scaleway.com/instance/)
|
|
517
|
+
- [Scaleway CLI - VPC](https://cli.scaleway.com/vpc/)
|
|
518
|
+
- [Scaleway CLI - Block](https://cli.scaleway.com/block/)
|
|
519
|
+
- [Security Groups API Reference](https://bump.sh/demo/hub/scaleway-developers/doc/instance-v1/group/endpoint-security-groups)
|
|
520
|
+
- [Scaleway API Overview](https://www.scaleway.com/en/developers/api/)
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
nvoi (0.1.
|
|
4
|
+
nvoi (0.1.6)
|
|
5
5
|
aws-sdk-ec2 (~> 1.400)
|
|
6
6
|
faraday (~> 2.7)
|
|
7
7
|
net-scp (~> 4.0)
|
|
8
8
|
net-ssh (~> 7.2)
|
|
9
9
|
thor (~> 1.3)
|
|
10
|
+
zeitwerk (~> 2.6)
|
|
10
11
|
|
|
11
12
|
GEM
|
|
12
13
|
remote: https://rubygems.org/
|
|
@@ -28,7 +29,7 @@ GEM
|
|
|
28
29
|
public_suffix (>= 2.0.2, < 8.0)
|
|
29
30
|
ast (2.4.3)
|
|
30
31
|
aws-eventstream (1.4.0)
|
|
31
|
-
aws-partitions (1.
|
|
32
|
+
aws-partitions (1.1192.0)
|
|
32
33
|
aws-sdk-core (3.239.2)
|
|
33
34
|
aws-eventstream (~> 1, >= 1.3.0)
|
|
34
35
|
aws-partitions (~> 1, >= 1.992.0)
|
|
@@ -49,6 +50,7 @@ GEM
|
|
|
49
50
|
crack (1.0.1)
|
|
50
51
|
bigdecimal
|
|
51
52
|
rexml
|
|
53
|
+
docile (1.4.1)
|
|
52
54
|
drb (2.2.3)
|
|
53
55
|
faraday (2.14.0)
|
|
54
56
|
faraday-net_http (>= 2.0, < 3.5)
|
|
@@ -112,6 +114,12 @@ GEM
|
|
|
112
114
|
rubocop-rails (>= 2.30)
|
|
113
115
|
ruby-progressbar (1.13.0)
|
|
114
116
|
securerandom (0.4.1)
|
|
117
|
+
simplecov (0.22.0)
|
|
118
|
+
docile (~> 1.1)
|
|
119
|
+
simplecov-html (~> 0.11)
|
|
120
|
+
simplecov_json_formatter (~> 0.1)
|
|
121
|
+
simplecov-html (0.13.2)
|
|
122
|
+
simplecov_json_formatter (0.1.4)
|
|
115
123
|
thor (1.4.0)
|
|
116
124
|
tzinfo (2.0.6)
|
|
117
125
|
concurrent-ruby (~> 1.0)
|
|
@@ -123,6 +131,7 @@ GEM
|
|
|
123
131
|
addressable (>= 2.8.0)
|
|
124
132
|
crack (>= 0.3.2)
|
|
125
133
|
hashdiff (>= 0.4.0, < 2.0.0)
|
|
134
|
+
zeitwerk (2.7.3)
|
|
126
135
|
|
|
127
136
|
PLATFORMS
|
|
128
137
|
aarch64-linux-gnu
|
|
@@ -145,6 +154,7 @@ DEPENDENCIES
|
|
|
145
154
|
rake (~> 13.0)
|
|
146
155
|
rubocop (~> 1.57)
|
|
147
156
|
rubocop-rails-omakase
|
|
157
|
+
simplecov
|
|
148
158
|
webmock (~> 3.19)
|
|
149
159
|
|
|
150
160
|
BUNDLED WITH
|
data/doc/config-schema.yaml
CHANGED
|
@@ -187,6 +187,27 @@ components:
|
|
|
187
187
|
minimum: 1
|
|
188
188
|
default: 1
|
|
189
189
|
example: 2
|
|
190
|
+
volumes:
|
|
191
|
+
type: object
|
|
192
|
+
description: Block storage volumes attached to this server (key is volume name)
|
|
193
|
+
additionalProperties:
|
|
194
|
+
$ref: "#/components/schemas/ServerVolumeConfig"
|
|
195
|
+
example:
|
|
196
|
+
database:
|
|
197
|
+
size: 20
|
|
198
|
+
uploads:
|
|
199
|
+
size: 10
|
|
200
|
+
|
|
201
|
+
ServerVolumeConfig:
|
|
202
|
+
type: object
|
|
203
|
+
description: Server-attached volume configuration
|
|
204
|
+
properties:
|
|
205
|
+
size:
|
|
206
|
+
type: integer
|
|
207
|
+
description: Volume size in GB
|
|
208
|
+
minimum: 10
|
|
209
|
+
default: 10
|
|
210
|
+
example: 20
|
|
190
211
|
|
|
191
212
|
AppServiceConfig:
|
|
192
213
|
type: object
|
|
@@ -227,13 +248,15 @@ components:
|
|
|
227
248
|
description: Service-specific environment variables
|
|
228
249
|
additionalProperties:
|
|
229
250
|
type: string
|
|
230
|
-
|
|
251
|
+
mounts:
|
|
231
252
|
type: object
|
|
232
|
-
description:
|
|
253
|
+
description: |
|
|
254
|
+
Mount server volumes into the container.
|
|
255
|
+
Key is volume name (must exist in server's volumes), value is container mount path.
|
|
256
|
+
Note: Services with mounts can only run on a single server.
|
|
233
257
|
additionalProperties:
|
|
234
258
|
type: string
|
|
235
259
|
example:
|
|
236
|
-
data: /app/data
|
|
237
260
|
uploads: /app/public/uploads
|
|
238
261
|
|
|
239
262
|
HealthCheckConfig:
|
|
@@ -294,10 +317,15 @@ components:
|
|
|
294
317
|
type: string
|
|
295
318
|
description: Docker image for database (managed databases only)
|
|
296
319
|
example: postgres:15-alpine
|
|
297
|
-
|
|
298
|
-
type:
|
|
299
|
-
description:
|
|
300
|
-
|
|
320
|
+
mount:
|
|
321
|
+
type: object
|
|
322
|
+
description: |
|
|
323
|
+
Mount a server volume for database data persistence.
|
|
324
|
+
Key is volume name (must exist in server's volumes), value is container mount path.
|
|
325
|
+
additionalProperties:
|
|
326
|
+
type: string
|
|
327
|
+
example:
|
|
328
|
+
database: /var/lib/postgresql/data
|
|
301
329
|
secrets:
|
|
302
330
|
type: object
|
|
303
331
|
description: Database secrets (POSTGRES_PASSWORD, etc.)
|
|
@@ -331,10 +359,15 @@ components:
|
|
|
331
359
|
description: Service environment variables
|
|
332
360
|
additionalProperties:
|
|
333
361
|
type: string
|
|
334
|
-
|
|
335
|
-
type:
|
|
336
|
-
description:
|
|
337
|
-
|
|
362
|
+
mount:
|
|
363
|
+
type: object
|
|
364
|
+
description: |
|
|
365
|
+
Mount a server volume for data persistence.
|
|
366
|
+
Key is volume name (must exist in server's volumes), value is container mount path.
|
|
367
|
+
additionalProperties:
|
|
368
|
+
type: string
|
|
369
|
+
example:
|
|
370
|
+
redis_data: /data
|
|
338
371
|
|
|
339
372
|
SSHKeyConfig:
|
|
340
373
|
type: object
|
data/examples/golang/deploy.enc
CHANGED
|
Binary file
|
data/examples/golang/main.go
CHANGED
|
@@ -97,6 +97,9 @@ func setupRouter() *gin.Engine {
|
|
|
97
97
|
// Main endpoint: creates user on every visit, returns all users
|
|
98
98
|
router.GET("/", handleVisit)
|
|
99
99
|
|
|
100
|
+
// Test custom error pages (nginx intercepts 502, 503, 504)
|
|
101
|
+
router.GET("/error/:code", handleError)
|
|
102
|
+
|
|
100
103
|
return router
|
|
101
104
|
}
|
|
102
105
|
|
|
@@ -164,6 +167,21 @@ func handleVisit(c *gin.Context) {
|
|
|
164
167
|
})
|
|
165
168
|
}
|
|
166
169
|
|
|
170
|
+
// Error handler for testing custom error pages (nginx intercepts 502, 503, 504)
|
|
171
|
+
func handleError(c *gin.Context) {
|
|
172
|
+
code := c.Param("code")
|
|
173
|
+
switch code {
|
|
174
|
+
case "502":
|
|
175
|
+
c.AbortWithStatus(http.StatusBadGateway)
|
|
176
|
+
case "503":
|
|
177
|
+
c.AbortWithStatus(http.StatusServiceUnavailable)
|
|
178
|
+
case "504":
|
|
179
|
+
c.AbortWithStatus(http.StatusGatewayTimeout)
|
|
180
|
+
default:
|
|
181
|
+
c.JSON(http.StatusOK, gin.H{"usage": "/error/{502,503,504}"})
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
167
185
|
// Generate random name for demo purposes
|
|
168
186
|
func generateRandomName() string {
|
|
169
187
|
firstNames := []string{"Alice", "Bob", "Charlie", "Diana", "Eve", "Frank", "Grace", "Henry", "Ivy", "Jack"}
|