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.
- {python_rundeck-0.1.0.dist-info → python_rundeck-0.3.0.dist-info}/METADATA +135 -127
- {python_rundeck-0.1.0.dist-info → python_rundeck-0.3.0.dist-info}/RECORD +4 -4
- {python_rundeck-0.1.0.dist-info → python_rundeck-0.3.0.dist-info}/WHEEL +0 -0
- {python_rundeck-0.1.0.dist-info → python_rundeck-0.3.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-rundeck
|
|
3
|
-
Version: 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
|
+

|
|
42
|
+

|
|
43
|
+

|
|
44
|
+

|
|
36
45
|
|
|
37
|
-
|
|
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
|
-
|
|
48
|
+
Contents
|
|
40
49
|
--------
|
|
41
50
|
- Installation
|
|
42
|
-
-
|
|
51
|
+
- Quick start
|
|
43
52
|
- Configuration
|
|
44
|
-
-
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
53
|
+
- Available resources
|
|
54
|
+
- Examples by resource
|
|
55
|
+
- Error handling
|
|
56
|
+
- Development and testing
|
|
48
57
|
|
|
49
58
|
Installation
|
|
50
59
|
------------
|
|
51
|
-
|
|
60
|
+
Prerequisites: Python 3.11+. Install from PyPI.
|
|
52
61
|
|
|
53
62
|
```bash
|
|
54
|
-
|
|
55
|
-
# ou en editable avec pip
|
|
56
|
-
pip install -e .
|
|
63
|
+
pip install python-rundeck
|
|
57
64
|
```
|
|
58
65
|
|
|
59
|
-
|
|
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
|
-
#
|
|
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
|
-
#
|
|
75
|
+
# List projects
|
|
69
76
|
projects = rd.projects.list()
|
|
70
77
|
for p in projects:
|
|
71
78
|
print(p.name)
|
|
72
79
|
|
|
73
|
-
#
|
|
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
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
- `url
|
|
86
|
-
- `token
|
|
87
|
-
- `username` / `password
|
|
88
|
-
- `api_version
|
|
89
|
-
- `timeout
|
|
90
|
-
- `ssl_verify
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
- `RUNDECK_URL
|
|
95
|
-
- `RUNDECK_TOKEN
|
|
96
|
-
- `RUNDECK_USERNAME` / `RUNDECK_PASSWORD
|
|
97
|
-
- `RUNDECK_API_VERSION
|
|
98
|
-
- `RUNDECK_TIMEOUT
|
|
99
|
-
- `RUNDECK_SSL_VERIFY
|
|
100
|
-
- `RUNDECK_USER_AGENT
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
- `projects` (`ProjectManager`)
|
|
105
|
-
- `jobs` (`JobManager`)
|
|
106
|
-
- `executions` (`ExecutionManager`)
|
|
107
|
-
- `tokens` (`TokenManager`)
|
|
108
|
-
- `users` (`UserManager`)
|
|
109
|
-
- `metrics` (`MetricsManager`)
|
|
110
|
-
- `plugins` (`PluginManager`)
|
|
111
|
-
- `webhooks` (`WebhookEventManager` + `ProjectWebhookManager`)
|
|
112
|
-
- `key_storage` (`StorageKeyManager`)
|
|
113
|
-
- `adhoc` (`AdhocManager`, via `project.adhoc`)
|
|
114
|
-
- `system` (`SystemManager`)
|
|
115
|
-
- `config_management` (`ConfigManagementManager`)
|
|
116
|
-
- `scm` (via `project.scm`
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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
|
|
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
|
|
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
|
-
#
|
|
139
|
+
# Project export / import (ZIP archive)
|
|
133
140
|
archive = project.archive
|
|
134
|
-
resp = archive.export(export_all=False, export_webhooks=True) #
|
|
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
|
-
#
|
|
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
|
-
#
|
|
150
|
-
project.readme.get_readme() #
|
|
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("
|
|
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
|
|
162
|
+
project.readme.update_motd("Message of the day", content_type="text/plain")
|
|
156
163
|
project.readme.delete_motd()
|
|
157
164
|
|
|
158
|
-
#
|
|
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 (
|
|
167
|
-
scm_import = 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
|
-
#
|
|
177
|
+
# Plugin discovery
|
|
171
178
|
scm_import.plugins.list()
|
|
172
179
|
scm_export.plugins.list()
|
|
173
180
|
|
|
174
|
-
#
|
|
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
|
-
#
|
|
185
|
+
# Enable/disable a plugin
|
|
179
186
|
scm_import.config.enable("git-import")
|
|
180
187
|
scm_export.config.disable("custom-export")
|
|
181
188
|
|
|
182
|
-
#
|
|
189
|
+
# SCM status/config
|
|
183
190
|
import_status = scm_import.actions.status()
|
|
184
191
|
export_conf = scm_export.config.get()
|
|
185
192
|
|
|
186
|
-
#
|
|
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
|
-
#
|
|
206
|
+
# List jobs for a project
|
|
200
207
|
jobs = rd.jobs.list(project="demo", groupPath="ops")
|
|
201
208
|
|
|
202
|
-
#
|
|
209
|
+
# From a parent project
|
|
203
210
|
project = rd.projects.get("demo")
|
|
204
211
|
jobs = project.jobs.list()
|
|
205
212
|
|
|
206
|
-
#
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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:
|
|
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
|
-
#
|
|
242
|
+
# Run and get the execution
|
|
236
243
|
execution = job.run(argString="-option value")
|
|
237
244
|
|
|
238
|
-
#
|
|
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
|
|
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
|
|
257
|
+
# SCM import/export on a job
|
|
251
258
|
job_scm_export = job.scm.export
|
|
252
|
-
job_scm_import = 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
|
-
#
|
|
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
|
-
|
|
283
|
+
Executions
|
|
277
284
|
```python
|
|
278
|
-
#
|
|
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") #
|
|
287
|
+
running = rd.executions.running(project="demo") # or "*" for all
|
|
281
288
|
|
|
282
|
-
#
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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() #
|
|
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
|
-
|
|
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
|
-
#
|
|
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
|
|
324
|
-
u.update(email="new@example.com") #
|
|
330
|
+
u.roles() # via the object
|
|
331
|
+
u.update(email="new@example.com") # updates and refreshes the object
|
|
325
332
|
```
|
|
326
333
|
|
|
327
|
-
|
|
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
|
-
#
|
|
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
|
-
|
|
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
|
-
#
|
|
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
|
-
#
|
|
374
|
+
# Plugin details
|
|
368
375
|
first = plugins[0]
|
|
369
376
|
detail = rd.plugins.detail(first.service, first.name)
|
|
370
377
|
|
|
371
|
-
#
|
|
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
|
-
#
|
|
398
|
+
# Create a secret (password)
|
|
392
399
|
ks.create("integration/secret1", content="s3cr3t", content_type="application/x-rundeck-data-password")
|
|
393
|
-
resources = ks.list() #
|
|
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
|
|
402
|
-
#
|
|
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() #
|
|
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
|
-
#
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
-
|
|
444
|
-
-
|
|
445
|
-
-
|
|
446
|
-
- Tests
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
- `src/rundeck/
|
|
452
|
-
- `src/rundeck/
|
|
453
|
-
-
|
|
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.
|
|
26
|
-
python_rundeck-0.
|
|
27
|
-
python_rundeck-0.
|
|
28
|
-
python_rundeck-0.
|
|
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,,
|
|
File without changes
|
|
File without changes
|