paramsx 2.5.0__tar.gz → 2.5.1__tar.gz
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.
- {paramsx-2.5.0 → paramsx-2.5.1}/CHANGELOG.md +6 -0
- {paramsx-2.5.0/paramsx.egg-info → paramsx-2.5.1}/PKG-INFO +1 -1
- paramsx-2.5.1/paramsx/__init__.py +1 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/paramsx/web/ssm.py +24 -0
- {paramsx-2.5.0 → paramsx-2.5.1/paramsx.egg-info}/PKG-INFO +1 -1
- {paramsx-2.5.0 → paramsx-2.5.1}/tests/test_web.py +65 -0
- paramsx-2.5.0/paramsx/__init__.py +0 -1
- {paramsx-2.5.0 → paramsx-2.5.1}/LICENSE +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/MANIFEST.in +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/README.md +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/paramsx/core/__init__.py +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/paramsx/core/config.py +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/paramsx/core/rutas.py +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/paramsx/funcions.py +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/paramsx/main.py +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/paramsx/paramsx_config.py +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/paramsx/text.py +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/paramsx/web/__init__.py +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/paramsx/web/app.py +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/paramsx/web/static/ajustes.js +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/paramsx/web/static/app.css +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/paramsx/web/static/comun.js +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/paramsx/web/static/paramsx.js +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/paramsx/web/templates/index.html +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/paramsx.egg-info/SOURCES.txt +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/paramsx.egg-info/dependency_links.txt +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/paramsx.egg-info/entry_points.txt +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/paramsx.egg-info/requires.txt +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/paramsx.egg-info/top_level.txt +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/setup.cfg +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/setup.py +0 -0
- {paramsx-2.5.0 → paramsx-2.5.1}/tests/test_core.py +0 -0
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.5.1
|
|
4
|
+
|
|
5
|
+
### Corregido
|
|
6
|
+
|
|
7
|
+
- **Un borrado ya no pisa el cambio de otro**: justo antes de borrar se vuelve a leer la versión de cada parámetro (sin valores). Si alguien lo ha cambiado desde la revisión (también mientras se creaba la copia de un renombrado), no se borra y se avisa; en un renombrado, se dice que la copia se creó con el valor de antes. Si el rol no puede leer la versión, se borra como antes; si la lectura falla por otro motivo, no se borra.
|
|
8
|
+
|
|
3
9
|
## 2.5.0
|
|
4
10
|
|
|
5
11
|
### Añadido
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.5.1"
|
|
@@ -440,6 +440,30 @@ def aplicar(ssm, items, cfg):
|
|
|
440
440
|
borrar.remove(b)
|
|
441
441
|
resultados.append(b)
|
|
442
442
|
|
|
443
|
+
# Justo antes de borrar, otra vez la versión de cada uno (sin valores ni descifrar): si alguien lo ha cambiado desde
|
|
444
|
+
# la revisión (también mientras se creaban los renombrados), no se borra. SSM no tiene «borrar solo si sigue en la
|
|
445
|
+
# versión N»: entre esta lectura y el borrado queda una ventana de milisegundos que no se puede cerrar desde aquí.
|
|
446
|
+
esperada = {it.get("name"): it.get("version") for it in items if it.get("accion") == "borrar" and it.get("version")}
|
|
447
|
+
copia_de = {it.get("de"): it.get("name") for it in items if it.get("accion") == "nuevo" and it.get("de")}
|
|
448
|
+
try:
|
|
449
|
+
ahora = describir(ssm, "", [b["name"] for b in borrar]) if borrar else {}
|
|
450
|
+
except (ClientError, BotoCoreError) as exc:
|
|
451
|
+
if not denegado(exc):
|
|
452
|
+
# Otro fallo (red, límite de llamadas...): sin comprobar no se borra, pero lo ya aplicado se devuelve
|
|
453
|
+
for b in borrar:
|
|
454
|
+
b["error"] = f"No se pudo comprobar la versión antes de borrar ({motivo(exc)}): no se borra."
|
|
455
|
+
resultados += borrar
|
|
456
|
+
return resultados
|
|
457
|
+
ahora = None # sin permiso para describir: se borra como antes (ya se comprobó al revisar)
|
|
458
|
+
for b in [b for b in borrar if ahora is not None and b["name"] in ahora and b["name"] in esperada
|
|
459
|
+
and ahora[b["name"]].get("version") != esperada[b["name"]]]:
|
|
460
|
+
b["error"] = (f"Ha cambiado en AWS mientras se aplicaba (versión {esperada[b['name']]} → "
|
|
461
|
+
f"{ahora[b['name']].get('version')}): no se borra. "
|
|
462
|
+
+ (f"Su copia «{copia_de[b['name']]}» se creó con el valor de antes: revisa cuál dejar."
|
|
463
|
+
if b["name"] in copia_de else "Recarga el grupo."))
|
|
464
|
+
borrar.remove(b)
|
|
465
|
+
resultados.append(b)
|
|
466
|
+
|
|
443
467
|
# Borrados de 10 en 10 (el máximo de DeleteParameters)
|
|
444
468
|
for i in range(0, len(borrar), 10):
|
|
445
469
|
lote = borrar[i:i + 10]
|
|
@@ -333,6 +333,71 @@ def test_renombrar_conserva_la_clave_kms_y_nunca_pierde_el_viejo(cliente, ssm, m
|
|
|
333
333
|
assert "/dev/app/url" in ssm.params and not [o for o in ssm.ops("DeleteParameters") if "/dev/app/url" in o["Names"]]
|
|
334
334
|
|
|
335
335
|
|
|
336
|
+
def test_si_el_original_cambia_mientras_se_aplica_no_se_borra(cliente, ssm, monkeypatch):
|
|
337
|
+
ssm.poner("/dev/app/url", "https://x", tipo="String", tags=TAGS)
|
|
338
|
+
ssm.poner("/dev/app/b", "b", tipo="String", tags=TAGS)
|
|
339
|
+
ps = cargar(cliente)
|
|
340
|
+
aplicar = lambda items: {x["name"]: x for x in cliente.post("/api/aplicar", json={ # noqa: E731
|
|
341
|
+
"items": items, "confirmacion": CONFIRMA, "borrados": "1"}).get_json()["resultados"]}
|
|
342
|
+
|
|
343
|
+
# Mientras se crea la copia renombrada, otro cambia el original
|
|
344
|
+
real = ssm.put_parameter
|
|
345
|
+
|
|
346
|
+
def y_otro_cambia_el_original(**kw):
|
|
347
|
+
r = real(**kw)
|
|
348
|
+
if kw["Name"] == "/dev/app/url2":
|
|
349
|
+
real(Name="/dev/app/url", Value="https://nuevo", Overwrite=True)
|
|
350
|
+
return r
|
|
351
|
+
monkeypatch.setattr(ssm, "put_parameter", y_otro_cambia_el_original)
|
|
352
|
+
r = aplicar(renombrar(ps["/dev/app/url"], "/dev/app/url2"))
|
|
353
|
+
assert r["/dev/app/url2"]["ok"] and not r["/dev/app/url"]["ok"]
|
|
354
|
+
assert "Ha cambiado en AWS mientras se aplicaba (versión 1 → 2)" in r["/dev/app/url"]["error"]
|
|
355
|
+
assert "«/dev/app/url2»" in r["/dev/app/url"]["error"] # avisa de la copia con el valor de antes
|
|
356
|
+
assert ssm.params["/dev/app/url"]["value"] == "https://nuevo" # el cambio del otro no se pierde
|
|
357
|
+
assert ssm.ops("DeleteParameters") == []
|
|
358
|
+
monkeypatch.setattr(ssm, "put_parameter", real)
|
|
359
|
+
|
|
360
|
+
# Un borrado normal: lo cambian entre la revisión y el borrado
|
|
361
|
+
revisar_real = ssm_web._revisar
|
|
362
|
+
|
|
363
|
+
def revisa_y_cambia(*a, **k):
|
|
364
|
+
out = revisar_real(*a, **k)
|
|
365
|
+
ssm.poner("/dev/app/b", "b-de-otro", tipo="String")
|
|
366
|
+
return out
|
|
367
|
+
monkeypatch.setattr(ssm_web, "_revisar", revisa_y_cambia)
|
|
368
|
+
r = aplicar([item(ps["/dev/app/b"], accion="borrar")])
|
|
369
|
+
assert not r["/dev/app/b"]["ok"] and "Recarga el grupo" in r["/dev/app/b"]["error"]
|
|
370
|
+
assert "/dev/app/b" in ssm.params and ssm.ops("DeleteParameters") == []
|
|
371
|
+
|
|
372
|
+
# Sin permiso para volver a leerla: se borra como antes (ya se comprobó al revisar)
|
|
373
|
+
def revisa_y_quita_describe(*a, **k):
|
|
374
|
+
out = revisar_real(*a, **k)
|
|
375
|
+
ssm.sin_describe = True
|
|
376
|
+
return out
|
|
377
|
+
monkeypatch.setattr(ssm_web, "_revisar", revisa_y_quita_describe)
|
|
378
|
+
ssm.poner("/dev/app/c", "c", tipo="String")
|
|
379
|
+
r = aplicar([{"name": "/dev/app/c", "accion": "borrar", "version": 1}])
|
|
380
|
+
assert r["/dev/app/c"]["ok"] and "/dev/app/c" not in ssm.params
|
|
381
|
+
ssm.sin_describe = False
|
|
382
|
+
|
|
383
|
+
# Si falla de otra forma al leerla, no se borra (sin comprobar no se toca)
|
|
384
|
+
def revisa_y_rompe(*a, **k):
|
|
385
|
+
out = revisar_real(*a, **k)
|
|
386
|
+
monkeypatch.setattr(ssm, "describe_parameters", lambda **kw: (_ for _ in ()).throw(
|
|
387
|
+
ssm_web.ClientError({"Error": {"Code": "ThrottlingException", "Message": "Rate exceeded"}}, "Op")))
|
|
388
|
+
return out
|
|
389
|
+
monkeypatch.setattr(ssm_web, "_revisar", revisa_y_rompe)
|
|
390
|
+
ssm.poner("/dev/app/d", "d", tipo="String")
|
|
391
|
+
r = aplicar([{"name": "/dev/app/d", "accion": "borrar", "version": 1}])
|
|
392
|
+
assert not r["/dev/app/d"]["ok"] and "No se pudo comprobar" in r["/dev/app/d"]["error"]
|
|
393
|
+
assert "/dev/app/d" in ssm.params
|
|
394
|
+
monkeypatch.undo()
|
|
395
|
+
|
|
396
|
+
# Sin cambios, se borra como siempre (b va ya por la versión 2)
|
|
397
|
+
r = aplicar([{"name": "/dev/app/b", "accion": "borrar", "version": 2}])
|
|
398
|
+
assert r["/dev/app/b"]["ok"] and "/dev/app/b" not in ssm.params
|
|
399
|
+
|
|
400
|
+
|
|
336
401
|
# ---------------------------------------------------------------- nombre sin barra final
|
|
337
402
|
|
|
338
403
|
def test_nuevo_con_barra_final_se_quita(cliente, ssm):
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.5.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|