zosmfrestapi 0.2.1__tar.gz → 0.3.1__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.
Files changed (39) hide show
  1. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/PKG-INFO +95 -49
  2. zosmfrestapi-0.3.1/README.md +191 -0
  3. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/pyproject.toml +29 -20
  4. zosmfrestapi-0.3.1/zosmfrestapi/__init__.py +11 -0
  5. zosmfrestapi-0.2.1/zosmfrestapi/utils.py → zosmfrestapi-0.3.1/zosmfrestapi/_utils.py +1 -1
  6. zosmfrestapi-0.3.1/zosmfrestapi/exceptions/__init__.py +21 -0
  7. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/exceptions/authentication.py +1 -1
  8. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/exceptions/dataset.py +1 -1
  9. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/exceptions/software.py +1 -1
  10. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/exceptions/workflow.py +1 -1
  11. zosmfrestapi-0.3.1/zosmfrestapi/models/__init__.py +35 -0
  12. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/services/software.py +6 -7
  13. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/services/software_updates.py +10 -11
  14. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/services/topology.py +3 -3
  15. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/services/workflow.py +8 -10
  16. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/zcrypto_client.py +2 -1
  17. zosmfrestapi-0.2.1/README.md +0 -146
  18. zosmfrestapi-0.2.1/zosmfrestapi/__init__.py +0 -93
  19. zosmfrestapi-0.2.1/zosmfrestapi/models/__init__.py +0 -0
  20. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/LICENSE +0 -0
  21. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/client.py +0 -0
  22. /zosmfrestapi-0.2.1/zosmfrestapi/exceptions/__init__.py → /zosmfrestapi-0.3.1/zosmfrestapi/exceptions/commons.py +0 -0
  23. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/models/authentication.py +0 -0
  24. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/models/software.py +0 -0
  25. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/models/software_updates.py +0 -0
  26. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/models/topology.py +0 -0
  27. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/models/workflow.py +0 -0
  28. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/py.typed +0 -0
  29. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/services/__init__.py +0 -0
  30. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/services/authentication.py +0 -0
  31. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/services/dataset.py +0 -0
  32. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/testing/__init__.py +0 -0
  33. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/testing/authentication.py +0 -0
  34. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/testing/helpers.py +0 -0
  35. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/testing/software.py +0 -0
  36. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/testing/software_updates.py +0 -0
  37. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/testing/topology.py +0 -0
  38. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/testing/workflows.py +0 -0
  39. {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/zcrypto.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zosmfrestapi
3
- Version: 0.2.1
3
+ Version: 0.3.1
4
4
  Summary: A Python wrapper for the z/OSMF REST API
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -19,23 +19,23 @@ Requires-Dist: httpx2 (>=2.12.0,<3.0.0)
19
19
  Requires-Dist: pendulum (>=3.2.0,<4.0.0)
20
20
  Requires-Dist: py_zcrypto ; extra == "zcrypto"
21
21
  Project-URL: Homepage, https://sr.ht/~ocurero/zosmfrestapi/
22
+ Project-URL: Issues, https://todo.sr.ht/~ocurero/zosmfrestapi
22
23
  Project-URL: PyPI, https://pypi.org/project/zosmfrestapi/
23
24
  Project-URL: Repository, https://git.sr.ht/~ocurero/zosmfrestapi
24
25
  Description-Content-Type: text/markdown
25
26
 
26
- # A Python wrapper for the z/OSMF© REST API
27
+ # A Python wrapper for the z/OSMF REST API
27
28
 
28
29
  [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)
29
30
  [![builds.sr.ht status](https://builds.sr.ht/~ocurero/zosmfrestapi/commits/main/.build.yml.svg)](https://builds.sr.ht/~ocurero/zosmfrestapi/commits/main/.build.yml?)
30
- ![z/OS](https://img.shields.io/badge/works%20on-z/OS-8A2BE2)
31
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
31
+ [![100% coverage](https://img.shields.io/badge/coverage-100%25-brightgreen)](https://builds.sr.ht/~ocurero/zosmfrestapi/commits/main/.build.yml?)
32
32
  [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
33
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
34
+ ![z/OS](https://img.shields.io/badge/works%20on-z/OS-8A2BE2)
33
35
 
34
- * Open Source: MIT License.
35
36
  * Website: <https://sr.ht/~ocurero/zosmfrestapi/>
36
37
  * Repository: <https://git.sr.ht/~ocurero/zosmfrestapi>
37
38
  * Changelog: <https://git.sr.ht/~ocurero/zosmfrestapi/tree/main/item/CHANGELOG.md>
38
- * Contributing: <https://git.sr.ht/~ocurero/zosmfrestapi/tree/main/item/CONTRIBUTING.md>
39
39
 
40
40
  Key features:
41
41
  * **Pure Python**: Package and its dependencies are 100% pure Python (no C extensions required).
@@ -43,6 +43,8 @@ Key features:
43
43
  * **Flexible authentication**: Supports user/password, LTPA and JWT tokens, and mutual TLS (mTLS).
44
44
  * **Proxy ready**: Full support for standard HTTP/HTTPS proxies as well as authenticated proxies.
45
45
 
46
+ ![ZosmfClient demo](https://git.sr.ht/~ocurero/zosmfrestapi/blob/main/docs/ZosmfClient.gif)
47
+
46
48
 
47
49
  Install
48
50
  -------
@@ -62,32 +64,16 @@ root folder instead:
62
64
  python -m pip install .
63
65
  ```
64
66
 
65
- ## First request
66
-
67
- Save this as `example.py` and run it with `python example.py`. Enter the base
68
- URL of your z/OSMF server when prompted (for example,
69
- `https://zosmf.example.com:443`). The URL should include `https://` and any
70
- required port, but not an API path such as `/zosmf`.
71
-
72
- The password is requested without displaying it and is not stored in the
73
- script. Replace the sample operation with one your z/OSMF user is authorized to
74
- perform.
67
+ ## Quickstart
75
68
 
76
69
  ```python
77
- from getpass import getpass
78
-
79
- from zosmfrestapi import ZosmfClient, ZosmfError
80
70
 
81
- server = input("z/OSMF server URL: ").strip().rstrip("/")
82
- username = input("User ID: ").strip()
83
- password = getpass("Password: ")
71
+ from zosmfrestapi import ZosmfClient
84
72
 
85
- try:
86
- with ZosmfClient(server, username=username, password=password) as client:
87
- for instance in client.list_swis():
88
- print(f"{instance.name} ({instance.system})")
89
- except ZosmfError as error:
90
- print(f"The z/OSMF request failed: {error}")
73
+ with ZosmfClient("https://zosmf.example",
74
+ username="demouser", password="itsasecret") as client:
75
+ for instance in client.list_swis():
76
+ print(f"{instance.name} ({instance.system})")
91
77
  ```
92
78
 
93
79
  The `with` block closes the network connection automatically, even if a request
@@ -104,15 +90,54 @@ These calls must be made inside the `with` block, before the client is closed.
104
90
  For a partitioned data set member, use a name such as
105
91
  `USER.PDS(MEMBER)`.
106
92
 
93
+ ## Clients
94
+
95
+ The library provides two client implementations:
96
+
97
+ * **`ZosmfClient`**: The standard synchronous client for communicating with z/OSMF using username/password, tokens, or standard TLS certificate files.
98
+ * **`ZosmfZcryptoClient`**: A specialized client for z/OS environments that extracts mutual TLS (mTLS) client certificates directly from SAF key rings (RACF, ACF2, Top Secret).
99
+
100
+ ### Platform Support
101
+
102
+ | Client | Linux | macOS | Windows | z/OS USS |
103
+ | --- | :---: | :---: | :---: | :---: |
104
+ | `ZosmfClient` | ✅ | ✅ | ✅ | ✅ |
105
+ | `ZosmfZcryptoClient` | ❌ | ❌ | ❌ | ✅ |
106
+
107
+ ### Using `ZosmfZcryptoClient` on z/OS
108
+
109
+ ![ZosmfZcryptoClient demo](https://git.sr.ht/~ocurero/zosmfrestapi/blob/main/docs/ZosmfZcryptoClient.gif)
110
+
111
+ `ZosmfZcryptoClient` retrieves client certificates and private keys directly from a SAF key ring, exporting temporary PEM files and configuring mutual TLS transparently. When using a key ring owned by the current user, specify the ring name as "name". When using a key ring owned by another user, specify the ring name as "userid/name":
112
+
113
+ ```python
114
+ from zosmfrestapi import ZosmfZcryptoClient
115
+
116
+ with ZosmfZcryptoClient("https://zosmf.example",
117
+ keyring="userid/name", label="zOSMF Client Certificate") as client:
118
+ systems = client.get_systems()
119
+ ```
120
+
121
+ Install the optional `zcrypto` extra:
122
+
123
+ ```console
124
+ python -m pip install "zosmfrestapi[zcrypto]"
125
+ ```
126
+
127
+ > [!WARNING]
128
+ > The `zcrypto` extra requires `py_zcrypto`, a C extension that compiles against z/OS System SSL C headers. Therefore, it can **only** be installed and executed on **z/OS** systems. Attempting to install or use `ZosmfZcryptoClient` on Linux, macOS, or Windows will raise a `RuntimeError`.
129
+
130
+
131
+
107
132
  ## Authentication and TLS
108
133
 
109
134
  The client uses the server's normal TLS certificate checks by default. Keep
110
- those checks enabled for routine use. The HTTP transport is HTTPX2, a fork of
111
- HTTPX; HTTPX2 uses `truststore` to integrate operating-system certificate
112
- stores when it creates its default TLS context. This package currently passes
113
- its own context, created with Python's `ssl.create_default_context()`, so the
114
- certificates available to Python are used. If the z/OSMF server's CA is not
115
- trusted in that environment, pass its certificate file with `cafile` below.
135
+ those checks enabled for routine use. The HTTP transport is HTTPX2; HTTPX2 uses `truststore`
136
+ to integrate operating-system certificate stores when it creates its default TLS context.
137
+ zosmfrestapi currently passes its own context, created with Python's
138
+ `ssl.create_default_context()`, so the certificates available to Python are used.
139
+ If the z/OSMF server's CA is no trusted in that environment, pass its certificate file
140
+ with `cafile` below.
116
141
 
117
142
  | Situation | Client option |
118
143
  | --- | --- |
@@ -121,33 +146,31 @@ trusted in that environment, pass its certificate file with `cafile` below.
121
146
  | Client certificate and key in one PEM file | `cert="client.pem"` |
122
147
  | Internal certificate authority | `cafile="company-ca.pem"` |
123
148
  | Existing LTPA or JWT token | `ltpa_token="..."` or `jwt_token="..."` |
149
+ | Identity propagation (needs [PH68412](https://www.ibm.com/support/pages/apar/PH68412)) | None |
124
150
  | Network proxy | `proxy="http://proxy.example.com:8080"` |
125
151
 
126
152
  For example, to trust an internal certificate authority, pass `cafile` when
127
153
  creating the client:
128
154
 
129
155
  ```python
130
- with ZosmfClient(server, username=username, password=password,
156
+ with ZosmfClient("https://zosmf.example", username="demouser", password="itsasecret",
131
157
  cafile="company-ca.pem") as client:
132
158
  systems = client.get_systems()
133
159
  ```
134
160
 
135
- Avoid putting passwords or tokens directly in scripts, committing them to
136
- version control, or sharing them in logs. The `insecure=True` option disables
137
- TLS certificate verification; use it only for temporary diagnostics, never as
138
- a production fix. It cannot be combined with `cert` or `cafile`.
139
-
140
- ## What you can do
161
+ The `insecure=True` option disables TLS certificate verification; use it only for temporary
162
+ diagnostics, never as a production fix. It cannot be combined with `cert` or `cafile`.
141
163
 
142
- The client provides synchronous methods for:
164
+ ## Supported APIs
143
165
 
144
- * Authentication (`authenticate`).
145
- * z/OSMF groups and systems (`get_groups`, `get_systems`).
146
- * Data sets (`read_dataset`).
147
- * Software instances and SMP/E information (`list_swis`, `get_swi_by_name`,
148
- `get_swi_by_uuid`, and related query methods).
149
- * Workflows (list, inspect, create, start, wait for, cancel, and archive).
150
- * Software updates (search, inspect, start, monitor, and cancel).
166
+ | API Category | Description | Key Methods (examples) |
167
+ | --- | --- | --- |
168
+ | **Authentication** | Basic Auth, LTPA / JWT tokens session login | `authenticate()` |
169
+ | **Topology** | Query systems and sysplex groups defined in z/OSMF | `get_groups()`, `get_systems()` |
170
+ | **Datasets** | Sequential and partitioned dataset retrieval | `read_dataset()` |
171
+ | **Software Management** | SMP/E software instances, CSI queries, and datasets | `list_swis()`, `get_swi_by_name()`, `query_csi_by_name()` |
172
+ | **Software Updates** | Search, inspect, start, monitor, and cancel update processes | `search_sw_updates_by_name()`, `start_sw_update_by_name()`, `check_sw_update_status()` |
173
+ | **Workflows** | List, create, inspect, execute, monitor, and archive workflows | `get_workflows()`, `create_workflow()`, `start_workflow()`, `wait_for_workflow()` |
151
174
 
152
175
  Some operations change z/OSMF state. Check the method documentation and make
153
176
  sure your account has the required permissions before using them.
@@ -170,3 +193,26 @@ sure your account has the required permissions before using them.
170
193
  For the complete API, parameters, and return types, see the docstrings in the
171
194
  package source and the project website.
172
195
 
196
+ ## Contributing
197
+
198
+ Contributions are welcome! Please see [CONTRIBUTING.md](https://git.sr.ht/~ocurero/zosmfrestapi/tree/main/item/CONTRIBUTING.md) for guidelines on development, testing, and submitting patches.
199
+
200
+ ## Issues and Feedback
201
+
202
+ If you encounter any bugs or have feature requests, please report them on the [SourceHut issue tracker](https://todo.sr.ht/~ocurero/zosmfrestapi).
203
+
204
+ ## License
205
+
206
+ The MIT License. See [LICENSE](https://git.sr.ht/~ocurero/zosmfrestapi/tree/main/item/LICENSE).
207
+
208
+ ## Trademarks
209
+
210
+ IBM, the IBM logo, z/OS, MVS, and Z/OSMF are trademarks or are
211
+ registered trademarks of International Business Machines Corporation,
212
+ registered in many jurisdictions worldwide. Other product and service
213
+ names might be trademarks of IBM or other companies. A current list
214
+ of IBM trademarks is available at <https://www.ibm.com/legal/copytrade>.
215
+
216
+ This project is an independent community effort. It is not affiliated
217
+ with, endorsed by, or sponsored by IBM.
218
+
@@ -0,0 +1,191 @@
1
+ # A Python wrapper for the z/OSMF REST API
2
+
3
+ [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)
4
+ [![builds.sr.ht status](https://builds.sr.ht/~ocurero/zosmfrestapi/commits/main/.build.yml.svg)](https://builds.sr.ht/~ocurero/zosmfrestapi/commits/main/.build.yml?)
5
+ [![100% coverage](https://img.shields.io/badge/coverage-100%25-brightgreen)](https://builds.sr.ht/~ocurero/zosmfrestapi/commits/main/.build.yml?)
6
+ [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+ ![z/OS](https://img.shields.io/badge/works%20on-z/OS-8A2BE2)
9
+
10
+ * Website: <https://sr.ht/~ocurero/zosmfrestapi/>
11
+ * Repository: <https://git.sr.ht/~ocurero/zosmfrestapi>
12
+ * Changelog: <https://git.sr.ht/~ocurero/zosmfrestapi/tree/main/item/CHANGELOG.md>
13
+
14
+ Key features:
15
+ * **Pure Python**: Package and its dependencies are 100% pure Python (no C extensions required).
16
+ * **Cross-platform**: Works on Windows, Linux, macOS, and z/OS UNIX System Services.
17
+ * **Flexible authentication**: Supports user/password, LTPA and JWT tokens, and mutual TLS (mTLS).
18
+ * **Proxy ready**: Full support for standard HTTP/HTTPS proxies as well as authenticated proxies.
19
+
20
+ ![ZosmfClient demo](https://git.sr.ht/~ocurero/zosmfrestapi/blob/main/docs/ZosmfClient.gif)
21
+
22
+
23
+ Install
24
+ -------
25
+
26
+ **zosmfrestapi** requires Python 3.12 or newer and access to a z/OSMF server.
27
+
28
+ Install the package from PyPI:
29
+
30
+ ```console
31
+ python -m pip install zosmfrestapi
32
+ ```
33
+
34
+ If you have downloaded or cloned the source code, run this from the project's
35
+ root folder instead:
36
+
37
+ ```console
38
+ python -m pip install .
39
+ ```
40
+
41
+ ## Quickstart
42
+
43
+ ```python
44
+
45
+ from zosmfrestapi import ZosmfClient
46
+
47
+ with ZosmfClient("https://zosmf.example",
48
+ username="demouser", password="itsasecret") as client:
49
+ for instance in client.list_swis():
50
+ print(f"{instance.name} ({instance.system})")
51
+ ```
52
+
53
+ The `with` block closes the network connection automatically, even if a request
54
+ fails. `list_swis()` returns Python objects; the example prints each software
55
+ instance's name and system. You can also query systems or read a data set. Put
56
+ these calls inside the `with` block shown above, before it ends:
57
+
58
+ ```python
59
+ systems = client.get_systems()
60
+ contents = client.read_dataset("USER.DATASET")
61
+ ```
62
+
63
+ These calls must be made inside the `with` block, before the client is closed.
64
+ For a partitioned data set member, use a name such as
65
+ `USER.PDS(MEMBER)`.
66
+
67
+ ## Clients
68
+
69
+ The library provides two client implementations:
70
+
71
+ * **`ZosmfClient`**: The standard synchronous client for communicating with z/OSMF using username/password, tokens, or standard TLS certificate files.
72
+ * **`ZosmfZcryptoClient`**: A specialized client for z/OS environments that extracts mutual TLS (mTLS) client certificates directly from SAF key rings (RACF, ACF2, Top Secret).
73
+
74
+ ### Platform Support
75
+
76
+ | Client | Linux | macOS | Windows | z/OS USS |
77
+ | --- | :---: | :---: | :---: | :---: |
78
+ | `ZosmfClient` | ✅ | ✅ | ✅ | ✅ |
79
+ | `ZosmfZcryptoClient` | ❌ | ❌ | ❌ | ✅ |
80
+
81
+ ### Using `ZosmfZcryptoClient` on z/OS
82
+
83
+ ![ZosmfZcryptoClient demo](https://git.sr.ht/~ocurero/zosmfrestapi/blob/main/docs/ZosmfZcryptoClient.gif)
84
+
85
+ `ZosmfZcryptoClient` retrieves client certificates and private keys directly from a SAF key ring, exporting temporary PEM files and configuring mutual TLS transparently. When using a key ring owned by the current user, specify the ring name as "name". When using a key ring owned by another user, specify the ring name as "userid/name":
86
+
87
+ ```python
88
+ from zosmfrestapi import ZosmfZcryptoClient
89
+
90
+ with ZosmfZcryptoClient("https://zosmf.example",
91
+ keyring="userid/name", label="zOSMF Client Certificate") as client:
92
+ systems = client.get_systems()
93
+ ```
94
+
95
+ Install the optional `zcrypto` extra:
96
+
97
+ ```console
98
+ python -m pip install "zosmfrestapi[zcrypto]"
99
+ ```
100
+
101
+ > [!WARNING]
102
+ > The `zcrypto` extra requires `py_zcrypto`, a C extension that compiles against z/OS System SSL C headers. Therefore, it can **only** be installed and executed on **z/OS** systems. Attempting to install or use `ZosmfZcryptoClient` on Linux, macOS, or Windows will raise a `RuntimeError`.
103
+
104
+
105
+
106
+ ## Authentication and TLS
107
+
108
+ The client uses the server's normal TLS certificate checks by default. Keep
109
+ those checks enabled for routine use. The HTTP transport is HTTPX2; HTTPX2 uses `truststore`
110
+ to integrate operating-system certificate stores when it creates its default TLS context.
111
+ zosmfrestapi currently passes its own context, created with Python's
112
+ `ssl.create_default_context()`, so the certificates available to Python are used.
113
+ If the z/OSMF server's CA is no trusted in that environment, pass its certificate file
114
+ with `cafile` below.
115
+
116
+ | Situation | Client option |
117
+ | --- | --- |
118
+ | User ID and password | `username="...", password="..."` |
119
+ | Client certificate and key in separate files | `cert=("client.crt", "client.key")` |
120
+ | Client certificate and key in one PEM file | `cert="client.pem"` |
121
+ | Internal certificate authority | `cafile="company-ca.pem"` |
122
+ | Existing LTPA or JWT token | `ltpa_token="..."` or `jwt_token="..."` |
123
+ | Identity propagation (needs [PH68412](https://www.ibm.com/support/pages/apar/PH68412)) | None |
124
+ | Network proxy | `proxy="http://proxy.example.com:8080"` |
125
+
126
+ For example, to trust an internal certificate authority, pass `cafile` when
127
+ creating the client:
128
+
129
+ ```python
130
+ with ZosmfClient("https://zosmf.example", username="demouser", password="itsasecret",
131
+ cafile="company-ca.pem") as client:
132
+ systems = client.get_systems()
133
+ ```
134
+
135
+ The `insecure=True` option disables TLS certificate verification; use it only for temporary
136
+ diagnostics, never as a production fix. It cannot be combined with `cert` or `cafile`.
137
+
138
+ ## Supported APIs
139
+
140
+ | API Category | Description | Key Methods (examples) |
141
+ | --- | --- | --- |
142
+ | **Authentication** | Basic Auth, LTPA / JWT tokens session login | `authenticate()` |
143
+ | **Topology** | Query systems and sysplex groups defined in z/OSMF | `get_groups()`, `get_systems()` |
144
+ | **Datasets** | Sequential and partitioned dataset retrieval | `read_dataset()` |
145
+ | **Software Management** | SMP/E software instances, CSI queries, and datasets | `list_swis()`, `get_swi_by_name()`, `query_csi_by_name()` |
146
+ | **Software Updates** | Search, inspect, start, monitor, and cancel update processes | `search_sw_updates_by_name()`, `start_sw_update_by_name()`, `check_sw_update_status()` |
147
+ | **Workflows** | List, create, inspect, execute, monitor, and archive workflows | `get_workflows()`, `create_workflow()`, `start_workflow()`, `wait_for_workflow()` |
148
+
149
+ Some operations change z/OSMF state. Check the method documentation and make
150
+ sure your account has the required permissions before using them.
151
+
152
+ ## Troubleshooting
153
+
154
+ * **Python version error:** install Python 3.12 or newer, then recreate the
155
+ virtual environment with that interpreter.
156
+ * **401 / unauthorized:** check the server URL, user ID, password or token, and
157
+ whether the account is authorized for the requested API.
158
+ * **Certificate verification error:** ask your z/OSMF administrator for the
159
+ correct CA certificate and pass its path with `cafile`.
160
+ * **Connection or timeout error:** check that the server and port are reachable
161
+ from your machine and that any required proxy is configured.
162
+ * **PowerShell will not activate the virtual environment:** use the Python
163
+ executable inside `.venv\Scripts\python.exe` to run commands, or follow your
164
+ organization's PowerShell policy guidance. Do not change the machine-wide
165
+ execution policy just to install this package.
166
+
167
+ For the complete API, parameters, and return types, see the docstrings in the
168
+ package source and the project website.
169
+
170
+ ## Contributing
171
+
172
+ Contributions are welcome! Please see [CONTRIBUTING.md](https://git.sr.ht/~ocurero/zosmfrestapi/tree/main/item/CONTRIBUTING.md) for guidelines on development, testing, and submitting patches.
173
+
174
+ ## Issues and Feedback
175
+
176
+ If you encounter any bugs or have feature requests, please report them on the [SourceHut issue tracker](https://todo.sr.ht/~ocurero/zosmfrestapi).
177
+
178
+ ## License
179
+
180
+ The MIT License. See [LICENSE](https://git.sr.ht/~ocurero/zosmfrestapi/tree/main/item/LICENSE).
181
+
182
+ ## Trademarks
183
+
184
+ IBM, the IBM logo, z/OS, MVS, and Z/OSMF are trademarks or are
185
+ registered trademarks of International Business Machines Corporation,
186
+ registered in many jurisdictions worldwide. Other product and service
187
+ names might be trademarks of IBM or other companies. A current list
188
+ of IBM trademarks is available at <https://www.ibm.com/legal/copytrade>.
189
+
190
+ This project is an independent community effort. It is not affiliated
191
+ with, endorsed by, or sponsored by IBM.
@@ -21,11 +21,12 @@ dependencies = [
21
21
  "dacite (>=1.9.2,<2.0.0)",
22
22
  ]
23
23
  dynamic = []
24
- version = "0.2.1"
24
+ version = "0.3.1"
25
25
 
26
26
  [project.urls]
27
27
  Homepage = "https://sr.ht/~ocurero/zosmfrestapi/"
28
28
  Repository = "https://git.sr.ht/~ocurero/zosmfrestapi"
29
+ Issues = "https://todo.sr.ht/~ocurero/zosmfrestapi"
29
30
  PyPI = "https://pypi.org/project/zosmfrestapi/"
30
31
 
31
32
  [project.optional-dependencies]
@@ -35,11 +36,11 @@ zcrypto = [
35
36
 
36
37
  [dependency-groups]
37
38
  dev = [
39
+ "coverage (>=7.17.3,<8.0.0)",
38
40
  "pytest (>=9.1.1,<10.0.0)",
39
41
  "black (>=26.5.1,<27.0.0)",
40
42
  "pytest-recording (>=0.14.0,<0.15.0)",
41
43
  "pytest-httpx2 (>=1.0.0,<2.0.0)",
42
- "pytest-cov (>=7.1.0,<8.0.0)",
43
44
  "flake8 (>=7.5.0,<8.0.0)",
44
45
  "flake8-pyproject (>=1.2.4,<2.0.0)",
45
46
  "mypy (>=2.4.1,<3.0.0)",
@@ -60,33 +61,42 @@ per-file-ignores = "tests/*.py:E501"
60
61
 
61
62
  [tool.pytest.ini_options]
62
63
  testpaths = ["tests"]
63
- addopts = ["-ra",
64
- "--record-mode=none",
65
- "--cov-fail-under=100",
66
- "--cov=zosmfrestapi",
67
- ]
68
64
 
69
65
 
70
- [tool.poe.tasks]
71
- format = "black ."
66
+ [tool.poe.groups.quality.tasks.format]
67
+ help = "Format code acording to black."
68
+ cmd = "black zosmfrestapi tests"
72
69
 
73
- lint = [
70
+ [tool.poe.groups.quality.tasks.quality]
71
+ help = "Run quality checks: black, flake8, mypy and pyright."
72
+ sequence = [
74
73
  { cmd = "black --check ." },
75
- { cmd = "flake8" },
74
+ { cmd = "flake8 zosmfrestapi" },
76
75
  { cmd = "mypy zosmfrestapi" },
77
76
  { cmd = "pyright --warnings" }
77
+ ]
78
78
 
79
+ [tool.poe.groups.testing.tasks.client_tests]
80
+ help = "Run client tests only."
81
+ sequence = [{cmd = """coverage run --omit='tests/*,*/zcrypto*' -m
82
+ pytest --ignore=tests/test_zcrypto_client.py"""},
83
+ {cmd = "coverage report --fail-under=100 --show-missing"}
79
84
  ]
80
85
 
81
- test = "pytest"
86
+ [tool.poe.groups.testing.tasks.zcrypto_tests]
87
+ help = "Run zcrypto tests only."
88
+ sequence = [{cmd = """coverage run --omit='tests/*' --include='*/zcrypto*' -m
89
+ pytest tests/test_zcrypto_client.py"""},
90
+ {cmd = "coverage report --fail-under=100 --show-missing"}
91
+ ]
82
92
 
83
- check = [
84
- { cmd = "black --check ." },
85
- { cmd = "flake8 zosmfrestapi" },
86
- { cmd = "pyright --warnings" },
87
- { cmd = "mypy zosmfrestapi" },
88
- { cmd = "pytest" }
89
- ]
93
+ [tool.poe.groups.testing.tasks.tests]
94
+ help = "Run client and zcrypto tests."
95
+ sequence = ["client_tests", "zcrypto_tests"]
96
+
97
+ [tool.poe.tasks.check]
98
+ help = "Run all checks."
99
+ sequence = ["quality", "client_tests", "zcrypto_tests"]
90
100
 
91
101
  [[tool.mypy.overrides]]
92
102
  module = ["OpenSSL.*", "py_zcrypto.*"]
@@ -100,4 +110,3 @@ enable = false
100
110
  [build-system]
101
111
  requires = ["poetry-core>=1.0.0", "poetry-dynamic-versioning>=1.0.0,<2.0.0"]
102
112
  build-backend = "poetry_dynamic_versioning.backend"
103
-
@@ -0,0 +1,11 @@
1
+ """Synchronous Python client for the z/OSMF REST API.
2
+
3
+ The package root re-exports :class:`ZosmfClient` and :class:`ZosmfZcryptoClient`.
4
+ Create one client per server/configuration and use it as a context manager to close
5
+ the shared HTTP session when finished.
6
+ """
7
+
8
+ from zosmfrestapi.client import ZosmfClient
9
+ from zosmfrestapi.zcrypto_client import ZosmfZcryptoClient
10
+
11
+ __all__ = ["ZosmfClient", "ZosmfZcryptoClient"]
@@ -4,7 +4,7 @@ from typing import Any
4
4
  import pendulum
5
5
 
6
6
 
7
- def _parse_datetime(value: str) -> pendulum.DateTime:
7
+ def parse_datetime(value: str) -> pendulum.DateTime:
8
8
  """Parse a string and require a Pendulum ``DateTime`` result.
9
9
 
10
10
  Args:
@@ -0,0 +1,21 @@
1
+ from zosmfrestapi.exceptions.commons import ZosmfAuthError, ZosmfError
2
+ from zosmfrestapi.exceptions.authentication import ZosmfLoginError
3
+ from zosmfrestapi.exceptions.dataset import ZosmfDatasetNotFoundError
4
+ from zosmfrestapi.exceptions.software import (
5
+ ZosmfSoftwareInstanceNotFoundError,
6
+ ZosmfSoftwareManagementError,
7
+ ZosmfSoftwareManagementRequestError,
8
+ )
9
+ from zosmfrestapi.exceptions.workflow import ZosmfWorkflowBaseError, ZosmfWorkflowError
10
+
11
+ __all__ = [
12
+ "ZosmfDatasetNotFoundError",
13
+ "ZosmfError",
14
+ "ZosmfAuthError",
15
+ "ZosmfLoginError",
16
+ "ZosmfSoftwareManagementError",
17
+ "ZosmfSoftwareInstanceNotFoundError",
18
+ "ZosmfSoftwareManagementRequestError",
19
+ "ZosmfWorkflowBaseError",
20
+ "ZosmfWorkflowError",
21
+ ]
@@ -1,6 +1,6 @@
1
1
  import httpx2
2
2
 
3
- from . import ZosmfError
3
+ from zosmfrestapi.exceptions.commons import ZosmfError
4
4
 
5
5
 
6
6
  class ZosmfLoginError(ZosmfError):
@@ -1,7 +1,7 @@
1
1
  import logging
2
2
 
3
3
  import httpx2
4
- from zosmfrestapi.exceptions import ZosmfError
4
+ from zosmfrestapi.exceptions.commons import ZosmfError
5
5
 
6
6
  logger = logging.getLogger(__name__)
7
7
 
@@ -1,4 +1,4 @@
1
- from . import ZosmfError
1
+ from zosmfrestapi.exceptions.commons import ZosmfError
2
2
 
3
3
 
4
4
  class ZosmfSoftwareManagementError(ZosmfError):
@@ -1,6 +1,6 @@
1
1
  import httpx2
2
2
 
3
- from . import ZosmfError
3
+ from zosmfrestapi.exceptions.commons import ZosmfError
4
4
 
5
5
 
6
6
  class ZosmfWorkflowBaseError(ZosmfError):
@@ -0,0 +1,35 @@
1
+ from zosmfrestapi.models.authentication import LoginOk
2
+ from zosmfrestapi.models.software import (
3
+ DataSet,
4
+ Feature,
5
+ Fmid,
6
+ NonSmpeManagedDataset,
7
+ Product,
8
+ SmpeManagedDataset,
9
+ SmpeManagedDatasetZoneDddef,
10
+ SmpeManagedUnixDataset,
11
+ SoftwareInstance,
12
+ SoftwareInstanceWorkflow,
13
+ WorkflowLocation,
14
+ )
15
+ from zosmfrestapi.models.topology import Group, System
16
+ from zosmfrestapi.models.workflow import WorkflowInstance, WorkflowItem
17
+
18
+ __all__ = [
19
+ "System",
20
+ "Group",
21
+ "DataSet",
22
+ "Feature",
23
+ "Fmid",
24
+ "LoginOk",
25
+ "NonSmpeManagedDataset",
26
+ "Product",
27
+ "SmpeManagedDataset",
28
+ "SmpeManagedDatasetZoneDddef",
29
+ "SmpeManagedUnixDataset",
30
+ "SoftwareInstance",
31
+ "SoftwareInstanceWorkflow",
32
+ "WorkflowLocation",
33
+ "WorkflowInstance",
34
+ "WorkflowItem",
35
+ ]
@@ -1,11 +1,11 @@
1
1
  import logging
2
2
  import time
3
- from typing import Any
4
3
  from dataclasses import asdict
4
+ from typing import Any
5
5
 
6
6
  import pendulum
7
7
  from dacite import Config, from_dict
8
-
8
+ from zosmfrestapi import _utils
9
9
  from zosmfrestapi.exceptions.software import (
10
10
  ZosmfSoftwareInstanceNotFoundError,
11
11
  ZosmfSoftwareManagementError,
@@ -25,7 +25,6 @@ from zosmfrestapi.models.software import (
25
25
  SoftwareInstance,
26
26
  SoftwareInstanceWorkflow,
27
27
  )
28
- from zosmfrestapi.utils import _parse_datetime, remap
29
28
 
30
29
  from . import ZosmfBase
31
30
 
@@ -52,10 +51,10 @@ class SoftwareServices(ZosmfBase):
52
51
  return [
53
52
  from_dict(
54
53
  data_class=SoftwareInstance,
55
- data=remap(swi, SoftwareInstance),
54
+ data=_utils.remap(swi, SoftwareInstance),
56
55
  config=Config(
57
56
  type_hooks={
58
- pendulum.DateTime: _parse_datetime,
57
+ pendulum.DateTime: _utils.parse_datetime,
59
58
  }
60
59
  ),
61
60
  )
@@ -69,10 +68,10 @@ class SoftwareServices(ZosmfBase):
69
68
  self._raise_for_status(resp, exc_handler=ZosmfSoftwareManagementError)
70
69
  return from_dict(
71
70
  data_class=SoftwareInstance,
72
- data=remap(resp.json(), SoftwareInstance),
71
+ data=_utils.remap(resp.json(), SoftwareInstance),
73
72
  config=Config(
74
73
  type_hooks={
75
- pendulum.DateTime: _parse_datetime,
74
+ pendulum.DateTime: _utils.parse_datetime,
76
75
  list[DataSet]: lambda v: [] if v is None else v,
77
76
  list[Product]: lambda v: [] if v is None else v,
78
77
  list[NonSmpeProduct]: lambda v: [] if v is None else v,
@@ -3,6 +3,12 @@ from typing import Any
3
3
 
4
4
  import pendulum
5
5
  from dacite import Config, from_dict
6
+ from zosmfrestapi import _utils
7
+ from zosmfrestapi.exceptions.software import (
8
+ ZosmfSoftwareInstanceNotFoundError,
9
+ ZosmfSoftwareManagementError,
10
+ ZosmfSoftwareManagementRequestError,
11
+ )
6
12
  from zosmfrestapi.models.software_updates import (
7
13
  MissingFixcat,
8
14
  MissingUpdate,
@@ -10,13 +16,6 @@ from zosmfrestapi.models.software_updates import (
10
16
  UpdateProcess,
11
17
  )
12
18
 
13
- from zosmfrestapi.exceptions.software import (
14
- ZosmfSoftwareManagementError,
15
- ZosmfSoftwareInstanceNotFoundError,
16
- ZosmfSoftwareManagementRequestError,
17
- )
18
- from zosmfrestapi.utils import _parse_datetime
19
-
20
19
  from . import ZosmfBase
21
20
 
22
21
 
@@ -39,7 +38,7 @@ class SoftwareUpdatesServices(ZosmfBase):
39
38
  data=upd,
40
39
  config=Config(
41
40
  type_hooks={
42
- pendulum.DateTime: _parse_datetime,
41
+ pendulum.DateTime: _utils.parse_datetime,
43
42
  },
44
43
  convert_key=lambda k: k.replace("_", "-"),
45
44
  ),
@@ -128,7 +127,7 @@ class SoftwareUpdatesServices(ZosmfBase):
128
127
  data=process,
129
128
  config=Config(
130
129
  type_hooks={
131
- pendulum.DateTime: _parse_datetime,
130
+ pendulum.DateTime: _utils.parse_datetime,
132
131
  },
133
132
  convert_key=lambda k: k.replace("_", "-"),
134
133
  ),
@@ -397,7 +396,7 @@ class SoftwareUpdatesServices(ZosmfBase):
397
396
  data=sw_upd,
398
397
  config=Config(
399
398
  type_hooks={
400
- pendulum.DateTime: _parse_datetime,
399
+ pendulum.DateTime: _utils.parse_datetime,
401
400
  }
402
401
  ),
403
402
  )
@@ -864,7 +863,7 @@ class SoftwareUpdatesServices(ZosmfBase):
864
863
  data=process,
865
864
  config=Config(
866
865
  type_hooks={
867
- pendulum.DateTime: _parse_datetime,
866
+ pendulum.DateTime: _utils.parse_datetime,
868
867
  },
869
868
  convert_key=lambda k: k.replace("_", "-"),
870
869
  ),
@@ -1,7 +1,7 @@
1
1
  import logging
2
2
  from . import ZosmfBase
3
3
  from dacite import from_dict
4
- from zosmfrestapi.utils import remap
4
+ from zosmfrestapi import _utils
5
5
  from zosmfrestapi.models.topology import Group, System
6
6
 
7
7
  logger = logging.getLogger(__name__)
@@ -25,7 +25,7 @@ class TopologyServices(ZosmfBase):
25
25
  resp = self.http.get("/zosmf/resttopology/groups")
26
26
  self._raise_for_status(resp)
27
27
  return {
28
- item["name"]: from_dict(Group, data=remap(item, Group))
28
+ item["name"]: from_dict(Group, data=_utils.remap(item, Group))
29
29
  for item in resp.json()["items"]
30
30
  }
31
31
 
@@ -44,6 +44,6 @@ class TopologyServices(ZosmfBase):
44
44
  resp = self.http.get("/zosmf/resttopology/systems")
45
45
  self._raise_for_status(resp)
46
46
  return {
47
- item["systemName"]: from_dict(System, data=remap(item, System))
47
+ item["systemName"]: from_dict(System, data=_utils.remap(item, System))
48
48
  for item in resp.json()["items"]
49
49
  }
@@ -2,18 +2,14 @@ import time
2
2
  from typing import Any, Iterator, Literal, overload
3
3
 
4
4
  from dacite import from_dict
5
-
6
- from zosmfrestapi.exceptions.workflow import (
7
- ZosmfWorkflowBaseError,
8
- ZosmfWorkflowError,
9
- )
5
+ from zosmfrestapi import _utils
6
+ from zosmfrestapi.exceptions.workflow import ZosmfWorkflowBaseError, ZosmfWorkflowError
10
7
  from zosmfrestapi.models.workflow import (
11
8
  WorkflowArchivedListItem,
12
9
  WorkflowInstance,
13
10
  WorkflowItem,
14
11
  WorkflowListItem,
15
12
  )
16
- from zosmfrestapi.utils import remap, to_dict
17
13
 
18
14
  from . import ZosmfBase
19
15
 
@@ -67,7 +63,7 @@ class WorkflowServices(ZosmfBase):
67
63
  """
68
64
  return from_dict(
69
65
  WorkflowInstance,
70
- data=remap(
66
+ data=_utils.remap(
71
67
  self._get_workflow(workflow_id, steps=steps, variables=variables),
72
68
  WorkflowInstance,
73
69
  ),
@@ -134,7 +130,7 @@ class WorkflowServices(ZosmfBase):
134
130
  return [
135
131
  from_dict(
136
132
  WorkflowListItem,
137
- data=remap(workflow, WorkflowListItem),
133
+ data=_utils.remap(workflow, WorkflowListItem),
138
134
  )
139
135
  for workflow in resp.json()["workflows"]
140
136
  ]
@@ -159,7 +155,7 @@ class WorkflowServices(ZosmfBase):
159
155
  return [
160
156
  from_dict(
161
157
  WorkflowArchivedListItem,
162
- data=remap(archived_workflow, WorkflowArchivedListItem),
158
+ data=_utils.remap(archived_workflow, WorkflowArchivedListItem),
163
159
  )
164
160
  for archived_workflow in resp.json()["archivedWorkflows"]
165
161
  ]
@@ -185,7 +181,9 @@ class WorkflowServices(ZosmfBase):
185
181
  httpx2.RequestError: If either request fails before an HTTP response
186
182
  is received.
187
183
  """
188
- resp = self.http.post("/zosmf/workflow/rest/1.0/workflows", json=to_dict(workflow))
184
+ resp = self.http.post(
185
+ "/zosmf/workflow/rest/1.0/workflows", json=_utils.to_dict(workflow)
186
+ )
189
187
  self._raise_for_status(resp, exc_handler=ZosmfWorkflowError)
190
188
  return self.get_workflow(resp.json()["workflowKey"])
191
189
 
@@ -4,7 +4,6 @@ import ssl
4
4
  from tempfile import NamedTemporaryFile
5
5
 
6
6
  from zosmfrestapi.client import ZosmfClient
7
- from zosmfrestapi.zcrypto import _extract_key_from_pkcs12
8
7
 
9
8
 
10
9
  class ZosmfZcryptoClient(ZosmfClient):
@@ -46,6 +45,8 @@ class ZosmfZcryptoClient(ZosmfClient):
46
45
  raise RuntimeError("The zcrypto backend is only available on z/OS.")
47
46
  import py_zcrypto # pyright: ignore[reportMissingImports]
48
47
 
48
+ from zosmfrestapi.zcrypto import _extract_key_from_pkcs12
49
+
49
50
  keyring = kwargs.pop("keyring")
50
51
  label = kwargs.pop("label")
51
52
  zcrypto_obj = py_zcrypto.zcrypto()
@@ -1,146 +0,0 @@
1
- # A Python wrapper for the z/OSMF© REST API
2
-
3
- [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)
4
- [![builds.sr.ht status](https://builds.sr.ht/~ocurero/zosmfrestapi/commits/main/.build.yml.svg)](https://builds.sr.ht/~ocurero/zosmfrestapi/commits/main/.build.yml?)
5
- ![z/OS](https://img.shields.io/badge/works%20on-z/OS-8A2BE2)
6
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
- [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
8
-
9
- * Open Source: MIT License.
10
- * Website: <https://sr.ht/~ocurero/zosmfrestapi/>
11
- * Repository: <https://git.sr.ht/~ocurero/zosmfrestapi>
12
- * Changelog: <https://git.sr.ht/~ocurero/zosmfrestapi/tree/main/item/CHANGELOG.md>
13
- * Contributing: <https://git.sr.ht/~ocurero/zosmfrestapi/tree/main/item/CONTRIBUTING.md>
14
-
15
- Key features:
16
- * **Pure Python**: Package and its dependencies are 100% pure Python (no C extensions required).
17
- * **Cross-platform**: Works on Windows, Linux, macOS, and z/OS UNIX System Services.
18
- * **Flexible authentication**: Supports user/password, LTPA and JWT tokens, and mutual TLS (mTLS).
19
- * **Proxy ready**: Full support for standard HTTP/HTTPS proxies as well as authenticated proxies.
20
-
21
-
22
- Install
23
- -------
24
-
25
- **zosmfrestapi** requires Python 3.12 or newer and access to a z/OSMF server.
26
-
27
- Install the package from PyPI:
28
-
29
- ```console
30
- python -m pip install zosmfrestapi
31
- ```
32
-
33
- If you have downloaded or cloned the source code, run this from the project's
34
- root folder instead:
35
-
36
- ```console
37
- python -m pip install .
38
- ```
39
-
40
- ## First request
41
-
42
- Save this as `example.py` and run it with `python example.py`. Enter the base
43
- URL of your z/OSMF server when prompted (for example,
44
- `https://zosmf.example.com:443`). The URL should include `https://` and any
45
- required port, but not an API path such as `/zosmf`.
46
-
47
- The password is requested without displaying it and is not stored in the
48
- script. Replace the sample operation with one your z/OSMF user is authorized to
49
- perform.
50
-
51
- ```python
52
- from getpass import getpass
53
-
54
- from zosmfrestapi import ZosmfClient, ZosmfError
55
-
56
- server = input("z/OSMF server URL: ").strip().rstrip("/")
57
- username = input("User ID: ").strip()
58
- password = getpass("Password: ")
59
-
60
- try:
61
- with ZosmfClient(server, username=username, password=password) as client:
62
- for instance in client.list_swis():
63
- print(f"{instance.name} ({instance.system})")
64
- except ZosmfError as error:
65
- print(f"The z/OSMF request failed: {error}")
66
- ```
67
-
68
- The `with` block closes the network connection automatically, even if a request
69
- fails. `list_swis()` returns Python objects; the example prints each software
70
- instance's name and system. You can also query systems or read a data set. Put
71
- these calls inside the `with` block shown above, before it ends:
72
-
73
- ```python
74
- systems = client.get_systems()
75
- contents = client.read_dataset("USER.DATASET")
76
- ```
77
-
78
- These calls must be made inside the `with` block, before the client is closed.
79
- For a partitioned data set member, use a name such as
80
- `USER.PDS(MEMBER)`.
81
-
82
- ## Authentication and TLS
83
-
84
- The client uses the server's normal TLS certificate checks by default. Keep
85
- those checks enabled for routine use. The HTTP transport is HTTPX2, a fork of
86
- HTTPX; HTTPX2 uses `truststore` to integrate operating-system certificate
87
- stores when it creates its default TLS context. This package currently passes
88
- its own context, created with Python's `ssl.create_default_context()`, so the
89
- certificates available to Python are used. If the z/OSMF server's CA is not
90
- trusted in that environment, pass its certificate file with `cafile` below.
91
-
92
- | Situation | Client option |
93
- | --- | --- |
94
- | User ID and password | `username="...", password="..."` |
95
- | Client certificate and key in separate files | `cert=("client.crt", "client.key")` |
96
- | Client certificate and key in one PEM file | `cert="client.pem"` |
97
- | Internal certificate authority | `cafile="company-ca.pem"` |
98
- | Existing LTPA or JWT token | `ltpa_token="..."` or `jwt_token="..."` |
99
- | Network proxy | `proxy="http://proxy.example.com:8080"` |
100
-
101
- For example, to trust an internal certificate authority, pass `cafile` when
102
- creating the client:
103
-
104
- ```python
105
- with ZosmfClient(server, username=username, password=password,
106
- cafile="company-ca.pem") as client:
107
- systems = client.get_systems()
108
- ```
109
-
110
- Avoid putting passwords or tokens directly in scripts, committing them to
111
- version control, or sharing them in logs. The `insecure=True` option disables
112
- TLS certificate verification; use it only for temporary diagnostics, never as
113
- a production fix. It cannot be combined with `cert` or `cafile`.
114
-
115
- ## What you can do
116
-
117
- The client provides synchronous methods for:
118
-
119
- * Authentication (`authenticate`).
120
- * z/OSMF groups and systems (`get_groups`, `get_systems`).
121
- * Data sets (`read_dataset`).
122
- * Software instances and SMP/E information (`list_swis`, `get_swi_by_name`,
123
- `get_swi_by_uuid`, and related query methods).
124
- * Workflows (list, inspect, create, start, wait for, cancel, and archive).
125
- * Software updates (search, inspect, start, monitor, and cancel).
126
-
127
- Some operations change z/OSMF state. Check the method documentation and make
128
- sure your account has the required permissions before using them.
129
-
130
- ## Troubleshooting
131
-
132
- * **Python version error:** install Python 3.12 or newer, then recreate the
133
- virtual environment with that interpreter.
134
- * **401 / unauthorized:** check the server URL, user ID, password or token, and
135
- whether the account is authorized for the requested API.
136
- * **Certificate verification error:** ask your z/OSMF administrator for the
137
- correct CA certificate and pass its path with `cafile`.
138
- * **Connection or timeout error:** check that the server and port are reachable
139
- from your machine and that any required proxy is configured.
140
- * **PowerShell will not activate the virtual environment:** use the Python
141
- executable inside `.venv\Scripts\python.exe` to run commands, or follow your
142
- organization's PowerShell policy guidance. Do not change the machine-wide
143
- execution policy just to install this package.
144
-
145
- For the complete API, parameters, and return types, see the docstrings in the
146
- package source and the project website.
@@ -1,93 +0,0 @@
1
- """Synchronous Python client for the z/OSMF REST API.
2
-
3
- The package root re-exports :class:`ZosmfClient`, :class:`ZosmfZcryptoClient`,
4
- response models, and public exceptions. Create one client per server/configuration and
5
- use it as a context manager to close the shared HTTP session when finished.
6
- """
7
-
8
- from zosmfrestapi.client import ZosmfClient
9
- from zosmfrestapi.exceptions import ZosmfAuthError, ZosmfError
10
- from zosmfrestapi.exceptions.authentication import ZosmfLoginError
11
- from zosmfrestapi.exceptions.dataset import ZosmfDatasetNotFoundError
12
- from zosmfrestapi.exceptions.software import (
13
- ZosmfSoftwareInstanceNotFoundError,
14
- ZosmfSoftwareManagementError,
15
- ZosmfSoftwareManagementRequestError,
16
- )
17
- from zosmfrestapi.exceptions.workflow import ZosmfWorkflowBaseError, ZosmfWorkflowError
18
- from zosmfrestapi.models.authentication import LoginOk
19
- from zosmfrestapi.models.software import (
20
- CsiEntry,
21
- DataSet,
22
- Feature,
23
- Fmid,
24
- NonSmpeManagedDataset,
25
- Product,
26
- SmpeManagedDataset,
27
- SmpeManagedDatasetZoneDddef,
28
- SmpeManagedUnixDataset,
29
- SoftwareInstance,
30
- SoftwareInstanceWorkflow,
31
- WorkflowLocation,
32
- )
33
- from zosmfrestapi.models.software_updates import (
34
- MissingFixcat,
35
- MissingUpdate,
36
- MissingUpdateResolver,
37
- SoftwareUpdate,
38
- SoftwareUpdateZone,
39
- UpdateErrorResults,
40
- UpdateProcess,
41
- UpdateResult,
42
- UpdateSelection,
43
- )
44
- from zosmfrestapi.models.topology import Group, System
45
- from zosmfrestapi.models.workflow import (
46
- WorkflowArchivedListItem,
47
- WorkflowInstance,
48
- WorkflowItem,
49
- WorkflowListItem,
50
- )
51
- from zosmfrestapi.zcrypto_client import ZosmfZcryptoClient
52
-
53
- __all__ = [
54
- "ZosmfClient",
55
- "ZosmfZcryptoClient",
56
- "LoginOk",
57
- "ZosmfDatasetNotFoundError",
58
- "ZosmfError",
59
- "ZosmfAuthError",
60
- "ZosmfLoginError",
61
- "System",
62
- "Group",
63
- "CsiEntry",
64
- "DataSet",
65
- "Feature",
66
- "Fmid",
67
- "NonSmpeManagedDataset",
68
- "Product",
69
- "SmpeManagedDataset",
70
- "SmpeManagedDatasetZoneDddef",
71
- "SmpeManagedUnixDataset",
72
- "SoftwareInstance",
73
- "SoftwareInstanceWorkflow",
74
- "WorkflowLocation",
75
- "ZosmfSoftwareManagementError",
76
- "ZosmfSoftwareInstanceNotFoundError",
77
- "ZosmfSoftwareManagementRequestError",
78
- "MissingFixcat",
79
- "MissingUpdate",
80
- "MissingUpdateResolver",
81
- "SoftwareUpdate",
82
- "SoftwareUpdateZone",
83
- "UpdateErrorResults",
84
- "UpdateProcess",
85
- "UpdateResult",
86
- "UpdateSelection",
87
- "WorkflowArchivedListItem",
88
- "WorkflowInstance",
89
- "WorkflowItem",
90
- "WorkflowListItem",
91
- "ZosmfWorkflowBaseError",
92
- "ZosmfWorkflowError",
93
- ]
File without changes
File without changes