Class: DockerSwarm::Container
- Includes:
- DockerSwarm::Concerns::Creatable, DockerSwarm::Concerns::Deletable, DockerSwarm::Concerns::Loggable
- Defined in:
- lib/docker_swarm/models/container.rb
Overview
Represents a Docker Container
Class Method Summary collapse
-
.create_query_params ⇒ Array<String>
POST /containers/createtoma el nombre por query string. -
.index_query_params ⇒ Array<Symbol>
GET /containers/jsondeclara exactamente tres query params propios además defilters:all,limitysize(spec v1.41,ContainerList).
Instance Method Summary collapse
-
#restart(timeout: nil) ⇒ Boolean
Reinicia el container (+POST /containers/Base#id/restart+).
-
#start ⇒ Boolean
Starts the container.
-
#stats(query_params = {}) ⇒ Hash
Métricas de uso del container (+GET /containers/Base#id/stats+).
-
#stop ⇒ Boolean
Stops the container.
-
#update(new_attributes = {}, **opts) ⇒ Hash
Actualiza los límites de recursos del container (+POST /containers/Base#id/update+).
Methods included from DockerSwarm::Concerns::Loggable
Methods included from DockerSwarm::Concerns::Deletable
Methods included from DockerSwarm::Concerns::Creatable
#query_params_for_docker, #save
Methods inherited from Base
all, #as_json, #assign_attributes, #attributes, defined_attributes, find, #id, #initialize, #method_missing, #payload_for_docker, #persisted?, #reload, resource_name, #respond_to_missing?, root_key, routes, #serializable_hash, where
Methods included from DockerSwarm::Concerns::Inspectable
Constructor Details
This class inherits a constructor from DockerSwarm::Base
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class DockerSwarm::Base
Class Method Details
.create_query_params ⇒ Array<String>
POST /containers/create toma el nombre por query string. En el body Docker lo
descarta en silencio y responde 201: el container nace con nombre aleatorio
y la adopción por nombre determinista en un reintento no encuentra nada, así que
el reintento duplica. Ver ADR-025 cláusula 1.
16 17 18 |
# File 'lib/docker_swarm/models/container.rb', line 16 def self.create_query_params %w[name].freeze end |
.index_query_params ⇒ Array<Symbol>
GET /containers/json declara exactamente tres query params propios además de
filters: all, limit y size (spec v1.41, ContainerList).
No hereda el default de Base porque since y before son
filtros de este recurso, no query params: ruteados a la URL el Engine los ignora
y devuelve la lista sin filtrar, sin error — resultado incorrecto silencioso,
peor que el rechazo ruidoso de #22. Y size faltaba: es query param propio (pide
el tamaño de los archivos del container), así que viajaba dentro de filters como
filtro inválido. Ver #35.
31 32 33 |
# File 'lib/docker_swarm/models/container.rb', line 31 def self.index_query_params %i[all limit size].freeze end |
Instance Method Details
#restart(timeout: nil) ⇒ Boolean
Reinicia el container (+POST /containers/Base#id/restart+).
⚠️ No se parece a Service#restart, y está bien. El hermano simula el restart
incrementando ForceUpdate porque los services de Swarm no tienen endpoint de
restart. Los containers sí lo tienen, así que copiar ese workaround sería arrastrar
una vuelta que acá no hace falta.
124 125 126 127 128 129 130 131 |
# File 'lib/docker_swarm/models/container.rb', line 124 def restart(timeout: nil) Api.request( action: self.class.routes[:restart], arguments: { id: self.ID }, query_params: timeout.nil? ? {} : { t: timeout } ) true end |
#start ⇒ Boolean
Starts the container
37 38 39 40 |
# File 'lib/docker_swarm/models/container.rb', line 37 def start Api.request(action: self.class.routes[:start], arguments: { id: self.ID }) true end |
#stats(query_params = {}) ⇒ Hash
Métricas de uso del container (+GET /containers/Base#id/stats+).
🚦 stream: false NO es un default cómodo: es lo que hace que el método vuelva.
El endpoint streamea por default —+stream=true+— y la conexión queda abierta emitiendo
un objeto por segundo. Medido contra un Engine 29.7.2: sin el parámetro, 6 objetos
en 6 s y la conexión no cierra (+exit 28+ de curl); con stream=false, un objeto y
cierra en 1 s. En una llamada RPC el default cuelga — y el modo de falla no es un
error, es una espera. Mismo patrón que ADR-027: el default de Docker no es el que sirve.
Por eso el parámetro se mergea en vez de reemplazarse, que es como lo hace DockerSwarm::Concerns::Loggable#logs: ahí un caller que pasa su propio hash sólo cambia qué streams lee; acá lo dejaría colgado. Se puede pisar a propósito (+stats(stream: true)+), pero no por accidente.
150 151 152 153 154 155 156 |
# File 'lib/docker_swarm/models/container.rb', line 150 def stats(query_params = {}) Api.request( action: self.class.routes[:stats], arguments: { id: self.ID }, query_params: { stream: false }.merge(query_params) ) end |
#stop ⇒ Boolean
Stops the container
44 45 46 47 |
# File 'lib/docker_swarm/models/container.rb', line 44 def stop Api.request(action: self.class.routes[:stop], arguments: { id: self.ID }) true end |
#update(new_attributes = {}, **opts) ⇒ Hash
Actualiza los límites de recursos del container (+POST /containers/Base#id/update+).
⚠️ NO usa DockerSwarm::Concerns::Updatable, y no es un olvido. Ese concern está escrito para
services de Swarm: manda ?version=<Version.Index> para el control de concurrencia
optimista y serializa con payload_for_docker. El update de un container no tiene
version — es otro endpoint con otra semántica (cpu, memoria, reinicio) — así que
incluirlo mandaría un query param que el Engine ignora en silencio.
🚦 La firma absorbe kwargs a propósito. DockerSwarm::Concerns::Creatable#save llama
update(registry_auth:) cuando el objeto ya está persistido; con una firma
update(new_attributes = {}) ese kwarg se convierte en Hash posicional (Ruby 3) y
terminaría posteado como atributo: {"registry_auth": null} hacia el Engine, sin
error. Los dos de registry se descartan acá porque son cosa de Service (header
X-Registry-Auth / query registryAuthFrom); un container no autentica en su update.
Devuelve el cuerpo de la respuesta —Docker responde +[...]+— y no un
booleano: el Engine avisa por ahí cuando un límite no se pudo aplicar. Colapsarlo a
true se comería justamente la señal.
🚦 Un payload vacío levanta, y por eso save sobre un container persistido NO funciona
— falla fuerte. DockerSwarm::Concerns::Creatable#save llama update(registry_auth:) sin
atributos, así que el payload queda en {} y el Engine responde +200 OK+ sin aplicar
nada (medido: body {} → {"Warnings":null}, Memory sin cambiar). Dejarlo pasar
convertiría a save en una promesa vacía: el caller asigna atributos, llama save, y
los pierde sin un solo error.
No se soporta el save genérico a propósito: POST /containers/{id}/update no es
"guardar el objeto", es un endpoint angosto de límites de recursos. Derivar el payload
de los atributos locales exigiría una whitelist de los campos que Docker acepta, que
driftea contra la API. Mejor decirlo que fingirlo.
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/docker_swarm/models/container.rb', line 85 def update(new_attributes = {}, **opts) # El `except` va sobre el MERGE, no sólo sobre `opts`: un caller que pase # `{registry_auth: "…", Memory: …}` como Hash **posicional** metería la credencial en el # payload, y de ahí al log (`body=…`) — la misma fuga que arregló #24 por el otro lado. payload = new_attributes.merge(opts).except(:registry_auth, :registry_auth_from, "registry_auth", "registry_auth_from") if payload.empty? raise ArgumentError, "Container#update requires at least one attribute. An empty payload gets a 200 OK " \ "from the Engine and applies nothing. Coming from `save`? Containers do not support " \ "the generic save: use `update(\"Memory\" => ...)` with explicit resource limits." end response = Api.request( action: self.class.routes[:update], arguments: { id: self.ID }, payload: payload ) # El estado local queda stale si no se recarga: el payload es **plano** (`Memory`) pero el # objeto lo tiene anidado (`HostConfig.Memory`), así que un `assign_attributes` —lo que # hace {Concerns::Updatable}— crearía un atributo fantasma en vez de actualizar el real. # `reload` trae la forma correcta del Engine; es el mismo cierre que usa `save` al crear. reload response end |