docker-swarm 0.5.4 → 0.7.0
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/CHANGELOG.md +121 -0
- data/LICENSE +21 -0
- data/README.md +32 -105
- data/docs/behavior/behavior.md +243 -0
- data/docs/glossary/glossary.md +141 -0
- data/lib/docker_swarm/base.rb +11 -19
- data/lib/docker_swarm/connection.rb +14 -7
- data/lib/docker_swarm/log_helper.rb +3 -1
- data/lib/docker_swarm/models/service.rb +9 -0
- data/lib/docker_swarm/version.rb +1 -1
- data/skill/SKILL.md +130 -183
- metadata +15 -12
- data/skill/references/api-detallada.md +0 -246
- data/skill/references/errores.md +0 -157
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: docker-swarm
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Gabriel
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: activesupport
|
|
@@ -88,7 +87,11 @@ executables: []
|
|
|
88
87
|
extensions: []
|
|
89
88
|
extra_rdoc_files: []
|
|
90
89
|
files:
|
|
90
|
+
- CHANGELOG.md
|
|
91
|
+
- LICENSE
|
|
91
92
|
- README.md
|
|
93
|
+
- docs/behavior/behavior.md
|
|
94
|
+
- docs/glossary/glossary.md
|
|
92
95
|
- lib/docker-swarm.rb
|
|
93
96
|
- lib/docker_swarm.rb
|
|
94
97
|
- lib/docker_swarm/api.rb
|
|
@@ -118,15 +121,16 @@ files:
|
|
|
118
121
|
- lib/docker_swarm/models/volume.rb
|
|
119
122
|
- lib/docker_swarm/version.rb
|
|
120
123
|
- skill/SKILL.md
|
|
121
|
-
|
|
122
|
-
- skill/references/errores.md
|
|
123
|
-
homepage: https://github.com/wispro/docker-swarm
|
|
124
|
+
homepage: https://github.com/gedera/docker-swarm
|
|
124
125
|
licenses:
|
|
125
126
|
- MIT
|
|
126
127
|
metadata:
|
|
127
|
-
homepage_uri: https://github.com/
|
|
128
|
-
source_code_uri: https://github.com/
|
|
129
|
-
|
|
128
|
+
homepage_uri: https://github.com/gedera/docker-swarm
|
|
129
|
+
source_code_uri: https://github.com/gedera/docker-swarm
|
|
130
|
+
changelog_uri: https://github.com/gedera/docker-swarm/blob/v0.7.0/CHANGELOG.md
|
|
131
|
+
bug_tracker_uri: https://github.com/gedera/docker-swarm/issues
|
|
132
|
+
documentation_uri: https://github.com/gedera/docker-swarm/blob/v0.7.0/skill/SKILL.md
|
|
133
|
+
rubygems_mfa_required: 'true'
|
|
130
134
|
rdoc_options: []
|
|
131
135
|
require_paths:
|
|
132
136
|
- lib
|
|
@@ -134,15 +138,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
134
138
|
requirements:
|
|
135
139
|
- - ">="
|
|
136
140
|
- !ruby/object:Gem::Version
|
|
137
|
-
version: 2.
|
|
141
|
+
version: 3.2.0
|
|
138
142
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
139
143
|
requirements:
|
|
140
144
|
- - ">="
|
|
141
145
|
- !ruby/object:Gem::Version
|
|
142
146
|
version: '0'
|
|
143
147
|
requirements: []
|
|
144
|
-
rubygems_version: 3.
|
|
145
|
-
signing_key:
|
|
148
|
+
rubygems_version: 3.6.7
|
|
146
149
|
specification_version: 4
|
|
147
150
|
summary: A Ruby ORM and API client for Docker Swarm.
|
|
148
151
|
test_files: []
|
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
# API Detallada
|
|
2
|
-
|
|
3
|
-
Referencia completa de modelos, concerns, middleware y métodos públicos de DockerSwarm.
|
|
4
|
-
|
|
5
|
-
## Modelos — Tabla de capacidades
|
|
6
|
-
|
|
7
|
-
| Modelo | Creatable | Updatable | Deletable | Loggable | Extra |
|
|
8
|
-
|--------|-----------|-----------|-----------|----------|-------|
|
|
9
|
-
| Service | x | x | x | x | Ciclo de vida completo |
|
|
10
|
-
| Node | | x | x | | Miembros del cluster, no se crean |
|
|
11
|
-
| Task | | | | x | Read-only, generados por services |
|
|
12
|
-
| Container | | | x | x | `#start`, `#stop` |
|
|
13
|
-
| Network | x | x | x | | CRUD completo |
|
|
14
|
-
| Volume | x | | x | | `root_key = "Volumes"` |
|
|
15
|
-
| Config | x | | x | | Configuración del cluster |
|
|
16
|
-
| Secret | x | | x | | Datos sensibles |
|
|
17
|
-
| Image | x | | x | | Pull/removal |
|
|
18
|
-
| Swarm | | | | | `.show` (estático) |
|
|
19
|
-
| System | | | | | `.info`, `.version`, `.up`, `.df` |
|
|
20
|
-
|
|
21
|
-
## Base — Métodos de clase
|
|
22
|
-
|
|
23
|
-
```ruby
|
|
24
|
-
# Listar todos (con filtros opcionales)
|
|
25
|
-
# @param filters [Hash] Filtros Docker (label:, name:, id:, role:, etc.)
|
|
26
|
-
# @return [Array<Model>]
|
|
27
|
-
Model.all(filters = {})
|
|
28
|
-
|
|
29
|
-
# Alias de .all
|
|
30
|
-
Model.where(filters)
|
|
31
|
-
|
|
32
|
-
# Buscar por ID (retorna nil si 404)
|
|
33
|
-
# @param id [String]
|
|
34
|
-
# @return [Model, nil]
|
|
35
|
-
Model.find(id)
|
|
36
|
-
|
|
37
|
-
# Nombre del recurso pluralizado (ej: "services", "nodes")
|
|
38
|
-
Model.resource_name
|
|
39
|
-
|
|
40
|
-
# Endpoints del modelo desde Api::ENDPOINTS
|
|
41
|
-
Model.routes
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### Filtros soportados
|
|
45
|
-
|
|
46
|
-
```ruby
|
|
47
|
-
# Filtros Docker se serializan como JSON en query param `filters`
|
|
48
|
-
DockerSwarm::Service.all(label: ["app=web"], name: ["my-service"])
|
|
49
|
-
DockerSwarm::Container.all(status: ["running"])
|
|
50
|
-
DockerSwarm::Node.all(role: ["manager"])
|
|
51
|
-
|
|
52
|
-
# Parámetros globales (no van en filters)
|
|
53
|
-
DockerSwarm::Image.all(all: true) # incluir intermedias
|
|
54
|
-
DockerSwarm::Container.all(limit: 10) # limitar resultados
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
## Base — Métodos de instancia
|
|
58
|
-
|
|
59
|
-
```ruby
|
|
60
|
-
# ID del recurso
|
|
61
|
-
# @return [String]
|
|
62
|
-
model.id
|
|
63
|
-
|
|
64
|
-
# Hash de atributos (excluye internos de ActiveModel)
|
|
65
|
-
# @return [Hash]
|
|
66
|
-
model.attributes
|
|
67
|
-
|
|
68
|
-
# Recarga desde Docker API
|
|
69
|
-
# @return [self]
|
|
70
|
-
model.reload
|
|
71
|
-
|
|
72
|
-
# Prepara payload para Docker (excluye ID, Version, CreatedAt, extrae Spec)
|
|
73
|
-
# @return [Hash]
|
|
74
|
-
model.payload_for_docker
|
|
75
|
-
|
|
76
|
-
# Persistido? (tiene ID)
|
|
77
|
-
# @return [Boolean]
|
|
78
|
-
model.persisted?
|
|
79
|
-
|
|
80
|
-
# Inspección legible: #<DockerSwarm::Service ID: abc, Name: web, Image: nginx>
|
|
81
|
-
model.inspect
|
|
82
|
-
|
|
83
|
-
# Serialización
|
|
84
|
-
model.as_json
|
|
85
|
-
model.serializable_hash
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
## Concern: Creatable
|
|
89
|
-
|
|
90
|
-
Incluido en: Service, Network, Volume, Config, Secret, Image.
|
|
91
|
-
|
|
92
|
-
```ruby
|
|
93
|
-
# Crear y persistir
|
|
94
|
-
# @param attributes [Hash] Atributos PascalCase
|
|
95
|
-
# @return [Model] instancia (con ID si exitoso)
|
|
96
|
-
Model.create(attributes)
|
|
97
|
-
|
|
98
|
-
# Persistir instancia nueva (o delegar a update si persisted?)
|
|
99
|
-
# @return [Boolean] false si validación falla
|
|
100
|
-
model.save
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
Flujo interno de `save`: `valid?` → `Api.request(:create, payload_for_docker)` → asigna ID de response → `reload`.
|
|
104
|
-
|
|
105
|
-
## Concern: Updatable
|
|
106
|
-
|
|
107
|
-
Incluido en: Service, Node, Network.
|
|
108
|
-
|
|
109
|
-
```ruby
|
|
110
|
-
# Actualizar recurso persistido
|
|
111
|
-
# @param new_attributes [Hash] Atributos a mergear
|
|
112
|
-
# @return [Boolean] false si validación falla
|
|
113
|
-
model.update(new_attributes = {})
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
Flujo interno: `assign_attributes` (deep_merge en Spec) → `valid?` → `Api.request(:update, id:, version: Version["Index"], payload:)`.
|
|
117
|
-
|
|
118
|
-
**Importante:** El query param `version` se extrae automáticamente de `self.Version["Index"]`. Sin esto, Docker rechaza el update con 500.
|
|
119
|
-
|
|
120
|
-
## Concern: Deletable
|
|
121
|
-
|
|
122
|
-
Incluido en: Service, Node, Container, Network, Volume, Config, Secret, Image.
|
|
123
|
-
|
|
124
|
-
```ruby
|
|
125
|
-
# Eliminar por instancia
|
|
126
|
-
# @return [true, nil] nil si ya no existía (404 graceful)
|
|
127
|
-
model.destroy
|
|
128
|
-
|
|
129
|
-
# Eliminar por ID (class method)
|
|
130
|
-
# @return [true, nil]
|
|
131
|
-
Model.destroy(id)
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
## Concern: Loggable
|
|
135
|
-
|
|
136
|
-
Incluido en: Service, Task, Container.
|
|
137
|
-
|
|
138
|
-
```ruby
|
|
139
|
-
# Obtener logs del recurso
|
|
140
|
-
# @param query_params [Hash] stdout:, stderr:, follow:, tail:, since:, timestamps:
|
|
141
|
-
# @return [String] Raw log stream
|
|
142
|
-
model.logs(query_params = { stdout: 1, stderr: 1 })
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
## Container — Métodos específicos
|
|
146
|
-
|
|
147
|
-
```ruby
|
|
148
|
-
container = DockerSwarm::Container.find("container_id")
|
|
149
|
-
|
|
150
|
-
# Iniciar contenedor detenido
|
|
151
|
-
# @return [Boolean]
|
|
152
|
-
container.start
|
|
153
|
-
|
|
154
|
-
# Detener contenedor en ejecución
|
|
155
|
-
# @return [Boolean]
|
|
156
|
-
container.stop
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
## System — Métodos estáticos
|
|
160
|
-
|
|
161
|
-
```ruby
|
|
162
|
-
# Ping al daemon
|
|
163
|
-
# @return [String] "OK"
|
|
164
|
-
DockerSwarm::System.up
|
|
165
|
-
|
|
166
|
-
# Información del daemon
|
|
167
|
-
# @return [Hash] (Containers, Images, Driver, MemoryLimit, etc.)
|
|
168
|
-
DockerSwarm::System.info
|
|
169
|
-
|
|
170
|
-
# Versión de Docker
|
|
171
|
-
# @return [Hash] (Version, ApiVersion, Os, Arch, etc.)
|
|
172
|
-
DockerSwarm::System.version
|
|
173
|
-
|
|
174
|
-
# Uso de disco
|
|
175
|
-
# @return [Hash] (LayersSize, Images, Containers, Volumes)
|
|
176
|
-
DockerSwarm::System.df
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
## Swarm — Método estático
|
|
180
|
-
|
|
181
|
-
```ruby
|
|
182
|
-
# Información del cluster Swarm
|
|
183
|
-
# @return [Hash] (ID, Version, Spec, JoinTokens, etc.)
|
|
184
|
-
DockerSwarm::Swarm.show
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
## Volume — Particularidad
|
|
188
|
-
|
|
189
|
-
Volume sobreescribe `root_key` porque Docker envuelve la respuesta en `{"Volumes": [...]}`:
|
|
190
|
-
|
|
191
|
-
```ruby
|
|
192
|
-
class Volume < Base
|
|
193
|
-
def self.root_key = "Volumes"
|
|
194
|
-
end
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
## Api — Bajo nivel
|
|
198
|
-
|
|
199
|
-
```ruby
|
|
200
|
-
# Request directo al Docker API
|
|
201
|
-
# @param action [Hash] {method:, path:} desde ENDPOINTS
|
|
202
|
-
# @param arguments [Hash] Interpolación en path (id:)
|
|
203
|
-
# @param query_params [Hash] Query string
|
|
204
|
-
# @param payload [Hash, nil] Body del request
|
|
205
|
-
DockerSwarm::Api.request(action:, arguments: {}, query_params: {}, payload: nil)
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
### Endpoints registrados
|
|
209
|
-
|
|
210
|
-
Todos definidos en `Api::ENDPOINTS` como Hash frozen:
|
|
211
|
-
|
|
212
|
-
| Recurso | Acciones |
|
|
213
|
-
|---------|----------|
|
|
214
|
-
| swarm | show |
|
|
215
|
-
| system | info, version, up, df |
|
|
216
|
-
| nodes | index, show, update, destroy |
|
|
217
|
-
| tasks | index, show, logs |
|
|
218
|
-
| services | index, show, create, update, destroy, logs |
|
|
219
|
-
| configs | index, show, create, destroy |
|
|
220
|
-
| secrets | index, show, create, destroy |
|
|
221
|
-
| networks | index, show, create, update, destroy |
|
|
222
|
-
| volumes | index, show, create, destroy |
|
|
223
|
-
| containers | index, show, create, start, stop, destroy, logs |
|
|
224
|
-
| images | index, show, create, destroy |
|
|
225
|
-
|
|
226
|
-
## Middleware Stack
|
|
227
|
-
|
|
228
|
-
Orden de ejecución en Excon:
|
|
229
|
-
|
|
230
|
-
1. **Excon defaults** (Retry, Instrumentor, etc.)
|
|
231
|
-
2. **Excon::Middleware::RedirectFollower**
|
|
232
|
-
3. **RequestEncoder** — Serializa body: JSON (default), form-urlencoded, multipart. Detecta por Content-Type header.
|
|
233
|
-
4. **ResponseJSONParser** — Parsea JSON si Content-Type incluye `application/json`. Aplica `with_indifferent_access` recursivo (Hash y Array de Hashes).
|
|
234
|
-
5. **ErrorHandler** — Status 4xx/5xx → excepción tipada. Loguea `business_error` antes de raise.
|
|
235
|
-
|
|
236
|
-
## Configuración
|
|
237
|
-
|
|
238
|
-
| Opción | Tipo | Default | Descripción |
|
|
239
|
-
|--------|------|---------|-------------|
|
|
240
|
-
| `socket_path` | String | `unix:///var/run/docker.sock` | Socket Unix o URL TCP |
|
|
241
|
-
| `logger` | Logger | `Logger.new($stdout)` | Logger para KV output |
|
|
242
|
-
| `log_level` | Integer | `Logger::INFO` | Nivel de log (se aplica al logger) |
|
|
243
|
-
| `read_timeout` | Float | `60.0` | Timeout lectura (segundos) |
|
|
244
|
-
| `write_timeout` | Float | `60.0` | Timeout escritura (segundos) |
|
|
245
|
-
| `connect_timeout` | Float | `10.0` | Timeout conexión (segundos) |
|
|
246
|
-
| `max_retries` | Integer | `3` | Reintentos en Socket/Timeout errors |
|
data/skill/references/errores.md
DELETED
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
# Catálogo de Errores
|
|
2
|
-
|
|
3
|
-
Referencia completa de excepciones de DockerSwarm. Todas heredan de `DockerSwarm::Error`.
|
|
4
|
-
|
|
5
|
-
## Jerarquía
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
DockerSwarm::Error (base)
|
|
9
|
-
├── BadRequest (400)
|
|
10
|
-
├── Unauthorized (401)
|
|
11
|
-
├── Forbidden (403)
|
|
12
|
-
├── NotFound (404)
|
|
13
|
-
├── NotAcceptable (406)
|
|
14
|
-
├── RequestTimeout (408)
|
|
15
|
-
├── Conflict (409)
|
|
16
|
-
├── UnprocessableEntity (422)
|
|
17
|
-
├── TooManyRequests (429)
|
|
18
|
-
├── InternalServerError (500)
|
|
19
|
-
├── BadGateway (502)
|
|
20
|
-
├── ServiceUnavailable (503)
|
|
21
|
-
├── GatewayTimeout (504)
|
|
22
|
-
└── Communication (socket/red)
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## Acceso
|
|
26
|
-
|
|
27
|
-
Cada excepción tiene 3 formas de acceso equivalentes:
|
|
28
|
-
|
|
29
|
-
```ruby
|
|
30
|
-
DockerSwarm::NotFound # alias directo (recomendado)
|
|
31
|
-
DockerSwarm::Error::NotFound # acceso via clase Error
|
|
32
|
-
DockerSwarm::Errors::NotFound # módulo Errors (const_missing dinámico)
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## Catálogo completo
|
|
36
|
-
|
|
37
|
-
### BadRequest (400)
|
|
38
|
-
|
|
39
|
-
**Causa:** Payload malformado o parámetros inválidos.
|
|
40
|
-
**Reproducción:** Enviar JSON con campos incorrectos (ej: `Replicas: "abc"` en vez de integer).
|
|
41
|
-
**Resolución:** Validar payload contra la documentación de Docker API. Verificar tipos de datos.
|
|
42
|
-
|
|
43
|
-
### Unauthorized (401)
|
|
44
|
-
|
|
45
|
-
**Causa:** Credenciales inválidas o ausentes para Docker daemon con TLS.
|
|
46
|
-
**Reproducción:** Conectar a daemon protegido sin certificados.
|
|
47
|
-
**Resolución:** Configurar TLS client certificates en Excon o en la URL de conexión.
|
|
48
|
-
|
|
49
|
-
### Forbidden (403)
|
|
50
|
-
|
|
51
|
-
**Causa:** Permisos insuficientes para la operación.
|
|
52
|
-
**Reproducción:** Intentar operación de swarm en un nodo worker.
|
|
53
|
-
**Resolución:** Verificar que el nodo es manager y que el usuario tiene permisos sobre el socket.
|
|
54
|
-
|
|
55
|
-
### NotFound (404)
|
|
56
|
-
|
|
57
|
-
**Causa:** Recurso no existe o fue eliminado.
|
|
58
|
-
**Reproducción:** `Service.find("id_inexistente")`.
|
|
59
|
-
**Resolución:** `Base.find` retorna `nil` automáticamente. `Deletable#destroy` también es graceful (retorna `nil` en 404). No requiere rescue manual en estos casos.
|
|
60
|
-
|
|
61
|
-
### NotAcceptable (406)
|
|
62
|
-
|
|
63
|
-
**Causa:** El servidor no puede producir una respuesta aceptable.
|
|
64
|
-
**Reproducción:** Raro en Docker API.
|
|
65
|
-
**Resolución:** Verificar headers Accept del request.
|
|
66
|
-
|
|
67
|
-
### RequestTimeout (408)
|
|
68
|
-
|
|
69
|
-
**Causa:** Docker daemon tardó demasiado en responder.
|
|
70
|
-
**Reproducción:** Operación en un cluster sobrecargado.
|
|
71
|
-
**Resolución:** Incrementar `read_timeout` en configuración. Verificar estado del cluster.
|
|
72
|
-
|
|
73
|
-
### Conflict (409)
|
|
74
|
-
|
|
75
|
-
**Causa:** Nombre duplicado, recurso en uso, o versión desactualizada.
|
|
76
|
-
**Reproducción:** `Service.create(Name: "nombre_existente")` o update con `Version.Index` stale.
|
|
77
|
-
**Resolución:** Para nombres: verificar existencia antes de crear. Para versiones: hacer `reload` y reintentar el update.
|
|
78
|
-
|
|
79
|
-
### UnprocessableEntity (422)
|
|
80
|
-
|
|
81
|
-
**Causa:** Payload semánticamente inválido.
|
|
82
|
-
**Reproducción:** Crear servicio con imagen inexistente y restricciones de scheduling imposibles.
|
|
83
|
-
**Resolución:** Verificar que la imagen existe y que las constraints del servicio son alcanzables.
|
|
84
|
-
|
|
85
|
-
### TooManyRequests (429)
|
|
86
|
-
|
|
87
|
-
**Causa:** Rate limiting del Docker daemon o registry.
|
|
88
|
-
**Reproducción:** Burst de requests al API.
|
|
89
|
-
**Resolución:** Implementar backoff. Los retries de Excon cubren errores de socket/timeout pero no 429.
|
|
90
|
-
|
|
91
|
-
### InternalServerError (500)
|
|
92
|
-
|
|
93
|
-
**Causa:** Error interno del Docker daemon.
|
|
94
|
-
**Reproducción:** Bug en Docker, operación sobre estado inconsistente, o update sin `version` query param.
|
|
95
|
-
**Resolución:** Verificar logs del Docker daemon (`journalctl -u docker`). Si es por version faltante, usar el modelo (Updatable lo maneja).
|
|
96
|
-
|
|
97
|
-
### BadGateway (502)
|
|
98
|
-
|
|
99
|
-
**Causa:** Proxy o load balancer entre cliente y daemon devuelve error.
|
|
100
|
-
**Reproducción:** Docker daemon detrás de reverse proxy caído.
|
|
101
|
-
**Resolución:** Verificar infraestructura de red y proxy.
|
|
102
|
-
|
|
103
|
-
### ServiceUnavailable (503)
|
|
104
|
-
|
|
105
|
-
**Causa:** Docker daemon reiniciando o en mantenimiento.
|
|
106
|
-
**Reproducción:** Request durante restart del servicio Docker.
|
|
107
|
-
**Resolución:** Reintentar después de esperar. `max_retries` cubre errores de socket pero no 503.
|
|
108
|
-
|
|
109
|
-
### GatewayTimeout (504)
|
|
110
|
-
|
|
111
|
-
**Causa:** Proxy entre cliente y daemon timeout.
|
|
112
|
-
**Reproducción:** Operación larga detrás de proxy con timeout corto.
|
|
113
|
-
**Resolución:** Incrementar timeout del proxy. Verificar que `read_timeout` de la gema es menor que el del proxy.
|
|
114
|
-
|
|
115
|
-
### Communication
|
|
116
|
-
|
|
117
|
-
**Causa:** Error de socket o red — daemon caído, socket inexistente, permisos insuficientes.
|
|
118
|
-
**Reproducción:** `DockerSwarm::System.up` con daemon apagado.
|
|
119
|
-
**Resolución:** Verificar que Docker está corriendo (`systemctl status docker`), que el socket existe y que el usuario tiene permisos de lectura.
|
|
120
|
-
|
|
121
|
-
## Manejo recomendado
|
|
122
|
-
|
|
123
|
-
```ruby
|
|
124
|
-
begin
|
|
125
|
-
DockerSwarm::Service.create(Name: "web", TaskTemplate: { ... })
|
|
126
|
-
rescue DockerSwarm::Conflict => e
|
|
127
|
-
# Nombre duplicado — buscar existente
|
|
128
|
-
existing = DockerSwarm::Service.all(name: ["web"]).first
|
|
129
|
-
rescue DockerSwarm::Communication => e
|
|
130
|
-
# Docker caído
|
|
131
|
-
logger.error("Docker unreachable: #{e.message}")
|
|
132
|
-
rescue DockerSwarm::Error => e
|
|
133
|
-
# Cualquier otro error de Docker
|
|
134
|
-
logger.error("Docker error: #{e.class} #{e.message}")
|
|
135
|
-
end
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
## Logging automático
|
|
139
|
-
|
|
140
|
-
El middleware ErrorHandler loguea automáticamente antes de raise:
|
|
141
|
-
|
|
142
|
-
```
|
|
143
|
-
component=docker_swarm.middleware.error_handler event=business_error source=http status=409 message="name conflicts" method=post path=/services/create
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
Formato KV con masking de datos sensibles via LogHelper.
|
|
147
|
-
|
|
148
|
-
## Causa original (Excon wrapping)
|
|
149
|
-
|
|
150
|
-
Excon puede envolver excepciones del middleware en `Excon::Error::Socket`. Connection detecta esto y re-raise la excepción original:
|
|
151
|
-
|
|
152
|
-
```ruby
|
|
153
|
-
# Connection#request internamente:
|
|
154
|
-
actual_error = e.cause&.class&.name&.include?("DockerSwarm::Error") ? e.cause : e
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
La excepción original mantiene la causa via `Exception#cause` de Ruby para trazabilidad completa.
|