python-rundeck 0.2.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.2.0.dist-info → python_rundeck-0.3.0.dist-info}/METADATA +130 -127
- {python_rundeck-0.2.0.dist-info → python_rundeck-0.3.0.dist-info}/RECORD +4 -4
- {python_rundeck-0.2.0.dist-info → python_rundeck-0.3.0.dist-info}/WHEEL +0 -0
- {python_rundeck-0.2.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
|
|
@@ -38,44 +38,46 @@ Description-Content-Type: text/markdown
|
|
|
38
38
|
|
|
39
39
|
python-rundeck
|
|
40
40
|
===============
|
|
41
|
+

|
|
42
|
+

|
|
43
|
+

|
|
44
|
+

|
|
41
45
|
|
|
42
|
-
|
|
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).
|
|
43
47
|
|
|
44
|
-
|
|
48
|
+
Contents
|
|
45
49
|
--------
|
|
46
50
|
- Installation
|
|
47
|
-
-
|
|
51
|
+
- Quick start
|
|
48
52
|
- Configuration
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
+
- Available resources
|
|
54
|
+
- Examples by resource
|
|
55
|
+
- Error handling
|
|
56
|
+
- Development and testing
|
|
53
57
|
|
|
54
58
|
Installation
|
|
55
59
|
------------
|
|
56
|
-
|
|
60
|
+
Prerequisites: Python 3.11+. Install from PyPI.
|
|
57
61
|
|
|
58
62
|
```bash
|
|
59
|
-
|
|
60
|
-
# ou en editable avec pip
|
|
61
|
-
pip install -e .
|
|
63
|
+
pip install python-rundeck
|
|
62
64
|
```
|
|
63
65
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
+
Quick start
|
|
67
|
+
-----------
|
|
66
68
|
```python
|
|
67
69
|
from rundeck.client import Rundeck
|
|
68
70
|
|
|
69
71
|
rd = Rundeck(url="https://rundeck.example.com", token="MY_TOKEN", api_version=56)
|
|
70
|
-
#
|
|
72
|
+
# Password auth (session cookie) if no token
|
|
71
73
|
rd = Rundeck(url="https://rundeck.example.com", username="admin", password="admin", api_version=56)
|
|
72
74
|
|
|
73
|
-
#
|
|
75
|
+
# List projects
|
|
74
76
|
projects = rd.projects.list()
|
|
75
77
|
for p in projects:
|
|
76
78
|
print(p.name)
|
|
77
79
|
|
|
78
|
-
#
|
|
80
|
+
# Get a project and run a job
|
|
79
81
|
project = rd.projects.get("demo")
|
|
80
82
|
jobs = project.jobs.list()
|
|
81
83
|
execu = jobs[0].run()
|
|
@@ -84,64 +86,64 @@ print(execu.id)
|
|
|
84
86
|
|
|
85
87
|
Configuration
|
|
86
88
|
-------------
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
- `url
|
|
91
|
-
- `token
|
|
92
|
-
- `username` / `password
|
|
93
|
-
- `api_version
|
|
94
|
-
- `timeout
|
|
95
|
-
- `ssl_verify
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
- `RUNDECK_URL
|
|
100
|
-
- `RUNDECK_TOKEN
|
|
101
|
-
- `RUNDECK_USERNAME` / `RUNDECK_PASSWORD
|
|
102
|
-
- `RUNDECK_API_VERSION
|
|
103
|
-
- `RUNDECK_TIMEOUT
|
|
104
|
-
- `RUNDECK_SSL_VERIFY
|
|
105
|
-
- `RUNDECK_USER_AGENT
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
- `projects` (`ProjectManager`)
|
|
110
|
-
- `jobs` (`JobManager`)
|
|
111
|
-
- `executions` (`ExecutionManager`)
|
|
112
|
-
- `tokens` (`TokenManager`)
|
|
113
|
-
- `users` (`UserManager`)
|
|
114
|
-
- `metrics` (`MetricsManager`)
|
|
115
|
-
- `plugins` (`PluginManager`)
|
|
116
|
-
- `webhooks` (`WebhookEventManager` + `ProjectWebhookManager`)
|
|
117
|
-
- `key_storage` (`StorageKeyManager`)
|
|
118
|
-
- `adhoc` (`AdhocManager`, via `project.adhoc`)
|
|
119
|
-
- `system` (`SystemManager`)
|
|
120
|
-
- `config_management` (`ConfigManagementManager`)
|
|
121
|
-
- `scm` (via `project.scm`
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
|
126
128
|
```python
|
|
127
|
-
# CRUD
|
|
129
|
+
# CRUD project
|
|
128
130
|
p = rd.projects.create("demo")
|
|
129
131
|
p = rd.projects.get("demo")
|
|
130
132
|
rd.projects.delete("demo")
|
|
131
133
|
projects = rd.projects.list()
|
|
132
134
|
|
|
133
|
-
# Export / import
|
|
135
|
+
# Export / import jobs from a project (via job manager)
|
|
134
136
|
project.jobs.export(format="json", idlist="id1,id2", groupPath="group/sub")
|
|
135
137
|
project.jobs.import_jobs(content=open("jobs.json").read(), format="json", dupeOption="update", uuidOption="remove")
|
|
136
138
|
|
|
137
|
-
#
|
|
139
|
+
# Project export / import (ZIP archive)
|
|
138
140
|
archive = project.archive
|
|
139
|
-
resp = archive.export(export_all=False, export_webhooks=True) #
|
|
141
|
+
resp = archive.export(export_all=False, export_webhooks=True) # Raw response (zip)
|
|
140
142
|
token_info = archive.export_async(exportAll=True)
|
|
141
143
|
status = archive.export_status(token_info.get("token", ""))
|
|
142
144
|
zip_resp = archive.export_download(token_info.get("token", ""))
|
|
143
145
|
|
|
144
|
-
#
|
|
146
|
+
# Archive import (sync or async)
|
|
145
147
|
archive.import_archive(
|
|
146
148
|
content=open("project-export.zip", "rb").read(),
|
|
147
149
|
jobUuidOption="preserve",
|
|
@@ -151,16 +153,16 @@ archive.import_archive(
|
|
|
151
153
|
archive.import_archive(content=open("project-export.zip", "rb").read(), async_import=True)
|
|
152
154
|
archive.import_status()
|
|
153
155
|
|
|
154
|
-
#
|
|
155
|
-
project.readme.get_readme() #
|
|
156
|
+
# Project README / MOTD
|
|
157
|
+
project.readme.get_readme() # default text
|
|
156
158
|
project.readme.get_readme(accept="application/json")
|
|
157
|
-
project.readme.update_readme("
|
|
159
|
+
project.readme.update_readme("New content", content_type="text/plain")
|
|
158
160
|
project.readme.delete_readme()
|
|
159
161
|
project.readme.get_motd()
|
|
160
|
-
project.readme.update_motd("Message
|
|
162
|
+
project.readme.update_motd("Message of the day", content_type="text/plain")
|
|
161
163
|
project.readme.delete_motd()
|
|
162
164
|
|
|
163
|
-
#
|
|
165
|
+
# Project config (key/value)
|
|
164
166
|
conf = p.config.get()
|
|
165
167
|
p.config.keys.get("project.label")
|
|
166
168
|
p.config.keys.set("project.label", "Demo")
|
|
@@ -168,27 +170,27 @@ p.config.keys.update({"project.description": "Sample"})
|
|
|
168
170
|
p.config.replace({"project.label": "Demo", "project.description": "Sample"})
|
|
169
171
|
p.config.keys.delete("project.label")
|
|
170
172
|
|
|
171
|
-
# SCM import/export (
|
|
172
|
-
scm_import = project.scm.import_ #
|
|
173
|
+
# SCM import/export (on a project)
|
|
174
|
+
scm_import = project.scm.import_ # or getattr(project.scm, "import")
|
|
173
175
|
scm_export = project.scm.export
|
|
174
176
|
|
|
175
|
-
#
|
|
177
|
+
# Plugin discovery
|
|
176
178
|
scm_import.plugins.list()
|
|
177
179
|
scm_export.plugins.list()
|
|
178
180
|
|
|
179
|
-
#
|
|
181
|
+
# Input fields for a plugin and setup (explicit plugin_type)
|
|
180
182
|
fields = scm_import.plugins.input_fields("git-import")
|
|
181
183
|
scm_import.config.setup("git-import", {"url": "ssh://git@example.com/repo.git", "dir": "/tmp/repo"})
|
|
182
184
|
|
|
183
|
-
#
|
|
185
|
+
# Enable/disable a plugin
|
|
184
186
|
scm_import.config.enable("git-import")
|
|
185
187
|
scm_export.config.disable("custom-export")
|
|
186
188
|
|
|
187
|
-
#
|
|
189
|
+
# SCM status/config
|
|
188
190
|
import_status = scm_import.actions.status()
|
|
189
191
|
export_conf = scm_export.config.get()
|
|
190
192
|
|
|
191
|
-
#
|
|
193
|
+
# Project-side SCM actions (e.g., commit/pull/push depending on plugin)
|
|
192
194
|
action_fields = scm_export.actions.input_fields("commit")
|
|
193
195
|
scm_export.actions.perform(
|
|
194
196
|
"commit",
|
|
@@ -201,14 +203,14 @@ scm_export.actions.perform(
|
|
|
201
203
|
|
|
202
204
|
Jobs
|
|
203
205
|
```python
|
|
204
|
-
#
|
|
206
|
+
# List jobs for a project
|
|
205
207
|
jobs = rd.jobs.list(project="demo", groupPath="ops")
|
|
206
208
|
|
|
207
|
-
#
|
|
209
|
+
# From a parent project
|
|
208
210
|
project = rd.projects.get("demo")
|
|
209
211
|
jobs = project.jobs.list()
|
|
210
212
|
|
|
211
|
-
#
|
|
213
|
+
# Direct access to a job
|
|
212
214
|
job = rd.jobs.get("job-id")
|
|
213
215
|
job.delete()
|
|
214
216
|
job.definition(format="yaml")
|
|
@@ -223,7 +225,7 @@ tags = job.tags()
|
|
|
223
225
|
workflow = job.workflow()
|
|
224
226
|
forecast = job.forecast(time="2024-05-01T10:00:00Z", max=5)
|
|
225
227
|
|
|
226
|
-
#
|
|
228
|
+
# Export/import jobs via manager (project parameter or parent)
|
|
227
229
|
rd.jobs.export(project="demo", format="xml", idlist="id1,id2", groupPath="group")
|
|
228
230
|
rd.jobs.import_jobs(
|
|
229
231
|
project="demo",
|
|
@@ -231,30 +233,30 @@ rd.jobs.import_jobs(
|
|
|
231
233
|
fileformat="xml",
|
|
232
234
|
dupeOption="update",
|
|
233
235
|
)
|
|
234
|
-
#
|
|
236
|
+
# Or via a parent project
|
|
235
237
|
project.jobs.export(format="json")
|
|
236
238
|
project.jobs.import_jobs(content=open("jobs.json", "rb").read(), fileformat="json")
|
|
237
239
|
|
|
238
|
-
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")(...)`.
|
|
239
241
|
|
|
240
|
-
#
|
|
242
|
+
# Run and get the execution
|
|
241
243
|
execution = job.run(argString="-option value")
|
|
242
244
|
|
|
243
|
-
#
|
|
245
|
+
# Bulk actions
|
|
244
246
|
rd.jobs.bulk.enable_execution(["id1", "id2"])
|
|
245
247
|
rd.jobs.bulk.disable_execution(["id1", "id2"])
|
|
246
248
|
rd.jobs.bulk.delete(["id1", "id2"])
|
|
247
249
|
rd.jobs.bulk.enable_schedule(["id1", "id2"])
|
|
248
250
|
rd.jobs.bulk.disable_schedule(["id1", "id2"])
|
|
249
251
|
|
|
250
|
-
# Upload
|
|
252
|
+
# Upload option files and uploaded files
|
|
251
253
|
job.upload_option_file("csvfile", open("data.csv", "rb").read(), file_name="data.csv")
|
|
252
254
|
job.list_uploaded_files(max=20)
|
|
253
255
|
rd.jobs.get_uploaded_file_info("file-id")
|
|
254
256
|
|
|
255
|
-
# SCM import/export
|
|
257
|
+
# SCM import/export on a job
|
|
256
258
|
job_scm_export = job.scm.export
|
|
257
|
-
job_scm_import = job.scm.import_ #
|
|
259
|
+
job_scm_import = job.scm.import_ # or getattr(job.scm, "import")
|
|
258
260
|
|
|
259
261
|
job_scm_export.status()
|
|
260
262
|
job_scm_export.diff()
|
|
@@ -264,7 +266,7 @@ job_scm_import.status()
|
|
|
264
266
|
job_scm_import.input_fields("pull")
|
|
265
267
|
job_scm_import.perform("pull", input_values={"message": "Update from repo"})
|
|
266
268
|
|
|
267
|
-
#
|
|
269
|
+
# Project resources
|
|
268
270
|
resources = project.resources.list(format="json", groupPath="ops")
|
|
269
271
|
node = project.resources.get("node1")
|
|
270
272
|
sources = project.sources.list()
|
|
@@ -278,18 +280,18 @@ project.acl.update("policy.aclpolicy", content="...yaml...")
|
|
|
278
280
|
project.acl.delete("policy.aclpolicy")
|
|
279
281
|
```
|
|
280
282
|
|
|
281
|
-
|
|
283
|
+
Executions
|
|
282
284
|
```python
|
|
283
|
-
#
|
|
285
|
+
# Simple or paginated list
|
|
284
286
|
execs = rd.executions.list(project="demo", status="running", max=50, offset=0)
|
|
285
|
-
running = rd.executions.running(project="demo") #
|
|
287
|
+
running = rd.executions.running(project="demo") # or "*" for all
|
|
286
288
|
|
|
287
|
-
#
|
|
289
|
+
# Details / deletion
|
|
288
290
|
e = rd.executions.get("123")
|
|
289
291
|
rd.executions.delete("123")
|
|
290
292
|
rd.executions.bulk_delete(["123", "124"])
|
|
291
293
|
|
|
292
|
-
#
|
|
294
|
+
# Advanced query
|
|
293
295
|
advanced = rd.executions.query(
|
|
294
296
|
project="demo",
|
|
295
297
|
statusFilter="failed",
|
|
@@ -299,12 +301,12 @@ advanced = rd.executions.query(
|
|
|
299
301
|
max=100,
|
|
300
302
|
)
|
|
301
303
|
|
|
302
|
-
#
|
|
304
|
+
# Execution methods
|
|
303
305
|
e.abort(asUser="admin")
|
|
304
306
|
output = e.get_output(offset=0, maxlines=100)
|
|
305
307
|
state = e.get_state()
|
|
306
308
|
is_running = e.is_running()
|
|
307
|
-
e.refresh() #
|
|
309
|
+
e.refresh() # reload data
|
|
308
310
|
```
|
|
309
311
|
|
|
310
312
|
Tokens
|
|
@@ -316,20 +318,20 @@ new_token = rd.tokens.create(user="alice", roles=["admin"], duration="90d", name
|
|
|
316
318
|
rd.tokens.delete(new_token.id)
|
|
317
319
|
```
|
|
318
320
|
|
|
319
|
-
|
|
321
|
+
Users
|
|
320
322
|
```python
|
|
321
323
|
users = rd.users.list()
|
|
322
324
|
me = rd.users.get_current()
|
|
323
325
|
u = rd.users.get("bob")
|
|
324
326
|
roles = rd.users.current_roles()
|
|
325
327
|
|
|
326
|
-
#
|
|
328
|
+
# Update via manager or object
|
|
327
329
|
u = rd.users.update("bob", firstName="Bob", lastName="Builder", email="bob@example.com")
|
|
328
|
-
u.roles() # via
|
|
329
|
-
u.update(email="new@example.com") #
|
|
330
|
+
u.roles() # via the object
|
|
331
|
+
u.update(email="new@example.com") # updates and refreshes the object
|
|
330
332
|
```
|
|
331
333
|
|
|
332
|
-
|
|
334
|
+
System
|
|
333
335
|
```python
|
|
334
336
|
system = rd.system
|
|
335
337
|
info = system.info()
|
|
@@ -339,7 +341,7 @@ system.logstorage.info()
|
|
|
339
341
|
system.logstorage.incomplete(max=50, offset=0)
|
|
340
342
|
system.logstorage.incomplete_resume()
|
|
341
343
|
|
|
342
|
-
#
|
|
344
|
+
# Execution mode (sub-manager)
|
|
343
345
|
system.executions.enable()
|
|
344
346
|
system.executions.disable()
|
|
345
347
|
system.executions.status()
|
|
@@ -356,7 +358,7 @@ rd.scheduler.takeover(all_servers=True)
|
|
|
356
358
|
rd.scheduler.takeover(server_uuid="uuid-123", project="demo", job_id="job-1")
|
|
357
359
|
```
|
|
358
360
|
|
|
359
|
-
|
|
361
|
+
Metrics
|
|
360
362
|
```python
|
|
361
363
|
metrics = rd.metrics
|
|
362
364
|
metrics.list()
|
|
@@ -364,16 +366,16 @@ metrics.data()
|
|
|
364
366
|
metrics.healthcheck()
|
|
365
367
|
metrics.ping()
|
|
366
368
|
|
|
367
|
-
#
|
|
369
|
+
# Installed plugins
|
|
368
370
|
plugins = rd.plugins.list()
|
|
369
371
|
for plugin in plugins:
|
|
370
372
|
print(plugin.name, plugin.service)
|
|
371
373
|
|
|
372
|
-
#
|
|
374
|
+
# Plugin details
|
|
373
375
|
first = plugins[0]
|
|
374
376
|
detail = rd.plugins.detail(first.service, first.name)
|
|
375
377
|
|
|
376
|
-
#
|
|
378
|
+
# Project webhooks and send
|
|
377
379
|
project = rd.projects.get("demo")
|
|
378
380
|
wh = project.webhooks
|
|
379
381
|
wh.create(
|
|
@@ -393,9 +395,9 @@ wh.delete(first_hook.id)
|
|
|
393
395
|
|
|
394
396
|
# Key storage (/storage/keys)
|
|
395
397
|
ks = rd.key_storage
|
|
396
|
-
#
|
|
398
|
+
# Create a secret (password)
|
|
397
399
|
ks.create("integration/secret1", content="s3cr3t", content_type="application/x-rundeck-data-password")
|
|
398
|
-
resources = ks.list() #
|
|
400
|
+
resources = ks.list() # root listing
|
|
399
401
|
meta = ks.get_metadata("integration/secret1")
|
|
400
402
|
ks.delete("integration/secret1")
|
|
401
403
|
|
|
@@ -403,17 +405,17 @@ ks.delete("integration/secret1")
|
|
|
403
405
|
project = rd.projects.get("demo")
|
|
404
406
|
exec1 = project.adhoc.run_command("echo 'hello world'")
|
|
405
407
|
exec2 = project.adhoc.run_script("echo 'from script'")
|
|
406
|
-
# exec2.id
|
|
407
|
-
#
|
|
408
|
+
# exec2.id to track execution
|
|
409
|
+
# Stub mode (no immediate refresh) then manual refresh
|
|
408
410
|
exec_stub = project.adhoc.run_command("echo stub", refresh=False)
|
|
409
|
-
exec_stub.refresh() #
|
|
411
|
+
exec_stub.refresh() # load the full object
|
|
410
412
|
# Script via multipart (upload)
|
|
411
413
|
exec3 = project.adhoc.run_script(
|
|
412
414
|
script_file=("hello.sh", "echo multipart", "text/plain"),
|
|
413
415
|
refresh=False,
|
|
414
416
|
)
|
|
415
417
|
|
|
416
|
-
#
|
|
418
|
+
# System features
|
|
417
419
|
features = rd.features.list()
|
|
418
420
|
if features:
|
|
419
421
|
first = features[0]
|
|
@@ -421,7 +423,7 @@ if features:
|
|
|
421
423
|
print(first.name, status.enabled)
|
|
422
424
|
```
|
|
423
425
|
|
|
424
|
-
|
|
426
|
+
Global configuration `/config`
|
|
425
427
|
```python
|
|
426
428
|
cfg = rd.config_management
|
|
427
429
|
all_configs = cfg.list()
|
|
@@ -433,27 +435,28 @@ cfg.restart()
|
|
|
433
435
|
|
|
434
436
|
Pagination
|
|
435
437
|
----------
|
|
436
|
-
|
|
438
|
+
Managers inherit `RundeckObjectManager.iter(...)` (offset/max). Example:
|
|
437
439
|
```python
|
|
438
440
|
for job in rd.jobs.iter(project="demo", page_size=100):
|
|
439
441
|
print(job.id)
|
|
440
442
|
```
|
|
441
443
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
-
|
|
449
|
-
-
|
|
450
|
-
-
|
|
451
|
-
- Tests
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
- `src/rundeck/
|
|
457
|
-
- `src/rundeck/
|
|
458
|
-
-
|
|
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.
|
|
459
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
|