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.
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/PKG-INFO +95 -49
- zosmfrestapi-0.3.1/README.md +191 -0
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/pyproject.toml +29 -20
- zosmfrestapi-0.3.1/zosmfrestapi/__init__.py +11 -0
- zosmfrestapi-0.2.1/zosmfrestapi/utils.py → zosmfrestapi-0.3.1/zosmfrestapi/_utils.py +1 -1
- zosmfrestapi-0.3.1/zosmfrestapi/exceptions/__init__.py +21 -0
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/exceptions/authentication.py +1 -1
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/exceptions/dataset.py +1 -1
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/exceptions/software.py +1 -1
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/exceptions/workflow.py +1 -1
- zosmfrestapi-0.3.1/zosmfrestapi/models/__init__.py +35 -0
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/services/software.py +6 -7
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/services/software_updates.py +10 -11
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/services/topology.py +3 -3
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/services/workflow.py +8 -10
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/zcrypto_client.py +2 -1
- zosmfrestapi-0.2.1/README.md +0 -146
- zosmfrestapi-0.2.1/zosmfrestapi/__init__.py +0 -93
- zosmfrestapi-0.2.1/zosmfrestapi/models/__init__.py +0 -0
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/LICENSE +0 -0
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/client.py +0 -0
- /zosmfrestapi-0.2.1/zosmfrestapi/exceptions/__init__.py → /zosmfrestapi-0.3.1/zosmfrestapi/exceptions/commons.py +0 -0
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/models/authentication.py +0 -0
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/models/software.py +0 -0
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/models/software_updates.py +0 -0
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/models/topology.py +0 -0
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/models/workflow.py +0 -0
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/py.typed +0 -0
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/services/__init__.py +0 -0
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/services/authentication.py +0 -0
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/services/dataset.py +0 -0
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/testing/__init__.py +0 -0
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/testing/authentication.py +0 -0
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/testing/helpers.py +0 -0
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/testing/software.py +0 -0
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/testing/software_updates.py +0 -0
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/testing/topology.py +0 -0
- {zosmfrestapi-0.2.1 → zosmfrestapi-0.3.1}/zosmfrestapi/testing/workflows.py +0 -0
- {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.
|
|
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
|
|
27
|
+
# A Python wrapper for the z/OSMF REST API
|
|
27
28
|
|
|
28
29
|
[](https://www.repostatus.org/#active)
|
|
29
30
|
[](https://builds.sr.ht/~ocurero/zosmfrestapi/commits/main/.build.yml?)
|
|
30
|
-
](https://opensource.org/licenses/MIT)
|
|
31
|
+
[](https://builds.sr.ht/~ocurero/zosmfrestapi/commits/main/.build.yml?)
|
|
32
32
|
[](https://github.com/psf/black)
|
|
33
|
+
[](https://opensource.org/licenses/MIT)
|
|
34
|
+

|
|
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
|
+

|
|
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
|
-
##
|
|
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
|
-
|
|
82
|
-
username = input("User ID: ").strip()
|
|
83
|
-
password = getpass("Password: ")
|
|
71
|
+
from zosmfrestapi import ZosmfClient
|
|
84
72
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
+

|
|
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
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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(
|
|
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
|
-
|
|
136
|
-
|
|
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
|
-
|
|
164
|
+
## Supported APIs
|
|
143
165
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
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
|
+
[](https://www.repostatus.org/#active)
|
|
4
|
+
[](https://builds.sr.ht/~ocurero/zosmfrestapi/commits/main/.build.yml?)
|
|
5
|
+
[](https://builds.sr.ht/~ocurero/zosmfrestapi/commits/main/.build.yml?)
|
|
6
|
+
[](https://github.com/psf/black)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+

|
|
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
|
+

|
|
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
|
+

|
|
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.
|
|
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
|
-
|
|
66
|
+
[tool.poe.groups.quality.tasks.format]
|
|
67
|
+
help = "Format code acording to black."
|
|
68
|
+
cmd = "black zosmfrestapi tests"
|
|
72
69
|
|
|
73
|
-
|
|
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
|
-
|
|
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
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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"]
|
|
@@ -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
|
+
]
|
|
@@ -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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
|
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(
|
|
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()
|
zosmfrestapi-0.2.1/README.md
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
# A Python wrapper for the z/OSMF© REST API
|
|
2
|
-
|
|
3
|
-
[](https://www.repostatus.org/#active)
|
|
4
|
-
[](https://builds.sr.ht/~ocurero/zosmfrestapi/commits/main/.build.yml?)
|
|
5
|
-

|
|
6
|
-
[](https://opensource.org/licenses/MIT)
|
|
7
|
-
[](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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|