python-rundeck 0.1.0__py3-none-any.whl → 0.3.0__py3-none-any.whl

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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-rundeck
3
- Version: 0.1.0
3
+ Version: 0.3.0
4
4
  Summary: Python client for the Rundeck API (v14-v56).
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -29,48 +29,55 @@ Requires-Dist: pytest-cov (>=5.0.0,<6.0.0) ; extra == "dev"
29
29
  Requires-Dist: requests (>=2.32.5,<3.0.0)
30
30
  Requires-Dist: ruff (>=0.7.0,<1.0.0) ; extra == "dev"
31
31
  Requires-Dist: safety (>=3.2.0,<4.0.0) ; extra == "dev"
32
+ Project-URL: Changelog, https://gitlab.com/pascal.seckinger/python-rundeck/-/blob/main/CHANGELOG.md
33
+ Project-URL: Documentation, https://gitlab.com/pascal.seckinger/python-rundeck/-/blob/main/README.md
34
+ Project-URL: Homepage, https://gitlab.com/pascal.seckinger/python-rundeck
35
+ Project-URL: Issues, https://gitlab.com/pascal.seckinger/python-rundeck/-/issues
36
+ Project-URL: Repository, https://gitlab.com/pascal.seckinger/python-rundeck
32
37
  Description-Content-Type: text/markdown
33
38
 
34
39
  python-rundeck
35
40
  ===============
41
+ ![PyPI Version](https://img.shields.io/pypi/v/python-rundeck)
42
+ ![Python Versions](https://img.shields.io/pypi/pyversions/python-rundeck)
43
+ ![License](https://img.shields.io/pypi/l/python-rundeck)
44
+ ![Downloads](https://static.pepy.tech/badge/python-rundeck)
36
45
 
37
- Client Python pour l’API Rundeck (v14v56), inspiré de l’architecture de python-gitlab. Fournit des managers typés pour les ressources clés (projects, jobs, executions, tokens, users, système, configuration) et SCM (import/export).
46
+ Python client for the Rundeck API (v14-v56), inspired by the python-gitlab architecture. Provides typed managers for key resources (projects, jobs, executions, tokens, users, system, configuration) and SCM (import/export).
38
47
 
39
- Sommaire
48
+ Contents
40
49
  --------
41
50
  - Installation
42
- - Démarrage rapide
51
+ - Quick start
43
52
  - Configuration
44
- - Ressources disponibles
45
- - Exemples par ressource
46
- - Gestion des erreurs
47
- - Développement et tests
53
+ - Available resources
54
+ - Examples by resource
55
+ - Error handling
56
+ - Development and testing
48
57
 
49
58
  Installation
50
59
  ------------
51
- Prerequis : Python 3.11+. Le projet utilise Poetry.
60
+ Prerequisites: Python 3.11+. Install from PyPI.
52
61
 
53
62
  ```bash
54
- poetry install
55
- # ou en editable avec pip
56
- pip install -e .
63
+ pip install python-rundeck
57
64
  ```
58
65
 
59
- Démarrage rapide
60
- ----------------
66
+ Quick start
67
+ -----------
61
68
  ```python
62
69
  from rundeck.client import Rundeck
63
70
 
64
71
  rd = Rundeck(url="https://rundeck.example.com", token="MY_TOKEN", api_version=56)
65
- # Auth par mot de passe (session cookie) si pas de token
72
+ # Password auth (session cookie) if no token
66
73
  rd = Rundeck(url="https://rundeck.example.com", username="admin", password="admin", api_version=56)
67
74
 
68
- # Lister les projets
75
+ # List projects
69
76
  projects = rd.projects.list()
70
77
  for p in projects:
71
78
  print(p.name)
72
79
 
73
- # Récupérer un projet et lancer un job
80
+ # Get a project and run a job
74
81
  project = rd.projects.get("demo")
75
82
  jobs = project.jobs.list()
76
83
  execu = jobs[0].run()
@@ -79,64 +86,64 @@ print(execu.id)
79
86
 
80
87
  Configuration
81
88
  -------------
82
- La configuration suit un modèle en cascade (args > env > fichiers > défauts) via `RundeckConfig`.
83
-
84
- Paramètres principaux :
85
- - `url` : URL Rundeck (ex. `https://rundeck.example.com`)
86
- - `token` : Token API (en-tête `X-Rundeck-Auth-Token`)
87
- - `username` / `password` : Authentification par session (j_security_check) si aucun token n'est fourni.
88
- - `api_version` : Version d’API (ex. `56`)
89
- - `timeout` : Timeout des requêtes (float, secondes)
90
- - `ssl_verify` : Vérification TLS (bool ou chemin CA)
91
-
92
- Fichiers de config : si besoin, passez `config_files` ou `Rundeck.from_config(config_section=...)`.
93
- Variables d'env utiles (config client) :
94
- - `RUNDECK_URL` : URL de base
95
- - `RUNDECK_TOKEN` : token API (en-tête `X-Rundeck-Auth-Token`)
96
- - `RUNDECK_USERNAME` / `RUNDECK_PASSWORD` : auth session (si pas de token)
97
- - `RUNDECK_API_VERSION` : version d'API (ex: 56)
98
- - `RUNDECK_TIMEOUT` : timeout des requêtes (secondes)
99
- - `RUNDECK_SSL_VERIFY` : vérification TLS (bool ou chemin CA)
100
- - `RUNDECK_USER_AGENT` : User-Agent HTTP
101
-
102
- Ressources disponibles
103
- ----------------------
104
- - `projects` (`ProjectManager`) : CRUD projets, export/import de jobs, config projet, archive (export/import).
105
- - `jobs` (`JobManager`) : liste, get, suppressions, actions bulk, exécution.
106
- - `executions` (`ExecutionManager`) : liste/filtre, running, get/delete, query avancée.
107
- - `tokens` (`TokenManager`) : liste, get, create, delete.
108
- - `users` (`UserManager`) : opérations utilisateurs (selon implémentation courante).
109
- - `metrics` (`MetricsManager`) : endpoints `/metrics` (list/data/healthcheck/ping).
110
- - `plugins` (`PluginManager`) : liste des plugins installés (`/plugin/list`).
111
- - `webhooks` (`WebhookEventManager` + `ProjectWebhookManager`) : gestion des webhooks projet et envoi via token.
112
- - `key_storage` (`StorageKeyManager`) : gestion du stockage des clés `/storage/keys`.
113
- - `adhoc` (`AdhocManager`, via `project.adhoc`) : exécution de commandes/scripts AdHoc.
114
- - `system` (`SystemManager`) : info système, exécutions enable/disable, logstorage, ACL.
115
- - `config_management` (`ConfigManagementManager`) : configuration globale `/config`.
116
- - `scm` (via `project.scm` et `job.scm`) : plugins import/export, setup, enable/disable, statut, actions (commit/import/export...).
117
-
118
- Exemples par ressource (complets)
119
- ---------------------------------
120
- Projets
89
+ Configuration follows a cascading model (args > env > files > defaults) via `RundeckConfig`.
90
+
91
+ Main parameters:
92
+ - `url`: Rundeck URL (e.g. `https://rundeck.example.com`)
93
+ - `token`: API token (header `X-Rundeck-Auth-Token`)
94
+ - `username` / `password`: Session authentication (j_security_check) if no token is provided.
95
+ - `api_version`: API version (e.g. `56`)
96
+ - `timeout`: Request timeout (float, seconds)
97
+ - `ssl_verify`: TLS verification (bool or CA path)
98
+
99
+ Config files: if needed, pass `config_files` or `Rundeck.from_config(config_section=...)`.
100
+ Useful env vars (client config):
101
+ - `RUNDECK_URL`: Base URL
102
+ - `RUNDECK_TOKEN`: API token (header `X-Rundeck-Auth-Token`)
103
+ - `RUNDECK_USERNAME` / `RUNDECK_PASSWORD`: Session auth (if no token)
104
+ - `RUNDECK_API_VERSION`: API version (e.g. 56)
105
+ - `RUNDECK_TIMEOUT`: Request timeout (seconds)
106
+ - `RUNDECK_SSL_VERIFY`: TLS verification (bool or CA path)
107
+ - `RUNDECK_USER_AGENT`: HTTP User-Agent
108
+
109
+ Available resources
110
+ -------------------
111
+ - `projects` (`ProjectManager`): CRUD projects, job export/import, project config, archive (export/import).
112
+ - `jobs` (`JobManager`): list, get, deletions, bulk actions, execution.
113
+ - `executions` (`ExecutionManager`): list/filter, running, get/delete, advanced query.
114
+ - `tokens` (`TokenManager`): list, get, create, delete.
115
+ - `users` (`UserManager`): user operations (per current implementation).
116
+ - `metrics` (`MetricsManager`): `/metrics` endpoints (list/data/healthcheck/ping).
117
+ - `plugins` (`PluginManager`): list installed plugins (`/plugin/list`).
118
+ - `webhooks` (`WebhookEventManager` + `ProjectWebhookManager`): project webhook management and sending via token.
119
+ - `key_storage` (`StorageKeyManager`): key storage management `/storage/keys`.
120
+ - `adhoc` (`AdhocManager`, via `project.adhoc`): run AdHoc commands/scripts.
121
+ - `system` (`SystemManager`): system info, executions enable/disable, logstorage, ACL.
122
+ - `config_management` (`ConfigManagementManager`): global configuration `/config`.
123
+ - `scm` (via `project.scm` and `job.scm`): import/export plugins, setup, enable/disable, status, actions (commit/import/export...).
124
+
125
+ Examples by resource (complete)
126
+ -------------------------------
127
+ Projects
121
128
  ```python
122
- # CRUD projet
129
+ # CRUD project
123
130
  p = rd.projects.create("demo")
124
131
  p = rd.projects.get("demo")
125
132
  rd.projects.delete("demo")
126
133
  projects = rd.projects.list()
127
134
 
128
- # Export / import de jobs d'un projet (via le manager de jobs)
135
+ # Export / import jobs from a project (via job manager)
129
136
  project.jobs.export(format="json", idlist="id1,id2", groupPath="group/sub")
130
137
  project.jobs.import_jobs(content=open("jobs.json").read(), format="json", dupeOption="update", uuidOption="remove")
131
138
 
132
- # Export / import du projet (archive ZIP)
139
+ # Project export / import (ZIP archive)
133
140
  archive = project.archive
134
- resp = archive.export(export_all=False, export_webhooks=True) # Response brute (zip)
141
+ resp = archive.export(export_all=False, export_webhooks=True) # Raw response (zip)
135
142
  token_info = archive.export_async(exportAll=True)
136
143
  status = archive.export_status(token_info.get("token", ""))
137
144
  zip_resp = archive.export_download(token_info.get("token", ""))
138
145
 
139
- # Import d'archive (synchrone ou async)
146
+ # Archive import (sync or async)
140
147
  archive.import_archive(
141
148
  content=open("project-export.zip", "rb").read(),
142
149
  jobUuidOption="preserve",
@@ -146,16 +153,16 @@ archive.import_archive(
146
153
  archive.import_archive(content=open("project-export.zip", "rb").read(), async_import=True)
147
154
  archive.import_status()
148
155
 
149
- # Readme / MOTD du projet
150
- project.readme.get_readme() # texte par défaut
156
+ # Project README / MOTD
157
+ project.readme.get_readme() # default text
151
158
  project.readme.get_readme(accept="application/json")
152
- project.readme.update_readme("Nouveau contenu", content_type="text/plain")
159
+ project.readme.update_readme("New content", content_type="text/plain")
153
160
  project.readme.delete_readme()
154
161
  project.readme.get_motd()
155
- project.readme.update_motd("Message du jour", content_type="text/plain")
162
+ project.readme.update_motd("Message of the day", content_type="text/plain")
156
163
  project.readme.delete_motd()
157
164
 
158
- # Config projet (clé/valeur)
165
+ # Project config (key/value)
159
166
  conf = p.config.get()
160
167
  p.config.keys.get("project.label")
161
168
  p.config.keys.set("project.label", "Demo")
@@ -163,27 +170,27 @@ p.config.keys.update({"project.description": "Sample"})
163
170
  p.config.replace({"project.label": "Demo", "project.description": "Sample"})
164
171
  p.config.keys.delete("project.label")
165
172
 
166
- # SCM import/export (sur un projet)
167
- scm_import = project.scm.import_ # ou getattr(project.scm, "import")
173
+ # SCM import/export (on a project)
174
+ scm_import = project.scm.import_ # or getattr(project.scm, "import")
168
175
  scm_export = project.scm.export
169
176
 
170
- # Découverte des plugins
177
+ # Plugin discovery
171
178
  scm_import.plugins.list()
172
179
  scm_export.plugins.list()
173
180
 
174
- # Champs d'entrée pour un plugin et setup (plugin_type explicite)
181
+ # Input fields for a plugin and setup (explicit plugin_type)
175
182
  fields = scm_import.plugins.input_fields("git-import")
176
183
  scm_import.config.setup("git-import", {"url": "ssh://git@example.com/repo.git", "dir": "/tmp/repo"})
177
184
 
178
- # Activer/désactiver un plugin
185
+ # Enable/disable a plugin
179
186
  scm_import.config.enable("git-import")
180
187
  scm_export.config.disable("custom-export")
181
188
 
182
- # Statut/config SCM
189
+ # SCM status/config
183
190
  import_status = scm_import.actions.status()
184
191
  export_conf = scm_export.config.get()
185
192
 
186
- # Actions SCM côté projet (ex: commit/pull/push selon plugin)
193
+ # Project-side SCM actions (e.g., commit/pull/push depending on plugin)
187
194
  action_fields = scm_export.actions.input_fields("commit")
188
195
  scm_export.actions.perform(
189
196
  "commit",
@@ -196,14 +203,14 @@ scm_export.actions.perform(
196
203
 
197
204
  Jobs
198
205
  ```python
199
- # Lister les jobs d’un projet
206
+ # List jobs for a project
200
207
  jobs = rd.jobs.list(project="demo", groupPath="ops")
201
208
 
202
- # Depuis un projet parenté
209
+ # From a parent project
203
210
  project = rd.projects.get("demo")
204
211
  jobs = project.jobs.list()
205
212
 
206
- # Accès direct à un job
213
+ # Direct access to a job
207
214
  job = rd.jobs.get("job-id")
208
215
  job.delete()
209
216
  job.definition(format="yaml")
@@ -218,7 +225,7 @@ tags = job.tags()
218
225
  workflow = job.workflow()
219
226
  forecast = job.forecast(time="2024-05-01T10:00:00Z", max=5)
220
227
 
221
- # Exporter/importer des jobs via le manager (paramètre project ou parent)
228
+ # Export/import jobs via manager (project parameter or parent)
222
229
  rd.jobs.export(project="demo", format="xml", idlist="id1,id2", groupPath="group")
223
230
  rd.jobs.import_jobs(
224
231
  project="demo",
@@ -226,30 +233,30 @@ rd.jobs.import_jobs(
226
233
  fileformat="xml",
227
234
  dupeOption="update",
228
235
  )
229
- # Ou via un projet parenté
236
+ # Or via a parent project
230
237
  project.jobs.export(format="json")
231
238
  project.jobs.import_jobs(content=open("jobs.json", "rb").read(), fileformat="json")
232
239
 
233
- Note: l'import reste exposé sous le nom `import_jobs(...)` (le mot-clé Python empêche un appel direct à `.import`). Si vous préférez l'alias, utilisez `getattr(rd.jobs, "import")(...)`.
240
+ Note: import remains exposed as `import_jobs(...)` (the Python keyword prevents a direct call to `.import`). If you prefer the alias, use `getattr(rd.jobs, "import")(...)`.
234
241
 
235
- # Exécuter et récupérer l'exécution
242
+ # Run and get the execution
236
243
  execution = job.run(argString="-option value")
237
244
 
238
- # Actions bulk
245
+ # Bulk actions
239
246
  rd.jobs.bulk.enable_execution(["id1", "id2"])
240
247
  rd.jobs.bulk.disable_execution(["id1", "id2"])
241
248
  rd.jobs.bulk.delete(["id1", "id2"])
242
249
  rd.jobs.bulk.enable_schedule(["id1", "id2"])
243
250
  rd.jobs.bulk.disable_schedule(["id1", "id2"])
244
251
 
245
- # Upload de fichiers d'option et fichiers uploadés
252
+ # Upload option files and uploaded files
246
253
  job.upload_option_file("csvfile", open("data.csv", "rb").read(), file_name="data.csv")
247
254
  job.list_uploaded_files(max=20)
248
255
  rd.jobs.get_uploaded_file_info("file-id")
249
256
 
250
- # SCM import/export sur un job
257
+ # SCM import/export on a job
251
258
  job_scm_export = job.scm.export
252
- job_scm_import = job.scm.import_ # ou getattr(job.scm, "import")
259
+ job_scm_import = job.scm.import_ # or getattr(job.scm, "import")
253
260
 
254
261
  job_scm_export.status()
255
262
  job_scm_export.diff()
@@ -259,7 +266,7 @@ job_scm_import.status()
259
266
  job_scm_import.input_fields("pull")
260
267
  job_scm_import.perform("pull", input_values={"message": "Update from repo"})
261
268
 
262
- # Ressources d'un projet
269
+ # Project resources
263
270
  resources = project.resources.list(format="json", groupPath="ops")
264
271
  node = project.resources.get("node1")
265
272
  sources = project.sources.list()
@@ -273,18 +280,18 @@ project.acl.update("policy.aclpolicy", content="...yaml...")
273
280
  project.acl.delete("policy.aclpolicy")
274
281
  ```
275
282
 
276
- Exécutions
283
+ Executions
277
284
  ```python
278
- # Liste simple ou paginée
285
+ # Simple or paginated list
279
286
  execs = rd.executions.list(project="demo", status="running", max=50, offset=0)
280
- running = rd.executions.running(project="demo") # ou "*" pour tous
287
+ running = rd.executions.running(project="demo") # or "*" for all
281
288
 
282
- # Détails / suppression
289
+ # Details / deletion
283
290
  e = rd.executions.get("123")
284
291
  rd.executions.delete("123")
285
292
  rd.executions.bulk_delete(["123", "124"])
286
293
 
287
- # Requête avancée (query)
294
+ # Advanced query
288
295
  advanced = rd.executions.query(
289
296
  project="demo",
290
297
  statusFilter="failed",
@@ -294,12 +301,12 @@ advanced = rd.executions.query(
294
301
  max=100,
295
302
  )
296
303
 
297
- # Méthodes sur Execution
304
+ # Execution methods
298
305
  e.abort(asUser="admin")
299
306
  output = e.get_output(offset=0, maxlines=100)
300
307
  state = e.get_state()
301
308
  is_running = e.is_running()
302
- e.refresh() # recharge les données
309
+ e.refresh() # reload data
303
310
  ```
304
311
 
305
312
  Tokens
@@ -311,20 +318,20 @@ new_token = rd.tokens.create(user="alice", roles=["admin"], duration="90d", name
311
318
  rd.tokens.delete(new_token.id)
312
319
  ```
313
320
 
314
- Utilisateurs
321
+ Users
315
322
  ```python
316
323
  users = rd.users.list()
317
324
  me = rd.users.get_current()
318
325
  u = rd.users.get("bob")
319
326
  roles = rd.users.current_roles()
320
327
 
321
- # Mise à jour via manager ou objet
328
+ # Update via manager or object
322
329
  u = rd.users.update("bob", firstName="Bob", lastName="Builder", email="bob@example.com")
323
- u.roles() # via l'objet
324
- u.update(email="new@example.com") # met à jour et rafraîchit l'objet
330
+ u.roles() # via the object
331
+ u.update(email="new@example.com") # updates and refreshes the object
325
332
  ```
326
333
 
327
- Système
334
+ System
328
335
  ```python
329
336
  system = rd.system
330
337
  info = system.info()
@@ -334,7 +341,7 @@ system.logstorage.info()
334
341
  system.logstorage.incomplete(max=50, offset=0)
335
342
  system.logstorage.incomplete_resume()
336
343
 
337
- # Mode exécution (sous-manager)
344
+ # Execution mode (sub-manager)
338
345
  system.executions.enable()
339
346
  system.executions.disable()
340
347
  system.executions.status()
@@ -351,7 +358,7 @@ rd.scheduler.takeover(all_servers=True)
351
358
  rd.scheduler.takeover(server_uuid="uuid-123", project="demo", job_id="job-1")
352
359
  ```
353
360
 
354
- Métriques
361
+ Metrics
355
362
  ```python
356
363
  metrics = rd.metrics
357
364
  metrics.list()
@@ -359,16 +366,16 @@ metrics.data()
359
366
  metrics.healthcheck()
360
367
  metrics.ping()
361
368
 
362
- # Plugins installés
369
+ # Installed plugins
363
370
  plugins = rd.plugins.list()
364
371
  for plugin in plugins:
365
372
  print(plugin.name, plugin.service)
366
373
 
367
- # Détail d'un plugin
374
+ # Plugin details
368
375
  first = plugins[0]
369
376
  detail = rd.plugins.detail(first.service, first.name)
370
377
 
371
- # Webhooks projet et envoi
378
+ # Project webhooks and send
372
379
  project = rd.projects.get("demo")
373
380
  wh = project.webhooks
374
381
  wh.create(
@@ -388,9 +395,9 @@ wh.delete(first_hook.id)
388
395
 
389
396
  # Key storage (/storage/keys)
390
397
  ks = rd.key_storage
391
- # Créer un secret (password)
398
+ # Create a secret (password)
392
399
  ks.create("integration/secret1", content="s3cr3t", content_type="application/x-rundeck-data-password")
393
- resources = ks.list() # liste racine
400
+ resources = ks.list() # root listing
394
401
  meta = ks.get_metadata("integration/secret1")
395
402
  ks.delete("integration/secret1")
396
403
 
@@ -398,17 +405,17 @@ ks.delete("integration/secret1")
398
405
  project = rd.projects.get("demo")
399
406
  exec1 = project.adhoc.run_command("echo 'hello world'")
400
407
  exec2 = project.adhoc.run_script("echo 'from script'")
401
- # exec2.id pour suivre l'exécution
402
- # Mode stub (sans refresh immédiat) puis refresh manuel
408
+ # exec2.id to track execution
409
+ # Stub mode (no immediate refresh) then manual refresh
403
410
  exec_stub = project.adhoc.run_command("echo stub", refresh=False)
404
- exec_stub.refresh() # charge l'objet complet
411
+ exec_stub.refresh() # load the full object
405
412
  # Script via multipart (upload)
406
413
  exec3 = project.adhoc.run_script(
407
414
  script_file=("hello.sh", "echo multipart", "text/plain"),
408
415
  refresh=False,
409
416
  )
410
417
 
411
- # Features système
418
+ # System features
412
419
  features = rd.features.list()
413
420
  if features:
414
421
  first = features[0]
@@ -416,7 +423,7 @@ if features:
416
423
  print(first.name, status.enabled)
417
424
  ```
418
425
 
419
- Configuration globale `/config`
426
+ Global configuration `/config`
420
427
  ```python
421
428
  cfg = rd.config_management
422
429
  all_configs = cfg.list()
@@ -428,27 +435,28 @@ cfg.restart()
428
435
 
429
436
  Pagination
430
437
  ----------
431
- Les managers héritent de `RundeckObjectManager.iter(...)` (offset/max). Exemple :
438
+ Managers inherit `RundeckObjectManager.iter(...)` (offset/max). Example:
432
439
  ```python
433
440
  for job in rd.jobs.iter(project="demo", page_size=100):
434
441
  print(job.id)
435
442
  ```
436
443
 
437
- Gestion des erreurs
438
- -------------------
439
- Les erreurs HTTP passent par `raise_for_status` et lèvent des exceptions dédiées (ex. `RundeckAuthenticationError`, `RundeckNotFoundError`, `RundeckValidationError`, `RundeckConflictError`, `RundeckServerError`). Gérez-les avec un bloc `try/except` autour des appels client.
440
-
441
- Développement et tests
442
- ----------------------
443
- - Formatage/Lint : `black src/rundeck tests/`, `ruff check src/rundeck tests/`
444
- - Typage : `mypy src/rundeck/`
445
- - Tests : `pytest`
446
- - Tests d'intégration locaux : `scripts/run-integration.sh` (démarre docker compose à la racine, exporte par défaut `RUNDECK_URL=http://localhost:4440`, `RUNDECK_TOKEN=adminToken`, `RUNDECK_API_VERSION=56`, attend le healthcheck, lance `poetry run pytest -m integration`). Vous pouvez surcharger les variables d'environnement avant l'appel. Ajoutez `KEEP_STACK=1` pour ne pas arrêter l'instance après les tests. Script de teardown dédié : `scripts/stop-integration.sh`.
447
-
448
- Structure du code
449
- -----------------
450
- - `src/rundeck/base.py` : objets/manager génériques, helpers `_build_path`, pagination, CRUD.
451
- - `src/rundeck/client.py` : client HTTP, méthodes `http_get/post/put/delete/list`.
452
- - `src/rundeck/v1/objects/` : managers et objets métiers (projects, jobs, executions, system, tokens, users, config_management).
453
- - Schéma managers/objets : on applique le pattern manager → objet partout où l’API expose une ressource identifiable (jobs, projects, users, tokens, executions, etc.). Pour les endpoints purement globaux ou utilitaires sans ressource (ex. `/system` et ses sous-domaines, `/config`, `/metrics`), on utilise des sous-managers dédiés plutôt que de forcer un objet artificiel.
444
+ Error handling
445
+ --------------
446
+ HTTP errors go through `raise_for_status` and raise dedicated exceptions (e.g., `RundeckAuthenticationError`, `RundeckNotFoundError`, `RundeckValidationError`, `RundeckConflictError`, `RundeckServerError`). Handle them with a `try/except` block around client calls.
447
+
448
+ Development and testing
449
+ -----------------------
450
+ - Development setup (contributors): clone the repo and run `poetry install`.
451
+ - Formatting/Lint: `black src/rundeck tests/`, `ruff check src/rundeck tests/`
452
+ - Typing: `mypy src/rundeck/`
453
+ - Tests: `pytest`
454
+ - Local integration tests: `scripts/run-integration.sh` (starts docker compose at repo root, exports by default `RUNDECK_URL=http://localhost:4440`, `RUNDECK_TOKEN=adminToken`, `RUNDECK_API_VERSION=56`, waits for the healthcheck, runs `poetry run pytest -m integration`). You can override env vars before running. Add `KEEP_STACK=1` to keep the instance running after tests. Dedicated teardown script: `scripts/stop-integration.sh`.
455
+
456
+ Code structure
457
+ --------------
458
+ - `src/rundeck/base.py`: generic objects/managers, `_build_path` helpers, pagination, CRUD.
459
+ - `src/rundeck/client.py`: HTTP client, `http_get/post/put/delete/list` methods.
460
+ - `src/rundeck/v1/objects/`: domain managers and objects (projects, jobs, executions, system, tokens, users, config_management).
461
+ - Managers/objects schema: we apply the manager -> object pattern wherever the API exposes an identifiable resource (jobs, projects, users, tokens, executions, etc.). For purely global or utility endpoints without a resource (e.g., `/system` and its subdomains, `/config`, `/metrics`), we use dedicated sub-managers rather than forcing an artificial object.
454
462
 
@@ -22,7 +22,7 @@ rundeck/v1/objects/system.py,sha256=wTfIxs4zINXxJF3zaEckB75sTFeeUq31O864y-B_pdo,
22
22
  rundeck/v1/objects/tokens.py,sha256=OWnfs1QUTpJbsaKf7r0Y7w3VYxxGZxBDead8JAoPKck,2373
23
23
  rundeck/v1/objects/users.py,sha256=N7WjC2UqXrmd0PurI317lua5wMSZN-C1YfdjjPWpqgA,3278
24
24
  rundeck/v1/objects/webhooks.py,sha256=F_HzNvlBRPvS_viu2reCRc7ECqRSUhp5RfD_G3r-ZZk,3358
25
- python_rundeck-0.1.0.dist-info/METADATA,sha256=S_LmnR9U55zEgsktZLy_h3QscV7-PwqTLJCUqMxEcF0,16088
26
- python_rundeck-0.1.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
27
- python_rundeck-0.1.0.dist-info/licenses/LICENSE,sha256=3X-BjvCzow8iLfLMykDaEAXjE9JvDrEHPkH9UK7MMMA,1073
28
- python_rundeck-0.1.0.dist-info/RECORD,,
25
+ python_rundeck-0.3.0.dist-info/METADATA,sha256=R2kNIAOkP26epzMRnUSZiRIwb7fvk4ayS0dmRwXM-Ug,16283
26
+ python_rundeck-0.3.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
27
+ python_rundeck-0.3.0.dist-info/licenses/LICENSE,sha256=3X-BjvCzow8iLfLMykDaEAXjE9JvDrEHPkH9UK7MMMA,1073
28
+ python_rundeck-0.3.0.dist-info/RECORD,,