paramsx 2.2.0__tar.gz → 2.2.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.
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.2.1
4
+
5
+ Solo comandos de terminal y documentación: no cambia nada de la lectura, la carga ni la
6
+ construcción de rutas. Si ya tienes la 2.2.0 funcionando, actualizar no te obliga a tocar
7
+ tu configuración.
8
+
9
+ ### Añadido
10
+
11
+ - **`paramsx --version`** (y `-v`), y la versión también en la cabecera de `paramsx --help`. La versión pasa a vivir en `paramsx/__init__.py` y `setup.py` la lee de ahí, para que el paquete y el comando no puedan decir cosas distintas.
12
+ - **`paramsx configure` sobre una configuración que ya existe ya no se queda en "no se sobrescribirá".** Sigue sin tocar el fichero, pero ahora te dice qué opciones nuevas no tienes y con qué valor por defecto se rellenan, si usas el nombre antiguo `abac`, y si la configuración es válida.
13
+ - **`paramsx configure --ejemplo`**: además de lo anterior, deja la plantilla de esta versión en `~/.xsoft/paramsx_config.ejemplo.py`, al lado de la tuya, para comparar. ParamsX no la lee: es solo referencia. Escribir en tu configuración es lo único que no se puede deshacer, así que va en un comando aparte y en otro fichero.
14
+ - Mensaje de primer arranque más claro cuando todavía no hay configuración, explicando qué hace `paramsx configure` y dónde va el fichero.
15
+
16
+ ### Cambiado
17
+
18
+ - **`paramsx --help` al día.** La opción 2 ya explica que eliges entre los ficheros que tengas en el directorio; el ejemplo de `mixto` usa el entorno en mayúscula como el resto de la documentación; `fichero_por_ruta` enseña el nombre real (`parameters_dev__API_STA__max.py`); y se documentan `profile_name`, `region_name` y `entornos`, que no aparecían aunque son obligatorios.
19
+ - **El README muestra el contenido literal de `paramsx_config.py`**, con sus comentarios y tablas, en vez de una versión resumida: es exactamente lo que te crea `paramsx configure`, así que no pueden desincronizarse. Y una tabla con todos los comandos disponibles.
20
+
3
21
  ## 2.2.0
4
22
 
5
23
  ### Añadido
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: paramsx
3
- Version: 2.2.0
3
+ Version: 2.2.1
4
4
  Summary: Librería para gestionar y respaldar parámetros de AWS SSM de manera sencilla y eficiente.
5
5
  Home-page: https://github.com/pistatxos/paramsx
6
6
  Author: Mariox
@@ -128,11 +128,55 @@ Este comando creará automáticamente una carpeta de configuración en tu direct
128
128
 
129
129
  Dentro de esta carpeta, encontrarás el archivo paramsx_config.py. Este archivo contiene la configuración inicial que debes ajustar según tu entorno.
130
130
 
131
+ Si ya tenías configuración de una versión anterior, `paramsx configure` **no la sobrescribe**: te dice qué opciones nuevas no tienes y con qué valor por defecto se están rellenando, y si la configuración es válida. Con `paramsx configure --ejemplo` además deja la plantilla de esta versión en `paramsx_config.ejemplo.py`, al lado de la tuya, para que compares sin tocar nada.
132
+
131
133
  Ejemplo del contenido de paramsx_config.py:
132
134
 
133
135
  ```python
134
136
  ## Configuraciones ParamsX
135
137
 
138
+ # --- Perfiles de naming -------------------------------------------------------------
139
+ # Un perfil dice CÓMO se construye la ruta real en AWS a partir de la ruta que declaras
140
+ # en 'parameter_list' y del entorno que eliges en el menú. Los nombres son tuyos: define
141
+ # solo los que uses y llámalos como quieras. Un perfil tiene tres campos:
142
+ #
143
+ # campo | valores | qué decide
144
+ # ------------------+------------------------------------------+---------------------------
145
+ # posicion_entorno | inicio | final | mixto | ninguno | dónde va el entorno
146
+ # case_entorno | lower | upper | capitalize | cómo se escribe el entorno
147
+ # case_ruta | lower | upper | capitalize | ninguno | case de la ruta AL CREAR
148
+ #
149
+ # posicion_entorno -> dónde se coloca el entorno (ejemplos con el entorno 'dev'):
150
+ #
151
+ # valor | ruta declarada | ruta real en AWS
152
+ # ---------+-----------------+--------------------------------------------------------
153
+ # inicio | /rds | /dev/rds
154
+ # final | /API/STA | /API/STA/DEV
155
+ # mixto | /API/*/STA | /API/DEV/STA el '*' marca el sitio; uno y como segmento
156
+ # ninguno | /api/sta/auth | /api/sta/auth una cuenta AWS por entorno; case_entorno da igual
157
+ #
158
+ # case_entorno -> cómo se escribe ese entorno en la ruta:
159
+ #
160
+ # valor | 'dev' se escribe | ruta real de /API/STA con posicion_entorno=final
161
+ # ------------+------------------+------------------------------------------------
162
+ # lower | dev | /API/STA/dev
163
+ # upper | DEV | /API/STA/DEV
164
+ # capitalize | Dev | /API/STA/Dev
165
+ #
166
+ # case_ruta -> a qué case se fuerza la ruta que TÚ escribes al CREAR un parámetro
167
+ # (opción 4 del menú). No afecta a leer ni a editar: lo que ya existe en AWS se
168
+ # respeta siempre tal cual esté.
169
+ #
170
+ # valor | si escribes /API/MULTIAPI/Token, se crea
171
+ # ------------+-----------------------------------------
172
+ # lower | /api/multiapi/token
173
+ # upper | /API/MULTIAPI/TOKEN
174
+ # capitalize | /Api/Multiapi/Token
175
+ # ninguno | /API/MULTIAPI/Token
176
+ #
177
+ # Combina los tres campos como necesites: no hay una lista cerrada de perfiles. En el
178
+ # README tienes más ejemplos.
179
+
136
180
  naming = {
137
181
  "min": {"posicion_entorno": "inicio", "case_entorno": "lower", "case_ruta": "lower"},
138
182
  "max": {"posicion_entorno": "final", "case_entorno": "upper", "case_ruta": "ninguno"},
@@ -150,97 +194,67 @@ configuraciones = {
150
194
  {"path": "/rds", "convencion": "min"}, # -> /dev/rds
151
195
  {"path": "/EMAIL", "convencion": "max"}, # -> /EMAIL/DEV
152
196
  {"path": "/API/STA", "convencion": "max"}, # -> /API/STA/DEV
197
+ # Con 'mixto' acotas por debajo del entorno: esto lee solo stan_ai, en vez de
198
+ # todo lo que cuelga de /API/MULTIAPI/DEV
153
199
  {"path": "/API/MULTIAPI/*/stan_ai", "convencion": "mixto_max"}, # -> /API/MULTIAPI/DEV/stan_ai
154
200
  ]
155
201
  }
156
202
 
203
+ # Perfil de naming que se usa al crear un parámetro nuevo (opción 4 del menú).
204
+ # Si no lo defines, se usa el primer perfil de 'naming'.
157
205
  convencion_nuevos = "min"
158
206
 
207
+ # ¿El nombre del fichero exportado incluye la ruta leída?
208
+ # False -> parameters_dev.py (comportamiento de siempre)
209
+ # True -> parameters_dev__API_STA__max.py (uno por entrada y entorno: lleva el
210
+ # entorno, la ruta y el perfil, porque dos entradas pueden compartir ruta)
211
+ # Ponlo en True si sueles leer varias rutas del mismo entorno y no quieres que la
212
+ # segunda lectura te machaque el fichero de la primera.
159
213
  fichero_por_ruta = False
160
214
 
161
215
 
162
216
  ## Configuraciones Tags
163
217
 
218
+ # Gestionar las tags de los parámetros: leerlas de AWS, exponerlas en el fichero
219
+ # exportado para editarlas y validar las obligatorias al cargar.
220
+ # True -> las tags viajan en el fichero y se validan.
221
+ # False -> no aparecen tags en el fichero y no se valida nada.
222
+ # En cuentas cuyo control de acceso va por tags (ABAC vía IAM) esto debe estar en True.
164
223
  tags_activas = True
165
224
 
225
+ # Solo aplica si tags_activas = True.
226
+ # False -> validación bloqueante: si a un parámetro le falta alguna tag obligatoria
227
+ # no se sube (ni su valor ni sus tags).
228
+ # True -> se permiten vacías: el parámetro se sube igualmente y las tags sin valor
229
+ # simplemente NO se crean en AWS (no se suben como etiquetas vacías).
166
230
  obligatorias_vacias = False
167
231
 
232
+ # Tags que se exigen en cada parámetro cuando tags_activas = True. La lista es libre:
233
+ # estas 8 son las que sostienen el control de acceso ABAC vía IAM de nuestra cuenta.
168
234
  tags_obligatorias = [
169
- "Application", "Environment", "Owner", "Project",
170
- "Product", "Service", "Component", "ManagedBy",
235
+ "Application",
236
+ "Environment",
237
+ "Owner",
238
+ "Project",
239
+ "Product",
240
+ "Service",
241
+ "Component",
242
+ "ManagedBy",
171
243
  ]
172
244
  ```
173
245
  Nota: Si el archivo paramsx_config.py ya existe, no será sobrescrito durante la instalación para proteger las configuraciones personalizadas.
174
246
 
175
247
  ### Los perfiles de naming
176
248
 
177
- Cada organización nombra sus parámetros a su manera, así que ParamsX no impone ninguna convención: **tú defines los perfiles que uses en el diccionario `naming` y les pones el nombre que quieras**. Cada entrada de `parameter_list` declara con qué perfil se construye su ruta completa.
178
-
179
- Un perfil tiene tres campos:
180
-
181
- | Campo | Valores | Qué decide |
182
- |---|---|---|
183
- | `posicion_entorno` | `inicio` \| `final` \| `mixto` \| `ninguno` | Dónde va el entorno dentro de la ruta. |
184
- | `case_entorno` | `lower` \| `upper` \| `capitalize` | Cómo se escribe el entorno. |
185
- | `case_ruta` | `lower` \| `upper` \| `capitalize` \| `ninguno` | Case de la ruta al crear parámetros. |
186
-
187
- Y en detalle:
188
-
189
- **`posicion_entorno`** — dónde se coloca el entorno, con el entorno `dev`:
190
-
191
- | Valor | Ruta declarada | Ruta real en AWS | |
192
- |---|---|---|---|
193
- | `inicio` | `/rds` | `/dev/rds` | |
194
- | `final` | `/API/STA` | `/API/STA/DEV` | |
195
- | `mixto` | `/API/*/STA` | `/API/DEV/STA` | el `*` marca el sitio |
196
- | `ninguno` | `/api/sta/auth` | `/api/sta/auth` | una cuenta AWS por entorno |
197
-
198
- **`case_entorno`** — cómo se escribe ese entorno en la ruta:
199
-
200
- | Valor | `dev` se escribe | `/API/STA` con `posicion_entorno: final` |
201
- |---|---|---|
202
- | `lower` | `dev` | `/API/STA/dev` |
203
- | `upper` | `DEV` | `/API/STA/DEV` |
204
- | `capitalize` | `Dev` | `/API/STA/Dev` |
205
-
206
- **`case_ruta`** — a qué case se fuerza la ruta que escribes al **crear** un parámetro (opción 4). No afecta a leer ni a editar: lo que ya existe en AWS se respeta siempre tal cual esté.
207
-
208
- | Valor | Si escribes `/API/MULTIAPI/Token`, se crea |
209
- |---|---|
210
- | `lower` | `/api/multiapi/token` |
211
- | `upper` | `/API/MULTIAPI/TOKEN` |
212
- | `capitalize` | `/Api/Multiapi/Token` |
213
- | `ninguno` | `/API/MULTIAPI/Token` |
249
+ Cada organización nombra sus parámetros a su manera, así que ParamsX no impone ninguna convención: **tú defines los perfiles que uses en el diccionario `naming` y les pones el nombre que quieras**. Cada entrada de `parameter_list` declara con qué perfil se construye su ruta completa. Los tres campos de un perfil y sus valores están explicados en el propio fichero de configuración, ahí arriba.
214
250
 
215
251
  **No hay una lista cerrada de perfiles.** Los tres campos se combinan libremente, así que la plantilla no intenta traértelos todos: define los dos o tres que use tu organización y olvídate del resto. `min` y `max` vienen predefinidos porque son los que ParamsX traía antes de que los perfiles fueran configurables.
216
252
 
217
- **`mixto` y el marcador `*`.** Cuando el entorno no va ni al principio ni al final, se marca su sitio con un `*` en la propia ruta. Es útil para acotar la lectura a un solo subárbol: con `/API/MULTIAPI/*/stan_ai` lees únicamente `/API/MULTIAPI/DEV/stan_ai`, en vez de todo lo que cuelga de `/API/MULTIAPI/DEV`. El `*` debe ser un segmento entero y aparecer **exactamente una vez**, y solo se admite en perfiles `mixto`: si el perfil y la ruta no cuentan la misma historia, ParamsX te lo dice al arrancar en vez de leer una ruta inexistente y devolverte una lista vacía.
218
-
219
- **`ninguno` y las cuentas sin entorno en la ruta.** Hay organizaciones que separan los entornos por cuenta de AWS y no meten `dev`/`prod` en el path. Con `posicion_entorno: "ninguno"` la ruta se usa tal cual; el selector de entorno del menú sigue existiendo, pero no toca la ruta. En este perfil el `case_entorno` es irrelevante, porque no se escribe ningún entorno.
253
+ **Para qué sirve el `*`.** Además de colocar el entorno donde quieras, acota la lectura a un solo subárbol: con `/API/MULTIAPI/*/stan_ai` lees únicamente `/API/MULTIAPI/DEV/stan_ai`, en vez de todo lo que cuelga de `/API/MULTIAPI/DEV`. Debe ser un segmento entero, aparecer **exactamente una vez** y solo se admite en perfiles `mixto`: si el perfil y la ruta no cuentan la misma historia, ParamsX te lo dice al arrancar en vez de leer una ruta inexistente y devolverte una lista vacía.
220
254
 
221
- Ya **no existe** la lista `entornos_old`: el entorno se escribe siempre a partir de la lista canónica `entornos` (en minúscula), aplicándole el `case_entorno` del perfil. Si en tus rutas el entorno se llama `staging` en vez de `pre`, ponlo así en `entornos`.
255
+ **Los entornos.** Ya no existe la lista `entornos_old`: el entorno sale siempre de la lista canónica `entornos` (en minúscula), aplicándole el `case_entorno` del perfil. Si en tus rutas se llama `staging` en vez de `pre`, ponlo así en `entornos`.
222
256
 
223
- Ejemplo completo de una `parameter_list` real, mezclando perfiles:
224
-
225
- ```python
226
- "parameter_list": [
227
- {"path": "/common", "convencion": "min"},
228
- {"path": "/rds", "convencion": "min"},
229
- {"path": "/api", "convencion": "min"},
230
- {"path": "/INFRA", "convencion": "max"},
231
- {"path": "/API/STA", "convencion": "max"},
232
- {"path": "/API/p15", "convencion": "max"},
233
- {"path": "/API/MULTIAPI", "convencion": "max"},
234
- {"path": "/APP/Alertas", "convencion": "max"},
235
- {"path": "/BUCKETS", "convencion": "max"},
236
- {"path": "/EMAIL", "convencion": "max"},
237
- {"path": "/INFERENCIAS/TASA_DMI", "convencion": "max"},
238
- {"path": "/CEE/CEXGEN", "convencion": "max"},
239
- {"path": "/API/MULTIAPI/*/stan_ai", "convencion": "mixto_max"},
240
- ]
241
- ```
242
-
243
- Sobre mayúsculas y minúsculas: ParamsX **no renombra ni fuerza el case de los parámetros que ya existen**, los lee y edita tal cual estén. El `case_ruta` del perfil solo entra en juego al crear parámetros nuevos.
257
+ Y ParamsX **no renombra ni fuerza el case de los parámetros que ya existen**: los lee y edita tal cual estén. El `case_ruta` del perfil solo entra en juego al crear parámetros nuevos.
244
258
 
245
259
  ### Un fichero por ruta: `fichero_por_ruta`
246
260
 
@@ -342,7 +356,17 @@ En algunos sistemas (especialmente en entornos corporativos como Windows), el PA
342
356
  ```source ~/.zshrc # Para zsh```
343
357
 
344
358
  Una vez instalado, verifica que el comando paramsx esté disponible ejecutando:
345
- ```paramsx --help```
359
+ ```paramsx --version```
360
+
361
+ Comandos disponibles:
362
+
363
+ | Comando | Qué hace |
364
+ |---|---|
365
+ | `paramsx` | Abre el menú interactivo (necesita configuración). |
366
+ | `paramsx configure` | Crea la configuración la primera vez; si ya existe, la revisa sin tocarla. |
367
+ | `paramsx configure --ejemplo` | Además deja la plantilla de esta versión al lado, para comparar. |
368
+ | `paramsx --version` | Versión instalada. |
369
+ | `paramsx --help` | Ayuda, con el resumen de todas las opciones de configuración. |
346
370
 
347
371
 
348
372
  ## Modo de empleo
@@ -108,11 +108,55 @@ Este comando creará automáticamente una carpeta de configuración en tu direct
108
108
 
109
109
  Dentro de esta carpeta, encontrarás el archivo paramsx_config.py. Este archivo contiene la configuración inicial que debes ajustar según tu entorno.
110
110
 
111
+ Si ya tenías configuración de una versión anterior, `paramsx configure` **no la sobrescribe**: te dice qué opciones nuevas no tienes y con qué valor por defecto se están rellenando, y si la configuración es válida. Con `paramsx configure --ejemplo` además deja la plantilla de esta versión en `paramsx_config.ejemplo.py`, al lado de la tuya, para que compares sin tocar nada.
112
+
111
113
  Ejemplo del contenido de paramsx_config.py:
112
114
 
113
115
  ```python
114
116
  ## Configuraciones ParamsX
115
117
 
118
+ # --- Perfiles de naming -------------------------------------------------------------
119
+ # Un perfil dice CÓMO se construye la ruta real en AWS a partir de la ruta que declaras
120
+ # en 'parameter_list' y del entorno que eliges en el menú. Los nombres son tuyos: define
121
+ # solo los que uses y llámalos como quieras. Un perfil tiene tres campos:
122
+ #
123
+ # campo | valores | qué decide
124
+ # ------------------+------------------------------------------+---------------------------
125
+ # posicion_entorno | inicio | final | mixto | ninguno | dónde va el entorno
126
+ # case_entorno | lower | upper | capitalize | cómo se escribe el entorno
127
+ # case_ruta | lower | upper | capitalize | ninguno | case de la ruta AL CREAR
128
+ #
129
+ # posicion_entorno -> dónde se coloca el entorno (ejemplos con el entorno 'dev'):
130
+ #
131
+ # valor | ruta declarada | ruta real en AWS
132
+ # ---------+-----------------+--------------------------------------------------------
133
+ # inicio | /rds | /dev/rds
134
+ # final | /API/STA | /API/STA/DEV
135
+ # mixto | /API/*/STA | /API/DEV/STA el '*' marca el sitio; uno y como segmento
136
+ # ninguno | /api/sta/auth | /api/sta/auth una cuenta AWS por entorno; case_entorno da igual
137
+ #
138
+ # case_entorno -> cómo se escribe ese entorno en la ruta:
139
+ #
140
+ # valor | 'dev' se escribe | ruta real de /API/STA con posicion_entorno=final
141
+ # ------------+------------------+------------------------------------------------
142
+ # lower | dev | /API/STA/dev
143
+ # upper | DEV | /API/STA/DEV
144
+ # capitalize | Dev | /API/STA/Dev
145
+ #
146
+ # case_ruta -> a qué case se fuerza la ruta que TÚ escribes al CREAR un parámetro
147
+ # (opción 4 del menú). No afecta a leer ni a editar: lo que ya existe en AWS se
148
+ # respeta siempre tal cual esté.
149
+ #
150
+ # valor | si escribes /API/MULTIAPI/Token, se crea
151
+ # ------------+-----------------------------------------
152
+ # lower | /api/multiapi/token
153
+ # upper | /API/MULTIAPI/TOKEN
154
+ # capitalize | /Api/Multiapi/Token
155
+ # ninguno | /API/MULTIAPI/Token
156
+ #
157
+ # Combina los tres campos como necesites: no hay una lista cerrada de perfiles. En el
158
+ # README tienes más ejemplos.
159
+
116
160
  naming = {
117
161
  "min": {"posicion_entorno": "inicio", "case_entorno": "lower", "case_ruta": "lower"},
118
162
  "max": {"posicion_entorno": "final", "case_entorno": "upper", "case_ruta": "ninguno"},
@@ -130,97 +174,67 @@ configuraciones = {
130
174
  {"path": "/rds", "convencion": "min"}, # -> /dev/rds
131
175
  {"path": "/EMAIL", "convencion": "max"}, # -> /EMAIL/DEV
132
176
  {"path": "/API/STA", "convencion": "max"}, # -> /API/STA/DEV
177
+ # Con 'mixto' acotas por debajo del entorno: esto lee solo stan_ai, en vez de
178
+ # todo lo que cuelga de /API/MULTIAPI/DEV
133
179
  {"path": "/API/MULTIAPI/*/stan_ai", "convencion": "mixto_max"}, # -> /API/MULTIAPI/DEV/stan_ai
134
180
  ]
135
181
  }
136
182
 
183
+ # Perfil de naming que se usa al crear un parámetro nuevo (opción 4 del menú).
184
+ # Si no lo defines, se usa el primer perfil de 'naming'.
137
185
  convencion_nuevos = "min"
138
186
 
187
+ # ¿El nombre del fichero exportado incluye la ruta leída?
188
+ # False -> parameters_dev.py (comportamiento de siempre)
189
+ # True -> parameters_dev__API_STA__max.py (uno por entrada y entorno: lleva el
190
+ # entorno, la ruta y el perfil, porque dos entradas pueden compartir ruta)
191
+ # Ponlo en True si sueles leer varias rutas del mismo entorno y no quieres que la
192
+ # segunda lectura te machaque el fichero de la primera.
139
193
  fichero_por_ruta = False
140
194
 
141
195
 
142
196
  ## Configuraciones Tags
143
197
 
198
+ # Gestionar las tags de los parámetros: leerlas de AWS, exponerlas en el fichero
199
+ # exportado para editarlas y validar las obligatorias al cargar.
200
+ # True -> las tags viajan en el fichero y se validan.
201
+ # False -> no aparecen tags en el fichero y no se valida nada.
202
+ # En cuentas cuyo control de acceso va por tags (ABAC vía IAM) esto debe estar en True.
144
203
  tags_activas = True
145
204
 
205
+ # Solo aplica si tags_activas = True.
206
+ # False -> validación bloqueante: si a un parámetro le falta alguna tag obligatoria
207
+ # no se sube (ni su valor ni sus tags).
208
+ # True -> se permiten vacías: el parámetro se sube igualmente y las tags sin valor
209
+ # simplemente NO se crean en AWS (no se suben como etiquetas vacías).
146
210
  obligatorias_vacias = False
147
211
 
212
+ # Tags que se exigen en cada parámetro cuando tags_activas = True. La lista es libre:
213
+ # estas 8 son las que sostienen el control de acceso ABAC vía IAM de nuestra cuenta.
148
214
  tags_obligatorias = [
149
- "Application", "Environment", "Owner", "Project",
150
- "Product", "Service", "Component", "ManagedBy",
215
+ "Application",
216
+ "Environment",
217
+ "Owner",
218
+ "Project",
219
+ "Product",
220
+ "Service",
221
+ "Component",
222
+ "ManagedBy",
151
223
  ]
152
224
  ```
153
225
  Nota: Si el archivo paramsx_config.py ya existe, no será sobrescrito durante la instalación para proteger las configuraciones personalizadas.
154
226
 
155
227
  ### Los perfiles de naming
156
228
 
157
- Cada organización nombra sus parámetros a su manera, así que ParamsX no impone ninguna convención: **tú defines los perfiles que uses en el diccionario `naming` y les pones el nombre que quieras**. Cada entrada de `parameter_list` declara con qué perfil se construye su ruta completa.
158
-
159
- Un perfil tiene tres campos:
160
-
161
- | Campo | Valores | Qué decide |
162
- |---|---|---|
163
- | `posicion_entorno` | `inicio` \| `final` \| `mixto` \| `ninguno` | Dónde va el entorno dentro de la ruta. |
164
- | `case_entorno` | `lower` \| `upper` \| `capitalize` | Cómo se escribe el entorno. |
165
- | `case_ruta` | `lower` \| `upper` \| `capitalize` \| `ninguno` | Case de la ruta al crear parámetros. |
166
-
167
- Y en detalle:
168
-
169
- **`posicion_entorno`** — dónde se coloca el entorno, con el entorno `dev`:
170
-
171
- | Valor | Ruta declarada | Ruta real en AWS | |
172
- |---|---|---|---|
173
- | `inicio` | `/rds` | `/dev/rds` | |
174
- | `final` | `/API/STA` | `/API/STA/DEV` | |
175
- | `mixto` | `/API/*/STA` | `/API/DEV/STA` | el `*` marca el sitio |
176
- | `ninguno` | `/api/sta/auth` | `/api/sta/auth` | una cuenta AWS por entorno |
177
-
178
- **`case_entorno`** — cómo se escribe ese entorno en la ruta:
179
-
180
- | Valor | `dev` se escribe | `/API/STA` con `posicion_entorno: final` |
181
- |---|---|---|
182
- | `lower` | `dev` | `/API/STA/dev` |
183
- | `upper` | `DEV` | `/API/STA/DEV` |
184
- | `capitalize` | `Dev` | `/API/STA/Dev` |
185
-
186
- **`case_ruta`** — a qué case se fuerza la ruta que escribes al **crear** un parámetro (opción 4). No afecta a leer ni a editar: lo que ya existe en AWS se respeta siempre tal cual esté.
187
-
188
- | Valor | Si escribes `/API/MULTIAPI/Token`, se crea |
189
- |---|---|
190
- | `lower` | `/api/multiapi/token` |
191
- | `upper` | `/API/MULTIAPI/TOKEN` |
192
- | `capitalize` | `/Api/Multiapi/Token` |
193
- | `ninguno` | `/API/MULTIAPI/Token` |
229
+ Cada organización nombra sus parámetros a su manera, así que ParamsX no impone ninguna convención: **tú defines los perfiles que uses en el diccionario `naming` y les pones el nombre que quieras**. Cada entrada de `parameter_list` declara con qué perfil se construye su ruta completa. Los tres campos de un perfil y sus valores están explicados en el propio fichero de configuración, ahí arriba.
194
230
 
195
231
  **No hay una lista cerrada de perfiles.** Los tres campos se combinan libremente, así que la plantilla no intenta traértelos todos: define los dos o tres que use tu organización y olvídate del resto. `min` y `max` vienen predefinidos porque son los que ParamsX traía antes de que los perfiles fueran configurables.
196
232
 
197
- **`mixto` y el marcador `*`.** Cuando el entorno no va ni al principio ni al final, se marca su sitio con un `*` en la propia ruta. Es útil para acotar la lectura a un solo subárbol: con `/API/MULTIAPI/*/stan_ai` lees únicamente `/API/MULTIAPI/DEV/stan_ai`, en vez de todo lo que cuelga de `/API/MULTIAPI/DEV`. El `*` debe ser un segmento entero y aparecer **exactamente una vez**, y solo se admite en perfiles `mixto`: si el perfil y la ruta no cuentan la misma historia, ParamsX te lo dice al arrancar en vez de leer una ruta inexistente y devolverte una lista vacía.
198
-
199
- **`ninguno` y las cuentas sin entorno en la ruta.** Hay organizaciones que separan los entornos por cuenta de AWS y no meten `dev`/`prod` en el path. Con `posicion_entorno: "ninguno"` la ruta se usa tal cual; el selector de entorno del menú sigue existiendo, pero no toca la ruta. En este perfil el `case_entorno` es irrelevante, porque no se escribe ningún entorno.
233
+ **Para qué sirve el `*`.** Además de colocar el entorno donde quieras, acota la lectura a un solo subárbol: con `/API/MULTIAPI/*/stan_ai` lees únicamente `/API/MULTIAPI/DEV/stan_ai`, en vez de todo lo que cuelga de `/API/MULTIAPI/DEV`. Debe ser un segmento entero, aparecer **exactamente una vez** y solo se admite en perfiles `mixto`: si el perfil y la ruta no cuentan la misma historia, ParamsX te lo dice al arrancar en vez de leer una ruta inexistente y devolverte una lista vacía.
200
234
 
201
- Ya **no existe** la lista `entornos_old`: el entorno se escribe siempre a partir de la lista canónica `entornos` (en minúscula), aplicándole el `case_entorno` del perfil. Si en tus rutas el entorno se llama `staging` en vez de `pre`, ponlo así en `entornos`.
235
+ **Los entornos.** Ya no existe la lista `entornos_old`: el entorno sale siempre de la lista canónica `entornos` (en minúscula), aplicándole el `case_entorno` del perfil. Si en tus rutas se llama `staging` en vez de `pre`, ponlo así en `entornos`.
202
236
 
203
- Ejemplo completo de una `parameter_list` real, mezclando perfiles:
204
-
205
- ```python
206
- "parameter_list": [
207
- {"path": "/common", "convencion": "min"},
208
- {"path": "/rds", "convencion": "min"},
209
- {"path": "/api", "convencion": "min"},
210
- {"path": "/INFRA", "convencion": "max"},
211
- {"path": "/API/STA", "convencion": "max"},
212
- {"path": "/API/p15", "convencion": "max"},
213
- {"path": "/API/MULTIAPI", "convencion": "max"},
214
- {"path": "/APP/Alertas", "convencion": "max"},
215
- {"path": "/BUCKETS", "convencion": "max"},
216
- {"path": "/EMAIL", "convencion": "max"},
217
- {"path": "/INFERENCIAS/TASA_DMI", "convencion": "max"},
218
- {"path": "/CEE/CEXGEN", "convencion": "max"},
219
- {"path": "/API/MULTIAPI/*/stan_ai", "convencion": "mixto_max"},
220
- ]
221
- ```
222
-
223
- Sobre mayúsculas y minúsculas: ParamsX **no renombra ni fuerza el case de los parámetros que ya existen**, los lee y edita tal cual estén. El `case_ruta` del perfil solo entra en juego al crear parámetros nuevos.
237
+ Y ParamsX **no renombra ni fuerza el case de los parámetros que ya existen**: los lee y edita tal cual estén. El `case_ruta` del perfil solo entra en juego al crear parámetros nuevos.
224
238
 
225
239
  ### Un fichero por ruta: `fichero_por_ruta`
226
240
 
@@ -322,7 +336,17 @@ En algunos sistemas (especialmente en entornos corporativos como Windows), el PA
322
336
  ```source ~/.zshrc # Para zsh```
323
337
 
324
338
  Una vez instalado, verifica que el comando paramsx esté disponible ejecutando:
325
- ```paramsx --help```
339
+ ```paramsx --version```
340
+
341
+ Comandos disponibles:
342
+
343
+ | Comando | Qué hace |
344
+ |---|---|
345
+ | `paramsx` | Abre el menú interactivo (necesita configuración). |
346
+ | `paramsx configure` | Crea la configuración la primera vez; si ya existe, la revisa sin tocarla. |
347
+ | `paramsx configure --ejemplo` | Además deja la plantilla de esta versión al lado, para comparar. |
348
+ | `paramsx --version` | Versión instalada. |
349
+ | `paramsx --help` | Ayuda, con el resumen de todas las opciones de configuración. |
326
350
 
327
351
 
328
352
  ## Modo de empleo
@@ -0,0 +1 @@
1
+ __version__ = "2.2.1"
@@ -7,6 +7,7 @@ import curses
7
7
  import importlib.util
8
8
  from botocore.exceptions import ClientError
9
9
  from . import paramsx_config as plantilla_config
10
+ from . import __version__
10
11
  from .funcions import (
11
12
  draw_header, draw_footer, show_main_menu, show_comparison_results,
12
13
  show_environment_selection, show_message, show_parameter_selection,
@@ -47,13 +48,27 @@ Ya no existe 'entornos_old': el entorno se escribe a partir de la lista 'entorno
47
48
  que va siempre en minúscula, aplicándole el 'case_entorno' del perfil."""
48
49
 
49
50
 
50
- # Cargar configuraciones desde el archivo de usuario
51
- def load_config():
51
+ # Opciones que viven fuera de 'configuraciones' y son opcionales: si el usuario no las
52
+ # tiene, se usa el valor de la plantilla. Se listan para poder decirle qué le falta.
53
+ CLAVES_OPCIONALES = (
54
+ "naming", "convencion_nuevos", "fichero_por_ruta",
55
+ "tags_activas", "obligatorias_vacias", "tags_obligatorias",
56
+ )
57
+
58
+
59
+ # Ejecutar el fichero de configuración del usuario y devolver el módulo resultante
60
+ def cargar_modulo_config():
52
61
  if not os.path.exists(CONFIG_PATH):
53
62
  raise FileNotFoundError(f"No se encontró el archivo de configuración en {CONFIG_PATH}")
54
63
  spec = importlib.util.spec_from_file_location("config", CONFIG_PATH)
55
64
  modulo = importlib.util.module_from_spec(spec)
56
65
  spec.loader.exec_module(modulo)
66
+ return modulo
67
+
68
+
69
+ # Cargar configuraciones desde el archivo de usuario
70
+ def load_config():
71
+ modulo = cargar_modulo_config()
57
72
 
58
73
  config = dict(modulo.configuraciones)
59
74
  # Todo lo que va fuera de 'configuraciones' es opcional en el fichero del usuario:
@@ -814,48 +829,141 @@ def main(stdscr, config=None):
814
829
 
815
830
 
816
831
  # Función para crear la configuración inicial
817
- def create_config():
832
+ def create_config(escribir_ejemplo=False):
818
833
  config_dir = os.path.expanduser("~/.xsoft")
819
834
  os.makedirs(config_dir, exist_ok=True)
820
835
 
821
836
  config_file = os.path.join(config_dir, "paramsx_config.py")
822
- if os.path.exists(config_file):
823
- print(f"El archivo de configuración ya existe en {config_file}. No se sobrescribirá.")
824
- else:
837
+ if not os.path.exists(config_file):
825
838
  # Se copia la plantilla del paquete para no duplicar el formato en dos sitios
826
839
  shutil.copyfile(PLANTILLA_PATH, config_file)
827
- print(f"Archivo de configuración creado en {config_file}. Por favor, edítalo con tus valores personalizados.")
840
+ print(f"Archivo de configuración creado en {config_file}.")
841
+ print("Ábrelo y ajústalo con tus valores: viene con cada opción comentada.")
842
+ return
843
+
844
+ # Con configuración ya hecha no se toca NADA: solo se revisa y se informa.
845
+ print(f"Ya tienes configuración en {config_file}, no se sobrescribe.")
846
+ print()
847
+ revisar_config(config_file)
848
+
849
+ ejemplo_file = os.path.join(config_dir, "paramsx_config.ejemplo.py")
850
+ if escribir_ejemplo:
851
+ shutil.copyfile(PLANTILLA_PATH, ejemplo_file)
852
+ print(f"\nPlantilla de esta versión escrita en {ejemplo_file}.")
853
+ print("Es solo una referencia para comparar: ParamsX no la lee.")
854
+ else:
855
+ print("\nPara dejar la plantilla de esta versión al lado de la tuya y comparar:")
856
+ print(" paramsx configure --ejemplo")
857
+
858
+
859
+ # Valor por defecto en una línea: el repr de 'naming' o de las tags ocupa media pantalla
860
+ def resumir_valor(valor):
861
+ if isinstance(valor, dict):
862
+ return f"{len(valor)} perfiles ({', '.join(valor)})"
863
+ if isinstance(valor, (list, tuple)):
864
+ elementos = ", ".join(str(v) for v in valor)
865
+ if len(elementos) > 50:
866
+ elementos = ", ".join(str(v) for v in list(valor)[:3]) + ", ..."
867
+ return f"{len(valor)} elementos ({elementos})"
868
+ return repr(valor)
869
+
870
+
871
+ # Revisar una configuración existente sin modificarla: qué opciones nuevas le faltan
872
+ # (que no son un error, se usa el valor por defecto) y qué está mal de verdad.
873
+ def revisar_config(config_file):
874
+ try:
875
+ modulo = cargar_modulo_config()
876
+ except Exception as e:
877
+ print(f"No se ha podido leer: {e}")
878
+ return
879
+
880
+ faltan = [clave for clave in CLAVES_OPCIONALES if not hasattr(modulo, clave)]
881
+ # 'abac' es el nombre antiguo de 'tags_activas': teniéndolo no falta nada
882
+ if "tags_activas" in faltan and hasattr(modulo, "abac"):
883
+ faltan.remove("tags_activas")
884
+ print("- 'abac' es el nombre antiguo de 'tags_activas'. Sigue funcionando, pero")
885
+ print(" renómbralo cuando puedas: el nuevo dice lo que hace.")
886
+
887
+ if faltan:
888
+ print("Opciones que no tienes y que ParamsX rellena con el valor por defecto:")
889
+ for clave in faltan:
890
+ print(f" {clave:20} -> {resumir_valor(getattr(plantilla_config, clave))}")
891
+ print("Añádelas solo si quieres cambiarlas; sin ellas todo sigue funcionando igual.")
892
+ else:
893
+ print("No te falta ninguna opción de esta versión.")
894
+
895
+ try:
896
+ # Validar SIN normalizar: normalize_config pasa 'entornos' a minúscula y se
897
+ # perdería el aviso de que están en mayúscula en el fichero del usuario.
898
+ errores, avisos = validate_config(load_config())
899
+ except Exception as e:
900
+ print(f"\nNo se ha podido validar: {e}")
901
+ return
902
+
903
+ if avisos:
904
+ print()
905
+ for aviso in avisos:
906
+ print(aviso)
907
+ if errores:
908
+ print("\nErrores que hay que corregir:\n")
909
+ for error in errores:
910
+ print(f"{error}\n")
911
+ else:
912
+ print("\nLa configuración es válida.")
913
+
914
+
915
+ # Versión instalada del paquete; si se ejecuta desde el código fuente, la del módulo
916
+ def version_actual():
917
+ try:
918
+ from importlib.metadata import version, PackageNotFoundError
919
+ try:
920
+ return version("paramsx")
921
+ except PackageNotFoundError:
922
+ return f"{__version__} (desde el código fuente, sin instalar)"
923
+ except ImportError:
924
+ return __version__
828
925
 
829
926
  # Mostrar ayuda
830
927
  def show_help():
928
+ # Texto plano, no f-string: lleva llaves literales de los dicts de ejemplo
831
929
  help_text = """
832
- ParamsX - Gestión de Parámetros de AWS SSM
930
+ ParamsX __VERSION__ - Gestión de Parámetros de AWS SSM
833
931
 
834
932
  Comandos disponibles:
835
- paramsx Ejecuta el programa principal (requiere configuración previa).
836
- paramsx configure Crea el archivo de configuración inicial en ~/.xsoft/paramsx_config.py.
837
- paramsx --help Muestra esta ayuda.
933
+ paramsx Ejecuta el programa principal (requiere configuración previa).
934
+ paramsx configure Crea ~/.xsoft/paramsx_config.py la primera vez. Si ya lo tienes,
935
+ NO lo toca: revisa qué opciones nuevas te faltan y si es válido.
936
+ paramsx configure --ejemplo Además deja la plantilla de esta versión al lado, como
937
+ paramsx_config.ejemplo.py, para comparar sin tocar la tuya.
938
+ paramsx --version Muestra la versión instalada.
939
+ paramsx --help Muestra esta ayuda.
838
940
 
839
941
  Opciones del menú:
840
942
  1. Leer parámetros Exporta a un fichero editable los parámetros de una ruta.
841
- 2. Cargar parámetros Compara el fichero editado y aplica los cambios en AWS.
943
+ 2. Cargar parámetros Elige uno de los ficheros exportados que tengas en el
944
+ directorio, compara y aplica los cambios en AWS.
842
945
  3. Crear Backup de parámetros Respalda una ruta, la lista completa o toda la cuenta.
843
946
  4. Crear nuevo parámetro Crea un parámetro nuevo con el perfil 'convencion_nuevos'.
844
947
 
845
- Configuración (~/.xsoft/paramsx_config.py):
846
- naming Perfiles de naming. Cada uno dice dónde va el entorno en la ruta
847
- y cómo se escribe. Los nombres los eliges tú:
948
+ Configuración (~/.xsoft/paramsx_config.py). El fichero trae comentada cada opción:
949
+ profile_name Perfil de ~/.aws/credentials.
950
+ region_name Región de AWS.
951
+ entornos Lista de entornos, SIEMPRE en minúscula: ['dev', 'pre', 'prod'].
952
+ Cada perfil de naming decide cómo se escriben en la ruta.
953
+ naming Perfiles de naming: cómo se construye la ruta real en AWS. Los
954
+ nombres los eliges tú y combinas estos tres campos:
848
955
  posicion_entorno 'inicio' /rds -> /dev/rds
849
956
  'final' /API/STA -> /API/STA/DEV
850
- 'mixto' /API/*/STA -> /API/dev/STA
957
+ 'mixto' /API/*/STA -> /API/DEV/STA
851
958
  'ninguno' /api/auth -> /api/auth
852
959
  case_entorno 'lower' | 'upper' | 'capitalize'
853
960
  case_ruta 'lower' | 'upper' | 'capitalize' | 'ninguno'
854
- (solo al crear parámetros)
961
+ (solo al crear parámetros, opción 4)
855
962
  parameter_list Lista de dicts {"path": "/rds", "convencion": "<perfil de naming>"}.
856
963
  convencion_nuevos Perfil que usan los parámetros creados con la opción 4.
857
- fichero_por_ruta True -> el fichero exportado incluye la ruta en su nombre, para
858
- que leer otra ruta del mismo entorno no machaque la anterior.
964
+ fichero_por_ruta True -> el fichero exportado lleva entorno, ruta y perfil en el
965
+ nombre, para que leer otra ruta del mismo entorno no machaque la
966
+ anterior: parameters_dev__API_STA__max.py
859
967
  tags_activas True para gestionar las tags en el fichero exportado y validarlas.
860
968
  (antes se llamaba 'abac'; ese nombre se sigue aceptando)
861
969
  tags_obligatorias Tags exigidas en cada parámetro cuando tags_activas = True.
@@ -868,23 +976,29 @@ Si necesitas más ayuda puedes leer el readme en GitHub o en Pypi:
868
976
  - https://pypi.org/project/paramsx/
869
977
 
870
978
  """
871
- print(help_text)
979
+ print(help_text.replace("__VERSION__", version_actual()))
872
980
 
873
981
  # Entry point
874
982
  def entry_point():
875
983
  if len(sys.argv) > 1:
876
984
  command = sys.argv[1]
877
985
  if command in ["configure", "config", "configurar"]:
878
- create_config()
986
+ create_config(escribir_ejemplo="--ejemplo" in sys.argv[2:])
879
987
  return
880
988
  elif command in ["--help", "-h"]:
881
989
  show_help()
882
990
  return
991
+ elif command in ["--version", "-v", "version"]:
992
+ print(f"paramsx {version_actual()}")
993
+ return
883
994
 
884
995
  # Verificar que exista el archivo de configuración
885
996
  if not os.path.exists(CONFIG_PATH):
886
- print("Error: No se encontró el archivo de configuración.")
887
- print("Usa 'paramsx configure' para crear uno automáticamente.")
997
+ print("ParamsX todavía no está configurado.")
998
+ print(f"No existe {CONFIG_PATH}.")
999
+ print()
1000
+ print("Ejecuta 'paramsx configure': te crea el fichero con cada opción comentada")
1001
+ print("para que lo ajustes con tu perfil de AWS, tus entornos y tus rutas.")
888
1002
  return
889
1003
 
890
1004
  # Validar la configuración antes de entrar en la interfaz curses
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: paramsx
3
- Version: 2.2.0
3
+ Version: 2.2.1
4
4
  Summary: Librería para gestionar y respaldar parámetros de AWS SSM de manera sencilla y eficiente.
5
5
  Home-page: https://github.com/pistatxos/paramsx
6
6
  Author: Mariox
@@ -128,11 +128,55 @@ Este comando creará automáticamente una carpeta de configuración en tu direct
128
128
 
129
129
  Dentro de esta carpeta, encontrarás el archivo paramsx_config.py. Este archivo contiene la configuración inicial que debes ajustar según tu entorno.
130
130
 
131
+ Si ya tenías configuración de una versión anterior, `paramsx configure` **no la sobrescribe**: te dice qué opciones nuevas no tienes y con qué valor por defecto se están rellenando, y si la configuración es válida. Con `paramsx configure --ejemplo` además deja la plantilla de esta versión en `paramsx_config.ejemplo.py`, al lado de la tuya, para que compares sin tocar nada.
132
+
131
133
  Ejemplo del contenido de paramsx_config.py:
132
134
 
133
135
  ```python
134
136
  ## Configuraciones ParamsX
135
137
 
138
+ # --- Perfiles de naming -------------------------------------------------------------
139
+ # Un perfil dice CÓMO se construye la ruta real en AWS a partir de la ruta que declaras
140
+ # en 'parameter_list' y del entorno que eliges en el menú. Los nombres son tuyos: define
141
+ # solo los que uses y llámalos como quieras. Un perfil tiene tres campos:
142
+ #
143
+ # campo | valores | qué decide
144
+ # ------------------+------------------------------------------+---------------------------
145
+ # posicion_entorno | inicio | final | mixto | ninguno | dónde va el entorno
146
+ # case_entorno | lower | upper | capitalize | cómo se escribe el entorno
147
+ # case_ruta | lower | upper | capitalize | ninguno | case de la ruta AL CREAR
148
+ #
149
+ # posicion_entorno -> dónde se coloca el entorno (ejemplos con el entorno 'dev'):
150
+ #
151
+ # valor | ruta declarada | ruta real en AWS
152
+ # ---------+-----------------+--------------------------------------------------------
153
+ # inicio | /rds | /dev/rds
154
+ # final | /API/STA | /API/STA/DEV
155
+ # mixto | /API/*/STA | /API/DEV/STA el '*' marca el sitio; uno y como segmento
156
+ # ninguno | /api/sta/auth | /api/sta/auth una cuenta AWS por entorno; case_entorno da igual
157
+ #
158
+ # case_entorno -> cómo se escribe ese entorno en la ruta:
159
+ #
160
+ # valor | 'dev' se escribe | ruta real de /API/STA con posicion_entorno=final
161
+ # ------------+------------------+------------------------------------------------
162
+ # lower | dev | /API/STA/dev
163
+ # upper | DEV | /API/STA/DEV
164
+ # capitalize | Dev | /API/STA/Dev
165
+ #
166
+ # case_ruta -> a qué case se fuerza la ruta que TÚ escribes al CREAR un parámetro
167
+ # (opción 4 del menú). No afecta a leer ni a editar: lo que ya existe en AWS se
168
+ # respeta siempre tal cual esté.
169
+ #
170
+ # valor | si escribes /API/MULTIAPI/Token, se crea
171
+ # ------------+-----------------------------------------
172
+ # lower | /api/multiapi/token
173
+ # upper | /API/MULTIAPI/TOKEN
174
+ # capitalize | /Api/Multiapi/Token
175
+ # ninguno | /API/MULTIAPI/Token
176
+ #
177
+ # Combina los tres campos como necesites: no hay una lista cerrada de perfiles. En el
178
+ # README tienes más ejemplos.
179
+
136
180
  naming = {
137
181
  "min": {"posicion_entorno": "inicio", "case_entorno": "lower", "case_ruta": "lower"},
138
182
  "max": {"posicion_entorno": "final", "case_entorno": "upper", "case_ruta": "ninguno"},
@@ -150,97 +194,67 @@ configuraciones = {
150
194
  {"path": "/rds", "convencion": "min"}, # -> /dev/rds
151
195
  {"path": "/EMAIL", "convencion": "max"}, # -> /EMAIL/DEV
152
196
  {"path": "/API/STA", "convencion": "max"}, # -> /API/STA/DEV
197
+ # Con 'mixto' acotas por debajo del entorno: esto lee solo stan_ai, en vez de
198
+ # todo lo que cuelga de /API/MULTIAPI/DEV
153
199
  {"path": "/API/MULTIAPI/*/stan_ai", "convencion": "mixto_max"}, # -> /API/MULTIAPI/DEV/stan_ai
154
200
  ]
155
201
  }
156
202
 
203
+ # Perfil de naming que se usa al crear un parámetro nuevo (opción 4 del menú).
204
+ # Si no lo defines, se usa el primer perfil de 'naming'.
157
205
  convencion_nuevos = "min"
158
206
 
207
+ # ¿El nombre del fichero exportado incluye la ruta leída?
208
+ # False -> parameters_dev.py (comportamiento de siempre)
209
+ # True -> parameters_dev__API_STA__max.py (uno por entrada y entorno: lleva el
210
+ # entorno, la ruta y el perfil, porque dos entradas pueden compartir ruta)
211
+ # Ponlo en True si sueles leer varias rutas del mismo entorno y no quieres que la
212
+ # segunda lectura te machaque el fichero de la primera.
159
213
  fichero_por_ruta = False
160
214
 
161
215
 
162
216
  ## Configuraciones Tags
163
217
 
218
+ # Gestionar las tags de los parámetros: leerlas de AWS, exponerlas en el fichero
219
+ # exportado para editarlas y validar las obligatorias al cargar.
220
+ # True -> las tags viajan en el fichero y se validan.
221
+ # False -> no aparecen tags en el fichero y no se valida nada.
222
+ # En cuentas cuyo control de acceso va por tags (ABAC vía IAM) esto debe estar en True.
164
223
  tags_activas = True
165
224
 
225
+ # Solo aplica si tags_activas = True.
226
+ # False -> validación bloqueante: si a un parámetro le falta alguna tag obligatoria
227
+ # no se sube (ni su valor ni sus tags).
228
+ # True -> se permiten vacías: el parámetro se sube igualmente y las tags sin valor
229
+ # simplemente NO se crean en AWS (no se suben como etiquetas vacías).
166
230
  obligatorias_vacias = False
167
231
 
232
+ # Tags que se exigen en cada parámetro cuando tags_activas = True. La lista es libre:
233
+ # estas 8 son las que sostienen el control de acceso ABAC vía IAM de nuestra cuenta.
168
234
  tags_obligatorias = [
169
- "Application", "Environment", "Owner", "Project",
170
- "Product", "Service", "Component", "ManagedBy",
235
+ "Application",
236
+ "Environment",
237
+ "Owner",
238
+ "Project",
239
+ "Product",
240
+ "Service",
241
+ "Component",
242
+ "ManagedBy",
171
243
  ]
172
244
  ```
173
245
  Nota: Si el archivo paramsx_config.py ya existe, no será sobrescrito durante la instalación para proteger las configuraciones personalizadas.
174
246
 
175
247
  ### Los perfiles de naming
176
248
 
177
- Cada organización nombra sus parámetros a su manera, así que ParamsX no impone ninguna convención: **tú defines los perfiles que uses en el diccionario `naming` y les pones el nombre que quieras**. Cada entrada de `parameter_list` declara con qué perfil se construye su ruta completa.
178
-
179
- Un perfil tiene tres campos:
180
-
181
- | Campo | Valores | Qué decide |
182
- |---|---|---|
183
- | `posicion_entorno` | `inicio` \| `final` \| `mixto` \| `ninguno` | Dónde va el entorno dentro de la ruta. |
184
- | `case_entorno` | `lower` \| `upper` \| `capitalize` | Cómo se escribe el entorno. |
185
- | `case_ruta` | `lower` \| `upper` \| `capitalize` \| `ninguno` | Case de la ruta al crear parámetros. |
186
-
187
- Y en detalle:
188
-
189
- **`posicion_entorno`** — dónde se coloca el entorno, con el entorno `dev`:
190
-
191
- | Valor | Ruta declarada | Ruta real en AWS | |
192
- |---|---|---|---|
193
- | `inicio` | `/rds` | `/dev/rds` | |
194
- | `final` | `/API/STA` | `/API/STA/DEV` | |
195
- | `mixto` | `/API/*/STA` | `/API/DEV/STA` | el `*` marca el sitio |
196
- | `ninguno` | `/api/sta/auth` | `/api/sta/auth` | una cuenta AWS por entorno |
197
-
198
- **`case_entorno`** — cómo se escribe ese entorno en la ruta:
199
-
200
- | Valor | `dev` se escribe | `/API/STA` con `posicion_entorno: final` |
201
- |---|---|---|
202
- | `lower` | `dev` | `/API/STA/dev` |
203
- | `upper` | `DEV` | `/API/STA/DEV` |
204
- | `capitalize` | `Dev` | `/API/STA/Dev` |
205
-
206
- **`case_ruta`** — a qué case se fuerza la ruta que escribes al **crear** un parámetro (opción 4). No afecta a leer ni a editar: lo que ya existe en AWS se respeta siempre tal cual esté.
207
-
208
- | Valor | Si escribes `/API/MULTIAPI/Token`, se crea |
209
- |---|---|
210
- | `lower` | `/api/multiapi/token` |
211
- | `upper` | `/API/MULTIAPI/TOKEN` |
212
- | `capitalize` | `/Api/Multiapi/Token` |
213
- | `ninguno` | `/API/MULTIAPI/Token` |
249
+ Cada organización nombra sus parámetros a su manera, así que ParamsX no impone ninguna convención: **tú defines los perfiles que uses en el diccionario `naming` y les pones el nombre que quieras**. Cada entrada de `parameter_list` declara con qué perfil se construye su ruta completa. Los tres campos de un perfil y sus valores están explicados en el propio fichero de configuración, ahí arriba.
214
250
 
215
251
  **No hay una lista cerrada de perfiles.** Los tres campos se combinan libremente, así que la plantilla no intenta traértelos todos: define los dos o tres que use tu organización y olvídate del resto. `min` y `max` vienen predefinidos porque son los que ParamsX traía antes de que los perfiles fueran configurables.
216
252
 
217
- **`mixto` y el marcador `*`.** Cuando el entorno no va ni al principio ni al final, se marca su sitio con un `*` en la propia ruta. Es útil para acotar la lectura a un solo subárbol: con `/API/MULTIAPI/*/stan_ai` lees únicamente `/API/MULTIAPI/DEV/stan_ai`, en vez de todo lo que cuelga de `/API/MULTIAPI/DEV`. El `*` debe ser un segmento entero y aparecer **exactamente una vez**, y solo se admite en perfiles `mixto`: si el perfil y la ruta no cuentan la misma historia, ParamsX te lo dice al arrancar en vez de leer una ruta inexistente y devolverte una lista vacía.
218
-
219
- **`ninguno` y las cuentas sin entorno en la ruta.** Hay organizaciones que separan los entornos por cuenta de AWS y no meten `dev`/`prod` en el path. Con `posicion_entorno: "ninguno"` la ruta se usa tal cual; el selector de entorno del menú sigue existiendo, pero no toca la ruta. En este perfil el `case_entorno` es irrelevante, porque no se escribe ningún entorno.
253
+ **Para qué sirve el `*`.** Además de colocar el entorno donde quieras, acota la lectura a un solo subárbol: con `/API/MULTIAPI/*/stan_ai` lees únicamente `/API/MULTIAPI/DEV/stan_ai`, en vez de todo lo que cuelga de `/API/MULTIAPI/DEV`. Debe ser un segmento entero, aparecer **exactamente una vez** y solo se admite en perfiles `mixto`: si el perfil y la ruta no cuentan la misma historia, ParamsX te lo dice al arrancar en vez de leer una ruta inexistente y devolverte una lista vacía.
220
254
 
221
- Ya **no existe** la lista `entornos_old`: el entorno se escribe siempre a partir de la lista canónica `entornos` (en minúscula), aplicándole el `case_entorno` del perfil. Si en tus rutas el entorno se llama `staging` en vez de `pre`, ponlo así en `entornos`.
255
+ **Los entornos.** Ya no existe la lista `entornos_old`: el entorno sale siempre de la lista canónica `entornos` (en minúscula), aplicándole el `case_entorno` del perfil. Si en tus rutas se llama `staging` en vez de `pre`, ponlo así en `entornos`.
222
256
 
223
- Ejemplo completo de una `parameter_list` real, mezclando perfiles:
224
-
225
- ```python
226
- "parameter_list": [
227
- {"path": "/common", "convencion": "min"},
228
- {"path": "/rds", "convencion": "min"},
229
- {"path": "/api", "convencion": "min"},
230
- {"path": "/INFRA", "convencion": "max"},
231
- {"path": "/API/STA", "convencion": "max"},
232
- {"path": "/API/p15", "convencion": "max"},
233
- {"path": "/API/MULTIAPI", "convencion": "max"},
234
- {"path": "/APP/Alertas", "convencion": "max"},
235
- {"path": "/BUCKETS", "convencion": "max"},
236
- {"path": "/EMAIL", "convencion": "max"},
237
- {"path": "/INFERENCIAS/TASA_DMI", "convencion": "max"},
238
- {"path": "/CEE/CEXGEN", "convencion": "max"},
239
- {"path": "/API/MULTIAPI/*/stan_ai", "convencion": "mixto_max"},
240
- ]
241
- ```
242
-
243
- Sobre mayúsculas y minúsculas: ParamsX **no renombra ni fuerza el case de los parámetros que ya existen**, los lee y edita tal cual estén. El `case_ruta` del perfil solo entra en juego al crear parámetros nuevos.
257
+ Y ParamsX **no renombra ni fuerza el case de los parámetros que ya existen**: los lee y edita tal cual estén. El `case_ruta` del perfil solo entra en juego al crear parámetros nuevos.
244
258
 
245
259
  ### Un fichero por ruta: `fichero_por_ruta`
246
260
 
@@ -342,7 +356,17 @@ En algunos sistemas (especialmente en entornos corporativos como Windows), el PA
342
356
  ```source ~/.zshrc # Para zsh```
343
357
 
344
358
  Una vez instalado, verifica que el comando paramsx esté disponible ejecutando:
345
- ```paramsx --help```
359
+ ```paramsx --version```
360
+
361
+ Comandos disponibles:
362
+
363
+ | Comando | Qué hace |
364
+ |---|---|
365
+ | `paramsx` | Abre el menú interactivo (necesita configuración). |
366
+ | `paramsx configure` | Crea la configuración la primera vez; si ya existe, la revisa sin tocarla. |
367
+ | `paramsx configure --ejemplo` | Además deja la plantilla de esta versión al lado, para comparar. |
368
+ | `paramsx --version` | Versión instalada. |
369
+ | `paramsx --help` | Ayuda, con el resumen de todas las opciones de configuración. |
346
370
 
347
371
 
348
372
  ## Modo de empleo
@@ -2,6 +2,7 @@ from setuptools import setup, find_packages
2
2
  from setuptools.command.install import install
3
3
  from distutils import log
4
4
  import os
5
+ import re
5
6
  import sys
6
7
  import shutil
7
8
  import platform
@@ -73,10 +74,15 @@ class CustomInstallCommand(install):
73
74
  with open("README.md", "r", encoding="utf-8") as fh:
74
75
  long_description = fh.read()
75
76
 
77
+ ## La versión vive en paramsx/__init__.py, para que 'paramsx --version' y el paquete
78
+ ## no puedan decir cosas distintas. Se lee con regex para no importar el paquete aquí.
79
+ with open("paramsx/__init__.py", "r", encoding="utf-8") as fh:
80
+ version = re.search(r'^__version__\s*=\s*"([^"]+)"', fh.read(), re.M).group(1)
81
+
76
82
  # Configuración del paquete
77
83
  setup(
78
84
  name="paramsx",
79
- version="2.2.0",
85
+ version=version,
80
86
  packages=find_packages(),
81
87
  include_package_data=True,
82
88
  package_data={
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes