python-jcli 1.0.0__py3-none-any.whl → 1.0.1__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.
Files changed (44) hide show
  1. jcli/__init__.py +1 -1
  2. jcli/cli.py +30 -10
  3. jcli/cli_helpers.py +5 -42
  4. jcli/skills/jcli/build/SKILL.md +123 -0
  5. jcli/specs/_auth.yaml +15 -0
  6. jcli/{plugins/skills.py → specs/plugins/jcli_commands.py} +64 -46
  7. jcli/specs/plugins/jenkins_auth.py +75 -0
  8. jcli/specs/plugins/jenkins_methods.py +332 -0
  9. jcli/specs/plugins/jenkins_pipeline_validate.py +51 -0
  10. jcli/specs/plugins/jenkins_plugin.py +77 -0
  11. jcli/specs/plugins/jenkins_system.py +137 -0
  12. jcli/specs/resources/build.yaml +160 -0
  13. jcli/specs/resources/credential.yaml +97 -0
  14. jcli/specs/resources/job.yaml +184 -0
  15. jcli/specs/resources/node.yaml +69 -0
  16. jcli/specs/resources/pipeline.yaml +62 -0
  17. jcli/specs/resources/plugin.yaml +65 -0
  18. jcli/specs/resources/system.yaml +72 -0
  19. jcli/specs/resources/view.yaml +75 -0
  20. {python_jcli-1.0.0.dist-info → python_jcli-1.0.1.dist-info}/METADATA +10 -9
  21. python_jcli-1.0.1.dist-info/RECORD +40 -0
  22. jcli/plugins/__init__.py +0 -28
  23. jcli/plugins/build.py +0 -197
  24. jcli/plugins/config.py +0 -268
  25. jcli/plugins/credential.py +0 -210
  26. jcli/plugins/job.py +0 -425
  27. jcli/plugins/node.py +0 -134
  28. jcli/plugins/pipeline.py +0 -108
  29. jcli/plugins/plugin.py +0 -173
  30. jcli/plugins/system.py +0 -173
  31. jcli/plugins/view.py +0 -148
  32. jcli/sdk/build.py +0 -182
  33. jcli/sdk/credential.py +0 -143
  34. jcli/sdk/job.py +0 -191
  35. jcli/sdk/job_templates.py +0 -128
  36. jcli/sdk/node.py +0 -139
  37. jcli/sdk/pipeline.py +0 -121
  38. jcli/sdk/plugin.py +0 -155
  39. jcli/sdk/system.py +0 -202
  40. jcli/sdk/view.py +0 -94
  41. python_jcli-1.0.0.dist-info/RECORD +0 -44
  42. {python_jcli-1.0.0.dist-info → python_jcli-1.0.1.dist-info}/WHEEL +0 -0
  43. {python_jcli-1.0.0.dist-info → python_jcli-1.0.1.dist-info}/entry_points.txt +0 -0
  44. {python_jcli-1.0.0.dist-info → python_jcli-1.0.1.dist-info}/top_level.txt +0 -0
jcli/sdk/system.py DELETED
@@ -1,202 +0,0 @@
1
- """Jenkins System SDK functions.
2
-
3
- All functions take a :class:`~jcli.sdk.client.JenkinsClient` as the first argument.
4
- """
5
-
6
- from __future__ import annotations
7
-
8
- from typing import TYPE_CHECKING, Any
9
-
10
- if TYPE_CHECKING:
11
- from jcli.sdk.client import JenkinsClient
12
-
13
- # ------------------------------------------------------------------
14
- # Public API
15
- # ------------------------------------------------------------------
16
-
17
-
18
- def get_system_info(client: "JenkinsClient") -> dict[str, Any]:
19
- """Get Jenkins system information.
20
-
21
- Calls ``GET /api/json`` and extracts version from the ``X-Jenkins``
22
- response header.
23
-
24
- Args:
25
- client: Authenticated Jenkins API client.
26
-
27
- Returns:
28
- Dictionary with keys:
29
- - ``version``: Jenkins version string (from ``X-Jenkins`` header).
30
- - ``num_executors``: Total number of executors.
31
- - ``mode``: Executor mode (e.g. ``NORMAL``, ``EXCLUSIVE``).
32
- - ``quietingDown``: Whether Jenkins is in quiet-down mode.
33
- - ``slaveAgentPort``: Port for JNLP agents.
34
- - ``num_nodes``: Total number of connected nodes (from ``computer``).
35
- - ``num_jobs``: Total number of jobs.
36
- - ``raw``: Full API response data.
37
- """
38
- resp = client.request("GET", "/api/json")
39
- data: dict[str, Any] = resp.json()
40
-
41
- version = resp.headers.get("X-Jenkins", "unknown")
42
-
43
- # Count nodes from computer list if available
44
- num_nodes = 0
45
- computer = data.get("computer", [])
46
- if isinstance(computer, list):
47
- num_nodes = len(computer)
48
-
49
- return {
50
- "version": version,
51
- "num_executors": data.get("numExecutors", 0),
52
- "mode": data.get("mode", ""),
53
- "quietingDown": data.get("quietingDown", False),
54
- "slaveAgentPort": data.get("slaveAgentPort", 0),
55
- "num_nodes": num_nodes,
56
- "num_jobs": len(data.get("jobs", [])),
57
- "raw": data,
58
- }
59
-
60
-
61
- def safe_restart(client: "JenkinsClient") -> bool:
62
- """Trigger a safe restart of Jenkins.
63
-
64
- Calls ``POST /safeRestart``. Jenkins waits for running builds to
65
- complete before restarting.
66
-
67
- Args:
68
- client: Authenticated Jenkins API client.
69
-
70
- Returns:
71
- ``True`` on success (HTTP 200/302).
72
- """
73
- resp = client.request("POST", "/safeRestart")
74
- return resp.ok
75
-
76
-
77
- def quiet_down(client: "JenkinsClient", reason: str = "") -> bool:
78
- """Put Jenkins into quiet-down mode.
79
-
80
- In quiet-down mode, Jenkins stops scheduling new builds. Running
81
- builds continue until finished. Calls ``POST /quietDown``.
82
-
83
- Args:
84
- client: Authenticated Jenkins API client.
85
- reason: Optional reason shown on the quiet-down banner.
86
-
87
- Returns:
88
- ``True`` on success (HTTP 200/302).
89
- """
90
- params: dict[str, str] | None = None
91
- if reason:
92
- params = {"reason": reason}
93
- resp = client.request("POST", "/quietDown", params=params)
94
- return resp.ok
95
-
96
-
97
- def cancel_quiet_down(client: "JenkinsClient") -> bool:
98
- """Cancel quiet-down mode, allowing Jenkins to resume scheduling builds.
99
-
100
- Calls ``POST /cancelQuietDown``.
101
-
102
- Args:
103
- client: Authenticated Jenkins API client.
104
-
105
- Returns:
106
- ``True`` on success (HTTP 200/302).
107
- """
108
- resp = client.request("POST", "/cancelQuietDown")
109
- return resp.ok
110
-
111
-
112
- def run_script(client: "JenkinsClient", script: str) -> Any:
113
- """Execute a Groovy script on the Jenkins server.
114
-
115
- Calls ``POST /scriptText`` with form-encoded script content.
116
-
117
- Args:
118
- client: Jenkins API client.
119
- script: Groovy script text.
120
-
121
- Returns:
122
- Script output as text.
123
- """
124
- resp = client.post_data("/scriptText", data={"script": script})
125
- return resp.text
126
-
127
-
128
- def get_system_load(client: "JenkinsClient") -> dict[str, Any]:
129
- """Get current system load statistics.
130
-
131
- Calls ``GET /queue/api/json`` for the build queue and
132
- ``GET /computer/api/json`` for executor usage.
133
-
134
- Args:
135
- client: Authenticated Jenkins API client.
136
-
137
- Returns:
138
- Dictionary with keys:
139
- - ``queue_length``: Number of items in the build queue.
140
- - ``total_executors``: Total executors across all nodes.
141
- - ``busy_executors``: Currently busy executors.
142
- - ``idle_executors``: Currently idle executors.
143
- """
144
- queue_data = client.get_json("/queue/api/json")
145
- queue_items = queue_data.get("items", [])
146
- queue_length = len(queue_items) if isinstance(queue_items, list) else 0
147
-
148
- computer_data = client.get_json("/computer/api/json")
149
- computers = computer_data.get("computer", [])
150
- total_executors = 0
151
- busy_executors = 0
152
- if isinstance(computers, list):
153
- for c in computers:
154
- total_executors += c.get("numExecutors", 0)
155
- busy = c.get("busyExecutors", 0)
156
- if busy:
157
- busy_executors += busy
158
-
159
- idle_executors = total_executors - busy_executors
160
-
161
- return {
162
- "queue_length": queue_length,
163
- "total_executors": total_executors,
164
- "busy_executors": busy_executors,
165
- "idle_executors": idle_executors,
166
- }
167
-
168
-
169
- def list_users(client: "JenkinsClient") -> Any:
170
- """List all Jenkins users.
171
-
172
- Calls ``GET /asynchPeople/api/json``.
173
-
174
- Args:
175
- client: Authenticated Jenkins API client.
176
-
177
- Returns:
178
- Parsed JSON with users list.
179
- """
180
- return client.get_json("/asynchPeople/api/json")
181
-
182
-
183
- def generate_token(
184
- client: "JenkinsClient",
185
- username: str,
186
- token_name: str = "jcli-generated",
187
- ) -> Any:
188
- """Generate a new API token for a user.
189
-
190
- Calls ``POST /user/{name}/descriptorByName/jenkins.security.ApiTokenProperty/generateNewToken``.
191
-
192
- Args:
193
- client: Authenticated Jenkins API client.
194
- username: Jenkins username.
195
- token_name: Name/label for the new token.
196
-
197
- Returns:
198
- Parsed JSON with token data including the token value.
199
- """
200
- path = f"/user/{username}/descriptorByName/jenkins.security.ApiTokenProperty/generateNewToken"
201
- data = {"newTokenName": token_name}
202
- return client.post_data(path, data=data).json()
jcli/sdk/view.py DELETED
@@ -1,94 +0,0 @@
1
- """SDK functions for Jenkins View management."""
2
-
3
- from __future__ import annotations
4
-
5
- from typing import Any
6
-
7
- from jcli.sdk.client import JenkinsClient
8
- from jcli.sdk.exceptions import JenkinsAPIError
9
-
10
-
11
- def list_views(client: JenkinsClient) -> list[dict[str, Any]]:
12
- """List all views on the Jenkins server.
13
-
14
- Args:
15
- client: Authenticated Jenkins client.
16
-
17
- Returns:
18
- List of view dicts, each with ``name``, ``url``, and ``jobs`` keys.
19
-
20
- Raises:
21
- JenkinsAPIError: If the API request fails.
22
- """
23
- data = client.get_json("/api/json", tree="views[name,url,jobs[name]]")
24
- return data.get("views", [])
25
-
26
-
27
- def get_view(client: JenkinsClient, name: str) -> dict[str, Any]:
28
- """Get details for a single Jenkins view.
29
-
30
- Args:
31
- client: Authenticated Jenkins client.
32
- name: View name.
33
-
34
- Returns:
35
- View detail dict.
36
-
37
- Raises:
38
- JenkinsAPIError: If the API request fails.
39
- JenkinsNotFoundError: If the view doesn't exist.
40
- """
41
- return client.get_json(f"/view/{name}/api/json")
42
-
43
-
44
- def create_view(
45
- client: JenkinsClient,
46
- name: str,
47
- config_xml: str,
48
- ) -> None:
49
- """Create a new Jenkins view.
50
-
51
- Args:
52
- client: Authenticated Jenkins client.
53
- name: View name to create.
54
- config_xml: XML configuration for the view.
55
-
56
- Raises:
57
- JenkinsAPIError: If the API request fails (e.g. view already exists).
58
- """
59
- client.post_xml(f"/createView?name={name}", config_xml)
60
-
61
-
62
- def update_view(
63
- client: JenkinsClient,
64
- name: str,
65
- config_xml: str | bytes,
66
- ) -> Any:
67
- """Update a view's configuration.
68
-
69
- Args:
70
- client: Jenkins API client.
71
- name: View name.
72
- config_xml: New XML configuration.
73
-
74
- Returns:
75
- Response from Jenkins.
76
-
77
- Raises:
78
- JenkinsAPIError: If the API request fails.
79
- """
80
- return client.post_xml(f"/view/{name}/config.xml", config_xml)
81
-
82
-
83
- def delete_view(client: JenkinsClient, name: str) -> None:
84
- """Delete an existing Jenkins view.
85
-
86
- Args:
87
- client: Authenticated Jenkins client.
88
- name: View name to delete.
89
-
90
- Raises:
91
- JenkinsAPIError: If the API request fails.
92
- JenkinsNotFoundError: If the view doesn't exist.
93
- """
94
- client.post_data(f"/view/{name}/doDelete", data="")
@@ -1,44 +0,0 @@
1
- jcli/__init__.py,sha256=J-j-u0itpEFT6irdmWmixQqYMadNl1X91TxUmoiLHMI,22
2
- jcli/__main__.py,sha256=ARL8XYr45T4pIf0gnyCCbK8uljcn1LF7TKcFapxHt_k,34
3
- jcli/cli.py,sha256=cg45uwYAW2IsdilPffCBSWK7RE2ragnKJ2xiYp9_m94,21175
4
- jcli/cli_helpers.py,sha256=8GsvEwmaqS8p9Rpx7d_b3_i_Pwag8zsJNNbunxgNXS0,1831
5
- jcli/plugins/__init__.py,sha256=I6vTpfYO3gIwHoNu5V-sOIdpT_g-bAy4RXR3TW3-k1U,1054
6
- jcli/plugins/build.py,sha256=60F0UPMFy_eZznBeAIM0XwCcQ3pAuJJjacGaCXxOlcI,6032
7
- jcli/plugins/config.py,sha256=OEl8X5zrYIBRHhBx1s6GokqBZ2yKRLYgMOVJjjbZgho,8302
8
- jcli/plugins/credential.py,sha256=ZLdKXoU1ZResv0FqWOH6XWNfb5iSi1rg3dFX1VZPd10,6415
9
- jcli/plugins/job.py,sha256=dq5jbAn8ZjtYNqJlo7u-0iORubMdZMB2sj4GVK01xoU,12872
10
- jcli/plugins/node.py,sha256=nwUDYvev9R_BOoYHVmNvNp3vhrmZAXVFN2z_-F_iO7I,4776
11
- jcli/plugins/pipeline.py,sha256=vTtLk0tPiMSwy2CsCEmtQMhbt9baFoxAqGCSyHtOmOc,3049
12
- jcli/plugins/plugin.py,sha256=0LMaPjr5jpZokOLENt0rDi_Klk4JYcw8uUzZUceDYvk,4713
13
- jcli/plugins/skills.py,sha256=5Nw3kPLbx82-8ackdXVLnIL09jziv53jhMZ2sCqYihk,14921
14
- jcli/plugins/system.py,sha256=2ojwBOsaiuNKmuiTLvU6GpLeSI3-kccy1QjpHuX_8vE,4938
15
- jcli/plugins/view.py,sha256=eH7pCe7Tw1rC4kVBZDxHqVd3ZrXYLlVxNGPjWvhgw8Q,4475
16
- jcli/sdk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- jcli/sdk/build.py,sha256=xNMPOCL-RUBQo7OJDuaIZ-DtnxN15kZbyO_insEiklM,5309
18
- jcli/sdk/client.py,sha256=hnBZcS82ziPyHepPWq7femUqQppw8QCtwbdMrWYVrxc,8723
19
- jcli/sdk/config.py,sha256=fSBTWqE0i8jpzmtGfo2M-Ln2Y5eQRQD0StS76glyCsI,6992
20
- jcli/sdk/credential.py,sha256=ayasSZjfn62Z1E6Rc15mqeqN0LyQ1wzO2OBsmlXY7Kk,4009
21
- jcli/sdk/exceptions.py,sha256=zv5oYOr_t0rma4lVudLp3gLdL5idSzlKGc7g2MowcL0,1737
22
- jcli/sdk/job.py,sha256=SLuCWdmKm9Y-hh1-TGGNCtELbFen8o6kt4nn4q1BqGg,4877
23
- jcli/sdk/job_templates.py,sha256=IDQFvlLjMxDP1sLfZUHSo6karjVKu9rsb3dZlMmXqpM,4021
24
- jcli/sdk/node.py,sha256=N7VTTxXhZKtik2Pn5tJMLoVkqz7iI5BDc-4o8u_c4Ig,4032
25
- jcli/sdk/pipeline.py,sha256=NLUNC8thSfHWc9_hf5N6wpeeHNlAFLj74Crb5HZmPG8,3515
26
- jcli/sdk/plugin.py,sha256=kKmxVPgV66sEUAc9J85-E8edY3qpcTw1M4FY_7OUqW8,4671
27
- jcli/sdk/system.py,sha256=L5PHlrjs-5_PFFOQ9IBA-vMwgQyqq33TfJidTcs0VSQ,6022
28
- jcli/sdk/view.py,sha256=5Poo50l3eY9ivef3hs0CyL-K39qDk39XQuX7gEHHRlA,2300
29
- jcli/sdk/output/__init__.py,sha256=Rt0F77oq24tqHvTDV4HyWKAjDtOyPOh9m7ucFy7B77s,70
30
- jcli/sdk/output/formatter.py,sha256=OUjQxeD-2iSNncuuRaLa01qLi899ux3F39KNkc8ik2Q,3876
31
- jcli/skills/jcli/SKILL.md,sha256=X9xHxRvNa4F3hUN8bhckBXAJZx2MWY58hGqqd0y158M,3040
32
- jcli/skills/jcli/auth/SKILL.md,sha256=4_DLD51SwKTXh2Xi0UiQbqG4uXw7qIKv2SOOopS2Qn0,1996
33
- jcli/skills/jcli/credential/SKILL.md,sha256=3VsVdGalsIySvGfFO79IdL0b5OjF7kJBS9_4P56Wt2A,1244
34
- jcli/skills/jcli/job/SKILL.md,sha256=bmGyiyLXS2n395bA31gehcMRe094SUBq-FzUlUDvpQM,2066
35
- jcli/skills/jcli/node/SKILL.md,sha256=k4qi6ApspdIlBcxb0v2ItPrPwT7d9AnFq4N-vGhGcqY,1247
36
- jcli/skills/jcli/pipeline/SKILL.md,sha256=kUwnxBCUx53zi7efVgtJg9ainO-YuX3griaCqoUyzxU,1231
37
- jcli/skills/jcli/plugin/SKILL.md,sha256=--1t5LekIHAtnCWUnsQ9BKkPIgAQ7n-p7_QGd8H2jbI,1178
38
- jcli/skills/jcli/system/SKILL.md,sha256=SHdcLbaJyifjt4KJlmdcHdYLsFGwpF-6lqiWdYpw3co,1932
39
- jcli/skills/jcli/view/SKILL.md,sha256=f2QZEzvFocIlR7Yh0RKnp5y4sijwUJU_1fxiW7gKJcA,1047
40
- python_jcli-1.0.0.dist-info/METADATA,sha256=9A7W8m365rFW8_iTXqwPA9VFDE-YUmNvdLR-7BKH7qs,12497
41
- python_jcli-1.0.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
42
- python_jcli-1.0.0.dist-info/entry_points.txt,sha256=g-Gb8voGH3Ru4NEoCUMJXJiMZMapdAfYi6Xt1phyFi4,39
43
- python_jcli-1.0.0.dist-info/top_level.txt,sha256=WFqrbWSEfhvQfbN2m-_Wi5KKCwv1_23LhzPUqo7AdQc,5
44
- python_jcli-1.0.0.dist-info/RECORD,,