python-rundeck 1.0.1__tar.gz → 2.0.0__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.
- {python_rundeck-1.0.1 → python_rundeck-2.0.0}/PKG-INFO +63 -24
- {python_rundeck-1.0.1 → python_rundeck-2.0.0}/README.md +61 -22
- {python_rundeck-1.0.1 → python_rundeck-2.0.0}/pyproject.toml +2 -2
- {python_rundeck-1.0.1 → python_rundeck-2.0.0}/src/rundeck/client.py +20 -12
- {python_rundeck-1.0.1 → python_rundeck-2.0.0}/src/rundeck/config.py +2 -1
- python_rundeck-2.0.0/src/rundeck/const.py +69 -0
- {python_rundeck-1.0.1 → python_rundeck-2.0.0}/src/rundeck/exceptions.py +1 -1
- python_rundeck-2.0.0/src/rundeck/utils.py +35 -0
- python_rundeck-2.0.0/src/rundeck/v1/objects/acl.py +24 -0
- {python_rundeck-1.0.1 → python_rundeck-2.0.0}/src/rundeck/v1/objects/adhoc.py +3 -20
- python_rundeck-2.0.0/src/rundeck/v1/objects/authorizations.py +45 -0
- python_rundeck-2.0.0/src/rundeck/v1/objects/executions.py +449 -0
- {python_rundeck-1.0.1 → python_rundeck-2.0.0}/src/rundeck/v1/objects/jobs.py +129 -47
- {python_rundeck-1.0.1 → python_rundeck-2.0.0}/src/rundeck/v1/objects/key_storage.py +10 -3
- python_rundeck-2.0.0/src/rundeck/v1/objects/metrics.py +81 -0
- python_rundeck-2.0.0/src/rundeck/v1/objects/project_plugins.py +29 -0
- {python_rundeck-1.0.1 → python_rundeck-2.0.0}/src/rundeck/v1/objects/projects.py +163 -74
- python_rundeck-2.0.0/src/rundeck/v1/objects/scheduler.py +67 -0
- {python_rundeck-1.0.1 → python_rundeck-2.0.0}/src/rundeck/v1/objects/scm.py +5 -0
- {python_rundeck-1.0.1 → python_rundeck-2.0.0}/src/rundeck/v1/objects/system.py +11 -6
- {python_rundeck-1.0.1 → python_rundeck-2.0.0}/src/rundeck/v1/objects/tokens.py +4 -0
- {python_rundeck-1.0.1 → python_rundeck-2.0.0}/src/rundeck/v1/objects/users.py +33 -16
- python_rundeck-1.0.1/src/rundeck/const.py +0 -45
- python_rundeck-1.0.1/src/rundeck/v1/objects/config_management.py +0 -51
- python_rundeck-1.0.1/src/rundeck/v1/objects/executions.py +0 -326
- python_rundeck-1.0.1/src/rundeck/v1/objects/metrics.py +0 -37
- python_rundeck-1.0.1/src/rundeck/v1/objects/scheduler.py +0 -50
- {python_rundeck-1.0.1 → python_rundeck-2.0.0}/LICENSE +0 -0
- {python_rundeck-1.0.1 → python_rundeck-2.0.0}/src/rundeck/__init__.py +0 -0
- {python_rundeck-1.0.1 → python_rundeck-2.0.0}/src/rundeck/base.py +0 -0
- {python_rundeck-1.0.1 → python_rundeck-2.0.0}/src/rundeck/py.typed +0 -0
- {python_rundeck-1.0.1 → python_rundeck-2.0.0}/src/rundeck/v1/__init__.py +0 -0
- {python_rundeck-1.0.1 → python_rundeck-2.0.0}/src/rundeck/v1/objects/__init__.py +0 -0
- {python_rundeck-1.0.1 → python_rundeck-2.0.0}/src/rundeck/v1/objects/features.py +0 -0
- {python_rundeck-1.0.1 → python_rundeck-2.0.0}/src/rundeck/v1/objects/plugins.py +0 -0
- {python_rundeck-1.0.1 → python_rundeck-2.0.0}/src/rundeck/v1/objects/webhooks.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-rundeck
|
|
3
|
-
Version:
|
|
4
|
-
Summary: Python client for the Rundeck API (v14-
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Summary: Python client for the Rundeck Community API (v14-v59).
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
License-File: LICENSE
|
|
7
7
|
Keywords: rundeck,api,client
|
|
@@ -43,7 +43,9 @@ python-rundeck
|
|
|
43
43
|

|
|
44
44
|

|
|
45
45
|
|
|
46
|
-
Python client for the Rundeck API (v14-
|
|
46
|
+
Python client for the Rundeck Community API (v14-v59), inspired by the python-gitlab architecture. The default API version is v59; current Rundeck servers require v17 or later and versions below v34 are deprecated. Provides typed managers for Community resources (projects, jobs, executions, tokens, users, system) and SCM (import/export).
|
|
47
|
+
|
|
48
|
+
Version 2.0 removes commercial-only Config Management and job-tag endpoints. Cluster schedule listing and takeover are Community operations and remain available. The authorization-evaluation endpoints are experimental in Rundeck and are exposed as such by this client.
|
|
47
49
|
|
|
48
50
|
Contents
|
|
49
51
|
--------
|
|
@@ -69,9 +71,9 @@ Quick start
|
|
|
69
71
|
```python
|
|
70
72
|
from rundeck.client import Rundeck
|
|
71
73
|
|
|
72
|
-
rd = Rundeck(url="https://rundeck.example.com", token="MY_TOKEN"
|
|
74
|
+
rd = Rundeck(url="https://rundeck.example.com", token="MY_TOKEN")
|
|
73
75
|
# Password auth (session cookie) if no token
|
|
74
|
-
rd = Rundeck(url="https://rundeck.example.com", username="admin", password="admin"
|
|
76
|
+
rd = Rundeck(url="https://rundeck.example.com", username="admin", password="admin")
|
|
75
77
|
|
|
76
78
|
# List projects
|
|
77
79
|
projects = rd.projects.list()
|
|
@@ -94,20 +96,24 @@ Main parameters:
|
|
|
94
96
|
- `url`: Rundeck URL (e.g. `https://rundeck.example.com`)
|
|
95
97
|
- `token`: API token (header `X-Rundeck-Auth-Token`)
|
|
96
98
|
- `username` / `password`: Session authentication (j_security_check) if no token is provided.
|
|
97
|
-
- `api_version`: API version (
|
|
99
|
+
- `api_version`: API version (default: `59`; older versions can be selected explicitly)
|
|
98
100
|
- `timeout`: Request timeout (float, seconds)
|
|
99
101
|
- `ssl_verify`: TLS verification (bool or CA path)
|
|
102
|
+
- `user_agent`: Custom HTTP User-Agent (string)
|
|
103
|
+
- `config_section`: Section name in config files (default: `rundeck`)
|
|
100
104
|
|
|
101
105
|
Config files: if needed, pass `config_files` or `Rundeck.from_config(config_section=...)`.
|
|
102
106
|
Useful env vars (client config):
|
|
103
107
|
- `RUNDECK_URL`: Base URL
|
|
104
108
|
- `RUNDECK_TOKEN`: API token (header `X-Rundeck-Auth-Token`)
|
|
105
109
|
- `RUNDECK_USERNAME` / `RUNDECK_PASSWORD`: Session auth (if no token)
|
|
106
|
-
- `RUNDECK_API_VERSION`: API version (
|
|
110
|
+
- `RUNDECK_API_VERSION`: API version (default `59`; older server versions can be selected explicitly)
|
|
107
111
|
- `RUNDECK_TIMEOUT`: Request timeout (seconds)
|
|
108
112
|
- `RUNDECK_SSL_VERIFY`: TLS verification (bool or CA path)
|
|
109
113
|
- `RUNDECK_USER_AGENT`: HTTP User-Agent
|
|
110
114
|
|
|
115
|
+
Rundeck 6.0+ accepts JSON for REST requests and responses. XML/YAML remain supported only as job, archive, and resource document formats.
|
|
116
|
+
|
|
111
117
|
Available resources
|
|
112
118
|
-------------------
|
|
113
119
|
- `projects` (`ProjectManager`): CRUD projects, job export/import, project config, archive (export/import).
|
|
@@ -115,13 +121,15 @@ Available resources
|
|
|
115
121
|
- `executions` (`ExecutionManager`): list/filter, running, get/delete, advanced query.
|
|
116
122
|
- `tokens` (`TokenManager`): list, get, create, delete.
|
|
117
123
|
- `users` (`UserManager`): user operations (per current implementation).
|
|
118
|
-
- `metrics` (`MetricsManager`): `/metrics` endpoints (list/data/healthcheck/ping).
|
|
124
|
+
- `metrics` (`MetricsManager`): legacy `/api/V/metrics` endpoints (list/data/healthcheck/ping/threads).
|
|
125
|
+
- `monitoring` (`MonitoringManager`): modern non-versioned `/monitoring/*` endpoints (Prometheus, metrics, health, readiness, info, thread dump).
|
|
126
|
+
- `authorizations` (`AuthorizationsManager`): experimental authorization evaluation endpoints.
|
|
119
127
|
- `plugins` (`PluginManager`): list installed plugins (`/plugin/list`).
|
|
120
128
|
- `webhooks` (`WebhookEventManager` + `ProjectWebhookManager`): project webhook management and sending via token.
|
|
121
129
|
- `key_storage` (`StorageKeyManager`): key storage management `/storage/keys`.
|
|
122
130
|
- `adhoc` (`AdhocManager`, via `project.adhoc`): run AdHoc commands/scripts.
|
|
123
|
-
- `system` (`SystemManager`): system info, executions enable/disable, logstorage, ACL.
|
|
124
|
-
- `
|
|
131
|
+
- `system` (`SystemManager`): system info and summary, executions enable/disable, logstorage, ACL.
|
|
132
|
+
- `scheduler` (`SchedulerManager`): scheduled job listing and cluster schedule takeover (Community).
|
|
125
133
|
- `scm` (via `project.scm` and `job.scm`): import/export plugins, setup, enable/disable, status, actions (commit/import/export...).
|
|
126
134
|
|
|
127
135
|
Return types policy
|
|
@@ -130,7 +138,7 @@ Return types policy
|
|
|
130
138
|
- Factory managers return the created resource object for actions that create it
|
|
131
139
|
(e.g., `project.adhoc` returns `Execution`).
|
|
132
140
|
- Utility managers return raw API responses (dict/str/bytes).
|
|
133
|
-
- `delete(...)` returns `None
|
|
141
|
+
- CRUD `delete(...)` returns `None`; action endpoints returning a result body return that raw result.
|
|
134
142
|
- Object methods return raw API responses and update the object in place when needed.
|
|
135
143
|
- Explicit flags are used when an object return is requested (e.g., `as_execution=True`).
|
|
136
144
|
|
|
@@ -142,7 +150,7 @@ Factory managers:
|
|
|
142
150
|
Returns `Execution` objects (execution factory).
|
|
143
151
|
|
|
144
152
|
Utility managers:
|
|
145
|
-
- `system`, `
|
|
153
|
+
- `system`, `metrics`, `scheduler`, `webhooks` (event send), `authorizations` (experimental).
|
|
146
154
|
- `scm` (via `project.scm` and `job.scm`), and project sub-managers like
|
|
147
155
|
`project.config`, `project.resources`, `project.sources`, `project.readme`,
|
|
148
156
|
`project.archive`, `project.acl`.
|
|
@@ -150,6 +158,13 @@ Utility managers:
|
|
|
150
158
|
Note: `project.webhooks.create(...)` returns the raw API response (e.g., `{"msg": "Saved webhook"}`)
|
|
151
159
|
because the Rundeck API does not return the created webhook object.
|
|
152
160
|
|
|
161
|
+
Migration from 1.1.0
|
|
162
|
+
-------------------
|
|
163
|
+
- Set `api_version=59` explicitly when upgrading a server/client pair gradually; the default is now 59.
|
|
164
|
+
- Remove calls to `rd.config_management` and `job.tags()`: their endpoints are only available in commercial Rundeck products.
|
|
165
|
+
- `rd.scheduler.takeover()` and scheduler job listing remain supported by Community. On a non-cluster server, takeover returns a successful response indicating that no action was performed.
|
|
166
|
+
- `rd.authorizations` wraps experimental endpoints and can change with Rundeck releases.
|
|
167
|
+
|
|
153
168
|
Example:
|
|
154
169
|
```python
|
|
155
170
|
job = rd.jobs.get("job-id") # -> Job (object)
|
|
@@ -257,9 +272,11 @@ job.enable_schedule()
|
|
|
257
272
|
job.disable_schedule()
|
|
258
273
|
info = job.info()
|
|
259
274
|
meta = job.meta(meta="name,description")
|
|
260
|
-
|
|
275
|
+
meta = job.meta(meta="*", meta_exclude="stats") # API v58+
|
|
261
276
|
workflow = job.workflow()
|
|
262
|
-
forecast = job.forecast(time="2024-05-01T10:00:00Z", max=5)
|
|
277
|
+
forecast = job.forecast(time="2024-05-01T10:00:00Z", max=5, past=False)
|
|
278
|
+
executions = job.executions(include_job_ref=True)
|
|
279
|
+
deleted = job.delete_executions()
|
|
263
280
|
|
|
264
281
|
# Export/import jobs via manager (project parameter or parent)
|
|
265
282
|
rd.jobs.export(project="demo", format="xml", idlist="id1,id2", groupPath="group")
|
|
@@ -460,14 +477,35 @@ if features:
|
|
|
460
477
|
print(first.name, status.enabled)
|
|
461
478
|
```
|
|
462
479
|
|
|
463
|
-
|
|
480
|
+
Monitoring
|
|
481
|
+
----------
|
|
482
|
+
```python
|
|
483
|
+
# Rundeck 6.0+ modern endpoints, outside /api/V.
|
|
484
|
+
health = rd.monitoring.health()
|
|
485
|
+
prometheus_text = rd.monitoring.prometheus()
|
|
486
|
+
metric = rd.monitoring.metric("jvm.memory.used", tags=["area:heap"])
|
|
487
|
+
thread_dump = rd.monitoring.thread_dump()
|
|
488
|
+
|
|
489
|
+
# Legacy metrics require rundeck.metrics.legacy.enabled=true on Rundeck 6.0.
|
|
490
|
+
legacy_threads = rd.metrics.threads()
|
|
491
|
+
ready = rd.monitoring.readiness()
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
Community additions
|
|
495
|
+
-------------------
|
|
464
496
|
```python
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
497
|
+
api_info = rd.api_info()
|
|
498
|
+
summary = rd.system.summary()
|
|
499
|
+
scheduled_jobs = rd.scheduler.jobs()
|
|
500
|
+
rd.tokens.remove_expired("admin") # use "*" with suitable administrator rights
|
|
501
|
+
|
|
502
|
+
project = rd.projects.get("demo")
|
|
503
|
+
project.plugins.save("ResourceModelSource", "resources.source", plugins=[])
|
|
504
|
+
project.archive.export_async(execution_ids=["1", "2"], use_post=True)
|
|
505
|
+
project.jobs.validate_option(option_data, job_was_scheduled=False)
|
|
506
|
+
|
|
507
|
+
# Experimental authorization API; actions are repeated query parameters.
|
|
508
|
+
permissions = rd.authorizations.application_kind("job", ["read", "run"])
|
|
471
509
|
```
|
|
472
510
|
|
|
473
511
|
Pagination
|
|
@@ -488,12 +526,13 @@ Development and testing
|
|
|
488
526
|
- Formatting/Lint: `black src/rundeck tests/`, `ruff check src/rundeck tests/`
|
|
489
527
|
- Typing: `mypy src/rundeck/`
|
|
490
528
|
- Tests: `pytest`
|
|
491
|
-
- Local integration tests: `scripts/run-integration.sh`
|
|
529
|
+
- Local integration tests: `scripts/run-integration.sh` starts Rundeck Community 6.2.1 by default with API v59. Use `RUNDECK_IMAGE=rundeck/rundeck:6.0.1 RUNDECK_API_VERSION=58` or `RUNDECK_IMAGE=rundeck/rundeck:5.18.0 RUNDECK_API_VERSION=56` for compatibility runs. Add `KEEP_STACK=1` to keep the instance running after tests. Dedicated teardown script: `scripts/stop-integration.sh`.
|
|
530
|
+
- The docker compose stack mounts `tokens.properties` at the repo root to seed a local admin token for integration tests. This file is only intended for local testing.
|
|
492
531
|
|
|
493
532
|
Code structure
|
|
494
533
|
--------------
|
|
495
534
|
- `src/rundeck/base.py`: generic objects/managers, `_build_path` helpers, pagination, CRUD.
|
|
496
535
|
- `src/rundeck/client.py`: HTTP client, `http_get/post/put/delete/list` methods.
|
|
497
|
-
- `src/rundeck/v1/objects/`: domain managers and objects (projects, jobs, executions, system, tokens, users,
|
|
498
|
-
- Managers/objects schema: we apply the manager -> object pattern wherever the API exposes an identifiable resource (jobs, projects, users, tokens, executions, etc.). For
|
|
536
|
+
- `src/rundeck/v1/objects/`: Community domain managers and objects (projects, jobs, executions, system, tokens, users, authorizations).
|
|
537
|
+
- Managers/objects schema: we apply the manager -> object pattern wherever the API exposes an identifiable resource (jobs, projects, users, tokens, executions, etc.). For global or utility endpoints without a resource (e.g., `/system`, `/scheduler`, `/metrics`), we use dedicated sub-managers rather than forcing an artificial object.
|
|
499
538
|
|
|
@@ -5,7 +5,9 @@ python-rundeck
|
|
|
5
5
|

|
|
6
6
|

|
|
7
7
|
|
|
8
|
-
Python client for the Rundeck API (v14-
|
|
8
|
+
Python client for the Rundeck Community API (v14-v59), inspired by the python-gitlab architecture. The default API version is v59; current Rundeck servers require v17 or later and versions below v34 are deprecated. Provides typed managers for Community resources (projects, jobs, executions, tokens, users, system) and SCM (import/export).
|
|
9
|
+
|
|
10
|
+
Version 2.0 removes commercial-only Config Management and job-tag endpoints. Cluster schedule listing and takeover are Community operations and remain available. The authorization-evaluation endpoints are experimental in Rundeck and are exposed as such by this client.
|
|
9
11
|
|
|
10
12
|
Contents
|
|
11
13
|
--------
|
|
@@ -31,9 +33,9 @@ Quick start
|
|
|
31
33
|
```python
|
|
32
34
|
from rundeck.client import Rundeck
|
|
33
35
|
|
|
34
|
-
rd = Rundeck(url="https://rundeck.example.com", token="MY_TOKEN"
|
|
36
|
+
rd = Rundeck(url="https://rundeck.example.com", token="MY_TOKEN")
|
|
35
37
|
# Password auth (session cookie) if no token
|
|
36
|
-
rd = Rundeck(url="https://rundeck.example.com", username="admin", password="admin"
|
|
38
|
+
rd = Rundeck(url="https://rundeck.example.com", username="admin", password="admin")
|
|
37
39
|
|
|
38
40
|
# List projects
|
|
39
41
|
projects = rd.projects.list()
|
|
@@ -56,20 +58,24 @@ Main parameters:
|
|
|
56
58
|
- `url`: Rundeck URL (e.g. `https://rundeck.example.com`)
|
|
57
59
|
- `token`: API token (header `X-Rundeck-Auth-Token`)
|
|
58
60
|
- `username` / `password`: Session authentication (j_security_check) if no token is provided.
|
|
59
|
-
- `api_version`: API version (
|
|
61
|
+
- `api_version`: API version (default: `59`; older versions can be selected explicitly)
|
|
60
62
|
- `timeout`: Request timeout (float, seconds)
|
|
61
63
|
- `ssl_verify`: TLS verification (bool or CA path)
|
|
64
|
+
- `user_agent`: Custom HTTP User-Agent (string)
|
|
65
|
+
- `config_section`: Section name in config files (default: `rundeck`)
|
|
62
66
|
|
|
63
67
|
Config files: if needed, pass `config_files` or `Rundeck.from_config(config_section=...)`.
|
|
64
68
|
Useful env vars (client config):
|
|
65
69
|
- `RUNDECK_URL`: Base URL
|
|
66
70
|
- `RUNDECK_TOKEN`: API token (header `X-Rundeck-Auth-Token`)
|
|
67
71
|
- `RUNDECK_USERNAME` / `RUNDECK_PASSWORD`: Session auth (if no token)
|
|
68
|
-
- `RUNDECK_API_VERSION`: API version (
|
|
72
|
+
- `RUNDECK_API_VERSION`: API version (default `59`; older server versions can be selected explicitly)
|
|
69
73
|
- `RUNDECK_TIMEOUT`: Request timeout (seconds)
|
|
70
74
|
- `RUNDECK_SSL_VERIFY`: TLS verification (bool or CA path)
|
|
71
75
|
- `RUNDECK_USER_AGENT`: HTTP User-Agent
|
|
72
76
|
|
|
77
|
+
Rundeck 6.0+ accepts JSON for REST requests and responses. XML/YAML remain supported only as job, archive, and resource document formats.
|
|
78
|
+
|
|
73
79
|
Available resources
|
|
74
80
|
-------------------
|
|
75
81
|
- `projects` (`ProjectManager`): CRUD projects, job export/import, project config, archive (export/import).
|
|
@@ -77,13 +83,15 @@ Available resources
|
|
|
77
83
|
- `executions` (`ExecutionManager`): list/filter, running, get/delete, advanced query.
|
|
78
84
|
- `tokens` (`TokenManager`): list, get, create, delete.
|
|
79
85
|
- `users` (`UserManager`): user operations (per current implementation).
|
|
80
|
-
- `metrics` (`MetricsManager`): `/metrics` endpoints (list/data/healthcheck/ping).
|
|
86
|
+
- `metrics` (`MetricsManager`): legacy `/api/V/metrics` endpoints (list/data/healthcheck/ping/threads).
|
|
87
|
+
- `monitoring` (`MonitoringManager`): modern non-versioned `/monitoring/*` endpoints (Prometheus, metrics, health, readiness, info, thread dump).
|
|
88
|
+
- `authorizations` (`AuthorizationsManager`): experimental authorization evaluation endpoints.
|
|
81
89
|
- `plugins` (`PluginManager`): list installed plugins (`/plugin/list`).
|
|
82
90
|
- `webhooks` (`WebhookEventManager` + `ProjectWebhookManager`): project webhook management and sending via token.
|
|
83
91
|
- `key_storage` (`StorageKeyManager`): key storage management `/storage/keys`.
|
|
84
92
|
- `adhoc` (`AdhocManager`, via `project.adhoc`): run AdHoc commands/scripts.
|
|
85
|
-
- `system` (`SystemManager`): system info, executions enable/disable, logstorage, ACL.
|
|
86
|
-
- `
|
|
93
|
+
- `system` (`SystemManager`): system info and summary, executions enable/disable, logstorage, ACL.
|
|
94
|
+
- `scheduler` (`SchedulerManager`): scheduled job listing and cluster schedule takeover (Community).
|
|
87
95
|
- `scm` (via `project.scm` and `job.scm`): import/export plugins, setup, enable/disable, status, actions (commit/import/export...).
|
|
88
96
|
|
|
89
97
|
Return types policy
|
|
@@ -92,7 +100,7 @@ Return types policy
|
|
|
92
100
|
- Factory managers return the created resource object for actions that create it
|
|
93
101
|
(e.g., `project.adhoc` returns `Execution`).
|
|
94
102
|
- Utility managers return raw API responses (dict/str/bytes).
|
|
95
|
-
- `delete(...)` returns `None
|
|
103
|
+
- CRUD `delete(...)` returns `None`; action endpoints returning a result body return that raw result.
|
|
96
104
|
- Object methods return raw API responses and update the object in place when needed.
|
|
97
105
|
- Explicit flags are used when an object return is requested (e.g., `as_execution=True`).
|
|
98
106
|
|
|
@@ -104,7 +112,7 @@ Factory managers:
|
|
|
104
112
|
Returns `Execution` objects (execution factory).
|
|
105
113
|
|
|
106
114
|
Utility managers:
|
|
107
|
-
- `system`, `
|
|
115
|
+
- `system`, `metrics`, `scheduler`, `webhooks` (event send), `authorizations` (experimental).
|
|
108
116
|
- `scm` (via `project.scm` and `job.scm`), and project sub-managers like
|
|
109
117
|
`project.config`, `project.resources`, `project.sources`, `project.readme`,
|
|
110
118
|
`project.archive`, `project.acl`.
|
|
@@ -112,6 +120,13 @@ Utility managers:
|
|
|
112
120
|
Note: `project.webhooks.create(...)` returns the raw API response (e.g., `{"msg": "Saved webhook"}`)
|
|
113
121
|
because the Rundeck API does not return the created webhook object.
|
|
114
122
|
|
|
123
|
+
Migration from 1.1.0
|
|
124
|
+
-------------------
|
|
125
|
+
- Set `api_version=59` explicitly when upgrading a server/client pair gradually; the default is now 59.
|
|
126
|
+
- Remove calls to `rd.config_management` and `job.tags()`: their endpoints are only available in commercial Rundeck products.
|
|
127
|
+
- `rd.scheduler.takeover()` and scheduler job listing remain supported by Community. On a non-cluster server, takeover returns a successful response indicating that no action was performed.
|
|
128
|
+
- `rd.authorizations` wraps experimental endpoints and can change with Rundeck releases.
|
|
129
|
+
|
|
115
130
|
Example:
|
|
116
131
|
```python
|
|
117
132
|
job = rd.jobs.get("job-id") # -> Job (object)
|
|
@@ -219,9 +234,11 @@ job.enable_schedule()
|
|
|
219
234
|
job.disable_schedule()
|
|
220
235
|
info = job.info()
|
|
221
236
|
meta = job.meta(meta="name,description")
|
|
222
|
-
|
|
237
|
+
meta = job.meta(meta="*", meta_exclude="stats") # API v58+
|
|
223
238
|
workflow = job.workflow()
|
|
224
|
-
forecast = job.forecast(time="2024-05-01T10:00:00Z", max=5)
|
|
239
|
+
forecast = job.forecast(time="2024-05-01T10:00:00Z", max=5, past=False)
|
|
240
|
+
executions = job.executions(include_job_ref=True)
|
|
241
|
+
deleted = job.delete_executions()
|
|
225
242
|
|
|
226
243
|
# Export/import jobs via manager (project parameter or parent)
|
|
227
244
|
rd.jobs.export(project="demo", format="xml", idlist="id1,id2", groupPath="group")
|
|
@@ -422,14 +439,35 @@ if features:
|
|
|
422
439
|
print(first.name, status.enabled)
|
|
423
440
|
```
|
|
424
441
|
|
|
425
|
-
|
|
442
|
+
Monitoring
|
|
443
|
+
----------
|
|
444
|
+
```python
|
|
445
|
+
# Rundeck 6.0+ modern endpoints, outside /api/V.
|
|
446
|
+
health = rd.monitoring.health()
|
|
447
|
+
prometheus_text = rd.monitoring.prometheus()
|
|
448
|
+
metric = rd.monitoring.metric("jvm.memory.used", tags=["area:heap"])
|
|
449
|
+
thread_dump = rd.monitoring.thread_dump()
|
|
450
|
+
|
|
451
|
+
# Legacy metrics require rundeck.metrics.legacy.enabled=true on Rundeck 6.0.
|
|
452
|
+
legacy_threads = rd.metrics.threads()
|
|
453
|
+
ready = rd.monitoring.readiness()
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
Community additions
|
|
457
|
+
-------------------
|
|
426
458
|
```python
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
459
|
+
api_info = rd.api_info()
|
|
460
|
+
summary = rd.system.summary()
|
|
461
|
+
scheduled_jobs = rd.scheduler.jobs()
|
|
462
|
+
rd.tokens.remove_expired("admin") # use "*" with suitable administrator rights
|
|
463
|
+
|
|
464
|
+
project = rd.projects.get("demo")
|
|
465
|
+
project.plugins.save("ResourceModelSource", "resources.source", plugins=[])
|
|
466
|
+
project.archive.export_async(execution_ids=["1", "2"], use_post=True)
|
|
467
|
+
project.jobs.validate_option(option_data, job_was_scheduled=False)
|
|
468
|
+
|
|
469
|
+
# Experimental authorization API; actions are repeated query parameters.
|
|
470
|
+
permissions = rd.authorizations.application_kind("job", ["read", "run"])
|
|
433
471
|
```
|
|
434
472
|
|
|
435
473
|
Pagination
|
|
@@ -450,11 +488,12 @@ Development and testing
|
|
|
450
488
|
- Formatting/Lint: `black src/rundeck tests/`, `ruff check src/rundeck tests/`
|
|
451
489
|
- Typing: `mypy src/rundeck/`
|
|
452
490
|
- Tests: `pytest`
|
|
453
|
-
- Local integration tests: `scripts/run-integration.sh`
|
|
491
|
+
- Local integration tests: `scripts/run-integration.sh` starts Rundeck Community 6.2.1 by default with API v59. Use `RUNDECK_IMAGE=rundeck/rundeck:6.0.1 RUNDECK_API_VERSION=58` or `RUNDECK_IMAGE=rundeck/rundeck:5.18.0 RUNDECK_API_VERSION=56` for compatibility runs. Add `KEEP_STACK=1` to keep the instance running after tests. Dedicated teardown script: `scripts/stop-integration.sh`.
|
|
492
|
+
- The docker compose stack mounts `tokens.properties` at the repo root to seed a local admin token for integration tests. This file is only intended for local testing.
|
|
454
493
|
|
|
455
494
|
Code structure
|
|
456
495
|
--------------
|
|
457
496
|
- `src/rundeck/base.py`: generic objects/managers, `_build_path` helpers, pagination, CRUD.
|
|
458
497
|
- `src/rundeck/client.py`: HTTP client, `http_get/post/put/delete/list` methods.
|
|
459
|
-
- `src/rundeck/v1/objects/`: domain managers and objects (projects, jobs, executions, system, tokens, users,
|
|
460
|
-
- Managers/objects schema: we apply the manager -> object pattern wherever the API exposes an identifiable resource (jobs, projects, users, tokens, executions, etc.). For
|
|
498
|
+
- `src/rundeck/v1/objects/`: Community domain managers and objects (projects, jobs, executions, system, tokens, users, authorizations).
|
|
499
|
+
- Managers/objects schema: we apply the manager -> object pattern wherever the API exposes an identifiable resource (jobs, projects, users, tokens, executions, etc.). For global or utility endpoints without a resource (e.g., `/system`, `/scheduler`, `/metrics`), we use dedicated sub-managers rather than forcing an artificial object.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "python-rundeck"
|
|
3
|
-
version = "
|
|
4
|
-
description = "Python client for the Rundeck API (v14-
|
|
3
|
+
version = "2.0.0"
|
|
4
|
+
description = "Python client for the Rundeck Community API (v14-v59)."
|
|
5
5
|
authors = [
|
|
6
6
|
{name = "Pascal Seckinger",email = "pascal.seckinger@protonmail.com"}
|
|
7
7
|
]
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
"""Client principal pour l'API Rundeck."""
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
Client principal pour l'API Rundeck
|
|
5
|
-
"""
|
|
3
|
+
from __future__ import annotations
|
|
6
4
|
|
|
7
5
|
from typing import Any
|
|
8
6
|
from urllib.parse import urljoin
|
|
@@ -37,8 +35,10 @@ class Rundeck:
|
|
|
37
35
|
api_version: int | None = None,
|
|
38
36
|
timeout: float | None = None,
|
|
39
37
|
ssl_verify: bool | None = None,
|
|
38
|
+
user_agent: str | None = None,
|
|
40
39
|
session: requests.Session | None = None,
|
|
41
40
|
config_files: list[str] | None = None,
|
|
41
|
+
config_section: str | None = None,
|
|
42
42
|
) -> None:
|
|
43
43
|
self.config = RundeckConfig(
|
|
44
44
|
url=url,
|
|
@@ -48,7 +48,9 @@ class Rundeck:
|
|
|
48
48
|
api_version=api_version,
|
|
49
49
|
timeout=timeout,
|
|
50
50
|
ssl_verify=ssl_verify,
|
|
51
|
+
user_agent=user_agent,
|
|
51
52
|
config_files=config_files,
|
|
53
|
+
config_section=config_section or "rundeck",
|
|
52
54
|
)
|
|
53
55
|
|
|
54
56
|
if not self.config.url:
|
|
@@ -79,12 +81,12 @@ class Rundeck:
|
|
|
79
81
|
def _init_managers(self) -> None:
|
|
80
82
|
"""Initialise les managers d'objets."""
|
|
81
83
|
# Import paresseux pour éviter les boucles d'import.
|
|
82
|
-
from rundeck.v1.objects.
|
|
84
|
+
from rundeck.v1.objects.authorizations import AuthorizationsManager
|
|
83
85
|
from rundeck.v1.objects.executions import ExecutionManager
|
|
84
86
|
from rundeck.v1.objects.features import FeatureManager
|
|
85
87
|
from rundeck.v1.objects.jobs import JobManager
|
|
86
88
|
from rundeck.v1.objects.key_storage import StorageKeyManager
|
|
87
|
-
from rundeck.v1.objects.metrics import MetricsManager
|
|
89
|
+
from rundeck.v1.objects.metrics import MetricsManager, MonitoringManager
|
|
88
90
|
from rundeck.v1.objects.plugins import PluginManager
|
|
89
91
|
from rundeck.v1.objects.projects import ProjectManager
|
|
90
92
|
from rundeck.v1.objects.scheduler import SchedulerManager
|
|
@@ -96,8 +98,9 @@ class Rundeck:
|
|
|
96
98
|
self.projects = ProjectManager(self)
|
|
97
99
|
self.jobs = JobManager(self)
|
|
98
100
|
self.executions = ExecutionManager(self)
|
|
99
|
-
self.
|
|
101
|
+
self.authorizations = AuthorizationsManager(self)
|
|
100
102
|
self.metrics = MetricsManager(self)
|
|
103
|
+
self.monitoring = MonitoringManager(self)
|
|
101
104
|
self.plugins = PluginManager(self)
|
|
102
105
|
self.webhooks = WebhookEventManager(self)
|
|
103
106
|
self.key_storage = StorageKeyManager(self)
|
|
@@ -107,6 +110,10 @@ class Rundeck:
|
|
|
107
110
|
self.tokens = TokenManager(self)
|
|
108
111
|
self.users = UserManager(self)
|
|
109
112
|
|
|
113
|
+
def api_info(self) -> dict[str, Any]:
|
|
114
|
+
"""Récupère les informations de l'API utilisée par ce client."""
|
|
115
|
+
return self.http_get("/")
|
|
116
|
+
|
|
110
117
|
@property
|
|
111
118
|
def url(self) -> str:
|
|
112
119
|
"""URL fournie par l'utilisateur."""
|
|
@@ -127,6 +134,7 @@ class Rundeck:
|
|
|
127
134
|
cls,
|
|
128
135
|
config_section: str | None = None,
|
|
129
136
|
config_files: list[str] | None = None,
|
|
137
|
+
user_agent: str | None = None,
|
|
130
138
|
**kwargs: Any,
|
|
131
139
|
) -> "Rundeck":
|
|
132
140
|
"""
|
|
@@ -144,8 +152,10 @@ class Rundeck:
|
|
|
144
152
|
api_version=conf.api_version,
|
|
145
153
|
timeout=conf.timeout,
|
|
146
154
|
ssl_verify=conf.ssl_verify,
|
|
155
|
+
user_agent=user_agent,
|
|
147
156
|
session=kwargs.get("session"),
|
|
148
157
|
config_files=config_files,
|
|
158
|
+
config_section=config_section,
|
|
149
159
|
)
|
|
150
160
|
|
|
151
161
|
def _authenticate_with_password(self) -> None:
|
|
@@ -265,14 +275,12 @@ class Rundeck:
|
|
|
265
275
|
if raw:
|
|
266
276
|
return response
|
|
267
277
|
|
|
268
|
-
if method == HTTP_DELETE:
|
|
269
|
-
return None
|
|
270
278
|
if response.text:
|
|
271
279
|
try:
|
|
272
280
|
return response.json()
|
|
273
281
|
except ValueError:
|
|
274
282
|
return response.text
|
|
275
|
-
return {}
|
|
283
|
+
return None if method == HTTP_DELETE else {}
|
|
276
284
|
|
|
277
285
|
def http_get(
|
|
278
286
|
self,
|
|
@@ -331,8 +339,8 @@ class Rundeck:
|
|
|
331
339
|
url: str,
|
|
332
340
|
raw: bool = False,
|
|
333
341
|
**kwargs: Any,
|
|
334
|
-
) ->
|
|
335
|
-
self._request(HTTP_DELETE, url, raw=raw, **kwargs)
|
|
342
|
+
) -> Any:
|
|
343
|
+
return self._request(HTTP_DELETE, url, raw=raw, **kwargs)
|
|
336
344
|
|
|
337
345
|
def __enter__(self) -> "Rundeck":
|
|
338
346
|
return self
|
|
@@ -63,6 +63,7 @@ class RundeckConfig:
|
|
|
63
63
|
api_version: int | str | None = None,
|
|
64
64
|
timeout: float | None = None,
|
|
65
65
|
ssl_verify: bool | str | None = None,
|
|
66
|
+
user_agent: str | None = None,
|
|
66
67
|
config_files: list[str] | None = None,
|
|
67
68
|
config_section: str = "rundeck",
|
|
68
69
|
) -> None:
|
|
@@ -103,7 +104,7 @@ class RundeckConfig:
|
|
|
103
104
|
else _coerce_ssl_verify(env_ssl_verify or file_conf.get("ssl_verify"))
|
|
104
105
|
)
|
|
105
106
|
self.user_agent: str = (
|
|
106
|
-
env_user_agent or file_conf.get("user_agent") or USER_AGENT
|
|
107
|
+
user_agent or env_user_agent or file_conf.get("user_agent") or USER_AGENT
|
|
107
108
|
)
|
|
108
109
|
self.config_files = files
|
|
109
110
|
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Constantes partagées pour le client Rundeck.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import tomllib
|
|
6
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# Package metadata
|
|
11
|
+
def _read_pyproject_version() -> str | None:
|
|
12
|
+
try:
|
|
13
|
+
root = Path(__file__).resolve().parents[2]
|
|
14
|
+
pyproject = root / "pyproject.toml"
|
|
15
|
+
if not pyproject.is_file():
|
|
16
|
+
return None
|
|
17
|
+
with pyproject.open("rb") as handle:
|
|
18
|
+
data = tomllib.load(handle)
|
|
19
|
+
return data.get("project", {}).get("version")
|
|
20
|
+
except Exception:
|
|
21
|
+
return None
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
__version__ = version("python-rundeck")
|
|
26
|
+
except PackageNotFoundError: # pragma: no cover - fallback for local dev
|
|
27
|
+
__version__ = _read_pyproject_version() or "0.0.0"
|
|
28
|
+
|
|
29
|
+
# Auth
|
|
30
|
+
RUNDECK_AUTH_HEADER = "X-Rundeck-Auth-Token"
|
|
31
|
+
|
|
32
|
+
# HTTP methods
|
|
33
|
+
HTTP_GET = "GET"
|
|
34
|
+
HTTP_POST = "POST"
|
|
35
|
+
HTTP_PUT = "PUT"
|
|
36
|
+
HTTP_DELETE = "DELETE"
|
|
37
|
+
|
|
38
|
+
# Content / formats
|
|
39
|
+
FORMAT_JSON = "json"
|
|
40
|
+
|
|
41
|
+
# API versions. The library remains compatible with legacy Rundeck servers
|
|
42
|
+
# using v14, while current Rundeck servers require at least v17.
|
|
43
|
+
API_VERSION_CURRENT = "59"
|
|
44
|
+
API_VERSION_MIN = "14"
|
|
45
|
+
API_VERSION_SERVER_MIN = "17"
|
|
46
|
+
API_VERSION_DEPRECATION = "34"
|
|
47
|
+
|
|
48
|
+
# Defaults
|
|
49
|
+
DEFAULT_API_VERSION = API_VERSION_CURRENT
|
|
50
|
+
DEFAULT_TIMEOUT = 30
|
|
51
|
+
USER_AGENT = "python-rundeck"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
__all__ = [
|
|
55
|
+
"__version__",
|
|
56
|
+
"API_VERSION_CURRENT",
|
|
57
|
+
"API_VERSION_DEPRECATION",
|
|
58
|
+
"API_VERSION_MIN",
|
|
59
|
+
"API_VERSION_SERVER_MIN",
|
|
60
|
+
"DEFAULT_API_VERSION",
|
|
61
|
+
"DEFAULT_TIMEOUT",
|
|
62
|
+
"FORMAT_JSON",
|
|
63
|
+
"HTTP_DELETE",
|
|
64
|
+
"HTTP_GET",
|
|
65
|
+
"HTTP_POST",
|
|
66
|
+
"HTTP_PUT",
|
|
67
|
+
"RUNDECK_AUTH_HEADER",
|
|
68
|
+
"USER_AGENT",
|
|
69
|
+
]
|
|
@@ -131,7 +131,7 @@ def raise_for_status(response: requests.Response) -> None:
|
|
|
131
131
|
raise RundeckAuthenticationError(message, error_code, response)
|
|
132
132
|
if code_lower == "api-version-unsupported":
|
|
133
133
|
raise RundeckApiVersionUnsupportedError(message, error_code, response)
|
|
134
|
-
if status
|
|
134
|
+
if status in (400, 422):
|
|
135
135
|
raise RundeckValidationError(message, error_code, response)
|
|
136
136
|
if status in (401, 403):
|
|
137
137
|
raise RundeckAuthenticationError(message, error_code, response)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any, Mapping
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def compact(*dicts: Mapping[str, Any], **kwargs: Any) -> dict[str, Any]:
|
|
7
|
+
"""
|
|
8
|
+
Supprime les entrées dont la valeur est None.
|
|
9
|
+
"""
|
|
10
|
+
result: dict[str, Any] = {}
|
|
11
|
+
for mapping in dicts:
|
|
12
|
+
if not mapping:
|
|
13
|
+
continue
|
|
14
|
+
for key, value in mapping.items():
|
|
15
|
+
if value is not None:
|
|
16
|
+
result[key] = value
|
|
17
|
+
for key, value in kwargs.items():
|
|
18
|
+
if value is not None:
|
|
19
|
+
result[key] = value
|
|
20
|
+
return result
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def build_headers(
|
|
24
|
+
accept: str | None = None,
|
|
25
|
+
content_type: str | None = None,
|
|
26
|
+
) -> dict[str, str] | None:
|
|
27
|
+
"""
|
|
28
|
+
Construit les en-têtes standards (Accept/Content-Type).
|
|
29
|
+
"""
|
|
30
|
+
headers: dict[str, str] = {}
|
|
31
|
+
if accept is not None:
|
|
32
|
+
headers["Accept"] = accept
|
|
33
|
+
if content_type is not None:
|
|
34
|
+
headers["Content-Type"] = content_type
|
|
35
|
+
return headers or None
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from rundeck.utils import build_headers
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class YamlPolicyMixin:
|
|
9
|
+
_yaml_content_type = "application/yaml"
|
|
10
|
+
|
|
11
|
+
def _yaml_headers(self) -> dict[str, str]:
|
|
12
|
+
headers = build_headers(
|
|
13
|
+
accept=self._yaml_content_type, content_type=self._yaml_content_type
|
|
14
|
+
)
|
|
15
|
+
return headers or {
|
|
16
|
+
"Accept": self._yaml_content_type,
|
|
17
|
+
"Content-Type": self._yaml_content_type,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
def _post_yaml(self, path: str, content: Any) -> Any:
|
|
21
|
+
return self.rd.http_post(path, data=content, headers=self._yaml_headers())
|
|
22
|
+
|
|
23
|
+
def _put_yaml(self, path: str, content: Any) -> Any:
|
|
24
|
+
return self.rd.http_put(path, data=content, headers=self._yaml_headers())
|