Skip to content

Commit 70a85ac

Browse files
authored
Dev/eccles/iam endpoints (#24)
* Easier succinct method of adding endpoints. Problem: Adding endpoints explicitly required more code. Solution: Using __getattr__ results in succinct easier-to-read code. Signed-off-by: Paul Hewlett <phewlett76@gmail.com> * Add IAM endpoints Problem: The IAM endpoints are not present. Solution: IAM endpoints access_policies and subjects are added with docs and unittests. Signed-off-by: Paul Hewlett <phewlett76@gmail.co> * Remove unnecessary compreehansions Problem: Uasge of [a for a in arch.list()] is unnecessary. Solution: Replace with list(arch.list()) ss it is more efficient. Signed-off-by: Paul Hewlett <phewlett76@gmail.com>
1 parent 2df95af commit 70a85ac

37 files changed

Lines changed: 2108 additions & 247 deletions

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,21 @@ If ok run the unittests:
176176
task unittests
177177
```
178178

179+
If you have access to an archivist instance then one can run functional tests. The URL
180+
and authtoken are required. The authtoken must be stored in a file in the credentials
181+
subdirectory credentials/authtoken (say).
182+
183+
These tests will create artefacts on the archivist instance so it is **not** recommended that
184+
they be run in a production environment.
185+
186+
Set 2 environment variables and execute:
187+
188+
```bash
189+
export TEST_ARCHIVIST="https://rkvst.poc.jitsuin.io"
190+
export TEST_AUTHTOKEN=credentials/authtoken
191+
task functests
192+
```
193+
179194
#### Testing Other Python Versions
180195

181196
##### Python 3.6

Taskfile.yml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ tasks:
3434
deps: [about]
3535
cmds:
3636
- ./scripts/builder.sh python3 --version
37-
- ./scripts/builder.sh pycodestyle --format=pylint archivist unittests examples
38-
- ./scripts/builder.sh python3 -m pylint --rcfile=pylintrc archivist unittests examples
37+
- ./scripts/builder.sh pycodestyle --format=pylint archivist functests unittests examples
38+
- ./scripts/builder.sh python3 -m pylint --rcfile=pylintrc archivist functests unittests examples
3939

4040
clean:
4141
desc: Clean git repo
@@ -53,8 +53,14 @@ tasks:
5353
desc: Format code using black
5454
deps: [about]
5555
cmds:
56-
- ./scripts/builder.sh black archivist examples unittests
56+
- ./scripts/builder.sh black archivist examples functests unittests
5757

58+
functests:
59+
desc: Run functests - requires an archivist instance and a authtoken
60+
deps: [about]
61+
cmds:
62+
- ./scripts/builder.sh ./scripts/functests.sh
63+
5864
publish:
5965
desc: pubish wheel package (will require username and password)
6066
deps: [about]

archivist/access_policies.py

Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
"""Access_Policies interface
2+
3+
Access to the access_policies endpoint.
4+
5+
The user is not expected to use this class directly. It is an attribute of the
6+
:class:`Archivist` class.
7+
8+
For example instantiate an Archivist instance and execute the methods of the class:
9+
10+
.. code-block:: python
11+
12+
with open(".auth_token", mode="r") as tokenfile:
13+
authtoken = tokenfile.read().strip()
14+
15+
# Initialize connection to Archivist
16+
arch = Archivist(
17+
"https://rkvst.poc.jitsuin.io",
18+
auth=authtoken,
19+
)
20+
asset = arch.access_policies.create(...)
21+
22+
"""
23+
24+
from copy import deepcopy
25+
26+
from .constants import (
27+
SEP,
28+
ACCESS_POLICIES_SUBPATH,
29+
ACCESS_POLICIES_LABEL,
30+
ASSETS_LABEL,
31+
)
32+
33+
from .assets import Asset
34+
35+
DEFAULT_PAGE_SIZE = 500
36+
37+
38+
class _AccessPoliciesClient:
39+
"""AccessPoliciesClient
40+
41+
Access to access_policies entitiies using CRUD interface. This class is usually
42+
accessed as an attribute of the Archivist class.
43+
44+
Args:
45+
archivist (Archivist): :class:`Archivist` instance
46+
47+
"""
48+
49+
def __init__(self, archivist):
50+
self._archivist = archivist
51+
52+
def create(self, props, filters, access_permissions):
53+
"""Create access policy
54+
55+
Creates access policy with defined attributes.
56+
57+
Args:
58+
props (dict): properties of created access policy.
59+
filters (list): assets filters
60+
access permissions (list): list of access permissions
61+
62+
Returns:
63+
:class:`AccessPolicy` instance
64+
65+
"""
66+
return self.create_from_data(
67+
self.__query(props, filters=filters, access_permissions=access_permissions),
68+
)
69+
70+
def create_from_data(self, data):
71+
"""Create access policy
72+
73+
Creates access policy with request body from data stream.
74+
Suitable for reading data from a file using json.load or yaml.load
75+
76+
Args:
77+
data (dict): request body of access policy.
78+
79+
Returns:
80+
:class:`AccessPolicy` instance
81+
82+
"""
83+
return AccessPolicy(
84+
**self._archivist.post(
85+
f"{ACCESS_POLICIES_SUBPATH}/{ACCESS_POLICIES_LABEL}",
86+
data,
87+
)
88+
)
89+
90+
def read(self, identity):
91+
"""Read Access Policy
92+
93+
Reads access policy.
94+
95+
Args:
96+
identity (str): access_policies identity e.g. access_policies/xxxxxxxxxxxxxxxxxxxxxxx
97+
98+
Returns:
99+
:class:`AccessPolicy` instance
100+
101+
"""
102+
return AccessPolicy(
103+
**self._archivist.get(
104+
ACCESS_POLICIES_SUBPATH,
105+
identity,
106+
)
107+
)
108+
109+
def update(self, identity, props=None, filters=None, access_permissions=None):
110+
"""Update Access Policy
111+
112+
Update access policy.
113+
114+
Args:
115+
identity (str): access_policies identity e.g. access_policies/xxxxxxxxxxxxxxxxxxxxxxx
116+
props (dict): properties of created access policy.
117+
filters (list): assets filters
118+
access permissions (list): list of access permissions
119+
120+
Returns:
121+
:class:`AccessPolicy` instance
122+
123+
"""
124+
return AccessPolicy(
125+
**self._archivist.patch(
126+
ACCESS_POLICIES_SUBPATH,
127+
identity,
128+
self.__query(
129+
props, filters=filters, access_permissions=access_permissions
130+
),
131+
)
132+
)
133+
134+
def delete(self, identity):
135+
"""Delete Access Policy
136+
137+
Deletes access policy.
138+
139+
Args:
140+
identity (str): access_policies identity e.g. access_policies/xxxxxxxxxxxxxxxxxxxxxxx
141+
142+
Returns:
143+
:class:`AccessPolicy` instance - empty?
144+
145+
"""
146+
return self._archivist.delete(ACCESS_POLICIES_SUBPATH, identity)
147+
148+
@staticmethod
149+
def __query(props, *, filters=None, access_permissions=None):
150+
query = deepcopy(props) if props else {}
151+
if filters is not None:
152+
query["filters"] = filters
153+
154+
if access_permissions is not None:
155+
query["access_permissions"] = access_permissions
156+
157+
return query
158+
159+
def count(self, *, display_name=None):
160+
"""Count access policies.
161+
162+
Counts number of access policies that match criteria.
163+
164+
Args:
165+
display_name (str): display name (optional0
166+
167+
Returns:
168+
integer count of access policies.
169+
170+
"""
171+
query = {"display_name": display_name} if display_name is not None else None
172+
return self._archivist.count(
173+
f"{ACCESS_POLICIES_SUBPATH}/{ACCESS_POLICIES_LABEL}",
174+
query=query,
175+
)
176+
177+
def list(
178+
self,
179+
*,
180+
page_size=DEFAULT_PAGE_SIZE,
181+
display_name=None,
182+
):
183+
"""List access policies.
184+
185+
List access policiess that match criteria.
186+
187+
Args:
188+
display_name (str): display name (optional0
189+
page_size (int): optional page size. (Rarely used).
190+
191+
Returns:
192+
iterable that returns :class:`AccessPolicy` instances
193+
194+
"""
195+
query = {"display_name": display_name} if display_name is not None else None
196+
return (
197+
AccessPolicy(**a)
198+
for a in self._archivist.list(
199+
f"{ACCESS_POLICIES_SUBPATH}/{ACCESS_POLICIES_LABEL}",
200+
ACCESS_POLICIES_LABEL,
201+
page_size=page_size,
202+
query=query,
203+
)
204+
)
205+
206+
# additional queries on different endpoints
207+
def count_matching_assets(self, access_policy_id):
208+
"""Count assets that match access_policy.
209+
210+
Counts number of assets that match an access_polocy.
211+
212+
Args:
213+
access_policy_id (str): e.g. access_policies/xxxxxxxxxxxxxxx
214+
215+
Returns:
216+
integer count of assets.
217+
218+
"""
219+
return self._archivist.count(
220+
SEP.join((ACCESS_POLICIES_SUBPATH, access_policy_id, ASSETS_LABEL)),
221+
)
222+
223+
def list_matching_assets(
224+
self,
225+
access_policy_id,
226+
*,
227+
page_size=DEFAULT_PAGE_SIZE,
228+
):
229+
"""List matching assets.
230+
231+
List assets that match access policy.
232+
233+
Args:
234+
access_policy_id (str): e.g. access_policies/xxxxxxxxxxxxxxx
235+
page_size (int): optional page size. (Rarely used).
236+
237+
Returns:
238+
iterable that returns :class:`Asset` instances
239+
240+
"""
241+
return (
242+
Asset(**a)
243+
for a in self._archivist.list(
244+
SEP.join((ACCESS_POLICIES_SUBPATH, access_policy_id, ASSETS_LABEL)),
245+
ASSETS_LABEL,
246+
page_size=page_size,
247+
)
248+
)
249+
250+
def count_matching_access_policies(self, asset_id):
251+
"""Count access policies that match asset.
252+
253+
Counts number of access policies that match asset.
254+
255+
Args:
256+
asset_id (str): e.g. assets/xxxxxxxxxxxxxxx
257+
258+
Returns:
259+
integer count of access policies.
260+
261+
"""
262+
return self._archivist.count(
263+
SEP.join((ACCESS_POLICIES_SUBPATH, asset_id, ACCESS_POLICIES_LABEL)),
264+
)
265+
266+
def list_matching_access_policies(self, asset_id, *, page_size=DEFAULT_PAGE_SIZE):
267+
"""List matching access policies.
268+
269+
List access policies that match asset.
270+
271+
Args:
272+
asset_id (str): e.g. assets/xxxxxxxxxxxxxxx
273+
page_size (int): optional page size. (Rarely used).
274+
275+
Returns:
276+
iterable that returns :class:`AccessPolicy` instances
277+
278+
"""
279+
return (
280+
AccessPolicy(**a)
281+
for a in self._archivist.list(
282+
SEP.join((ACCESS_POLICIES_SUBPATH, asset_id, ACCESS_POLICIES_LABEL)),
283+
ACCESS_POLICIES_LABEL,
284+
page_size=page_size,
285+
)
286+
)
287+
288+
289+
class AccessPolicy(dict):
290+
"""AccessPolicy object"""

0 commit comments

Comments
 (0)