okdata-cli 1.6.0__tar.gz → 2.0.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.
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/PKG-INFO +3 -4
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/README.md +2 -3
- okdata-cli-2.0.1/okdata/cli/__init__.py +1 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/__main__.py +2 -3
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/command.py +21 -13
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/commands/datasets/datasets.py +11 -3
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/commands/pubreg/pubreg.py +39 -61
- okdata-cli-2.0.1/okdata/cli/commands/teams/teams.py +174 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/data/output-format/datasets_copy_file_config.json +1 -1
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/output.py +0 -25
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata_cli.egg-info/PKG-INFO +3 -4
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata_cli.egg-info/SOURCES.txt +0 -9
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/setup.py +1 -1
- okdata-cli-1.6.0/okdata/cli/commands/__init__.py +0 -0
- okdata-cli-1.6.0/okdata/cli/commands/pipelines/__init__.py +0 -3
- okdata-cli-1.6.0/okdata/cli/commands/pipelines/inputs.py +0 -66
- okdata-cli-1.6.0/okdata/cli/commands/pipelines/instances.py +0 -111
- okdata-cli-1.6.0/okdata/cli/commands/pipelines/pipelines.py +0 -102
- okdata-cli-1.6.0/okdata/cli/commands/pipelines/schemas.py +0 -68
- okdata-cli-1.6.0/okdata/cli/commands/teams/teams.py +0 -210
- okdata-cli-1.6.0/okdata/cli/data/output-format/pipelines_config.json +0 -6
- okdata-cli-1.6.0/okdata/cli/data/output-format/pipelines_instances_config.json +0 -14
- okdata-cli-1.6.0/okdata/cli/data/output-format/pipelines_instances_inputs_config.json +0 -14
- okdata-cli-1.6.0/okdata/cli/data/output-format/pipelines_instances_schemas_config.json +0 -6
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/LICENSE +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/__init__.py +0 -0
- {okdata-cli-1.6.0/okdata/cli → okdata-cli-2.0.1/okdata/cli/commands}/__init__.py +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/commands/datasets/__init__.py +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/commands/datasets/questions.py +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/commands/datasets/validators.py +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/commands/datasets/wizards.py +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/commands/permissions.py +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/commands/pubreg/__init__.py +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/commands/pubreg/client.py +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/commands/pubreg/questions.py +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/commands/pubreg/wizards.py +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/commands/status.py +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/commands/teams/questions.py +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/commands/teams/util.py +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/commands/teams/wizards.py +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/commands/wizard.py +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/data/output-format/datasets_config.json +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/data/output-format/datasets_copy_file_config_2.json +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/data/output-format/datasets_dataset_config.json +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/data/output-format/datasets_dataset_version_config.json +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/data/output-format/datasets_dataset_version_edition_config.json +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/data/output-format/datasets_dataset_version_edition_distributions_config.json +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/data/output-format/datasets_dataset_versions_config.json +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/data/output-format/my_permissions_config.json +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/data/output-format/permissions_config.json +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/data/output-format/pubreg_audit_log_config.json +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/data/output-format/pubreg_clients_config.json +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/data/output-format/pubreg_multiple_client_keys_config.json +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/data/output-format/pubreg_single_client_keys_config.json +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/data/output-format/status_config.json +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/data/output-format/status_history_config.json +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/data/output-format/team_members_config.json +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/data/output-format/teams_config.json +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/date.py +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata/cli/io.py +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata_cli.egg-info/dependency_links.txt +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata_cli.egg-info/entry_points.txt +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata_cli.egg-info/namespace_packages.txt +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata_cli.egg-info/requires.txt +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/okdata_cli.egg-info/top_level.txt +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/pyproject.toml +0 -0
- {okdata-cli-1.6.0 → okdata-cli-2.0.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: okdata-cli
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.1
|
|
4
4
|
Summary: CLI for services provided by Oslo Origo
|
|
5
5
|
Home-page: https://github.com/oslokommune/okdata-cli/
|
|
6
6
|
Author: Oslo Origo
|
|
@@ -24,8 +24,7 @@ Okdata CLI provides a unified interface to data services for Oslo Origo teams.
|
|
|
24
24
|
|
|
25
25
|
* [Install](doc/install.md)
|
|
26
26
|
* [Configuration](doc/configuration.md)
|
|
27
|
-
* [Datasets](doc/datasets.md)
|
|
28
|
-
* [Permissions](doc/permissions.md)
|
|
29
|
-
* [Pipelines](doc/pipelines.md)
|
|
30
27
|
* [Public registers](doc/pubreg.md)
|
|
31
28
|
* [Teams](doc/teams.md)
|
|
29
|
+
* [Datasets](doc/datasets.md)
|
|
30
|
+
* [Permissions](doc/permissions.md)
|
|
@@ -4,8 +4,7 @@ Okdata CLI provides a unified interface to data services for Oslo Origo teams.
|
|
|
4
4
|
|
|
5
5
|
* [Install](doc/install.md)
|
|
6
6
|
* [Configuration](doc/configuration.md)
|
|
7
|
-
* [Datasets](doc/datasets.md)
|
|
8
|
-
* [Permissions](doc/permissions.md)
|
|
9
|
-
* [Pipelines](doc/pipelines.md)
|
|
10
7
|
* [Public registers](doc/pubreg.md)
|
|
11
8
|
* [Teams](doc/teams.md)
|
|
9
|
+
* [Datasets](doc/datasets.md)
|
|
10
|
+
* [Permissions](doc/permissions.md)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
MAINTAINER = "Dataspeilet"
|
|
@@ -5,10 +5,10 @@ from keycloak.exceptions import KeycloakGetError
|
|
|
5
5
|
from okdata.sdk.exceptions import ApiAuthenticateError
|
|
6
6
|
from requests.exceptions import RequestException
|
|
7
7
|
|
|
8
|
+
from okdata.cli import MAINTAINER
|
|
8
9
|
from okdata.cli.command import BaseCommand
|
|
9
10
|
from okdata.cli.commands.datasets import DatasetsCommand
|
|
10
11
|
from okdata.cli.commands.permissions import PermissionsCommand
|
|
11
|
-
from okdata.cli.commands.pipelines import Pipelines
|
|
12
12
|
from okdata.cli.commands.pubreg import PubregCommand
|
|
13
13
|
from okdata.cli.commands.status import StatusCommand
|
|
14
14
|
from okdata.cli.commands.teams.teams import TeamsCommand
|
|
@@ -33,7 +33,7 @@ def main():
|
|
|
33
33
|
else:
|
|
34
34
|
instance.print(
|
|
35
35
|
"A server error occurred. Please try again, or contact "
|
|
36
|
-
"
|
|
36
|
+
f"{MAINTAINER} if the problem persists.",
|
|
37
37
|
)
|
|
38
38
|
except ApiAuthenticateError:
|
|
39
39
|
instance.print(
|
|
@@ -69,7 +69,6 @@ def get_command_class(argv):
|
|
|
69
69
|
commands = {
|
|
70
70
|
"datasets": DatasetsCommand,
|
|
71
71
|
"permissions": PermissionsCommand,
|
|
72
|
-
"pipelines": Pipelines,
|
|
73
72
|
"pubreg": PubregCommand,
|
|
74
73
|
"status": StatusCommand,
|
|
75
74
|
"teams": TeamsCommand,
|
|
@@ -13,7 +13,7 @@ BASE_COMMAND_OPTIONS = """
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class BaseCommand:
|
|
16
|
-
version = "
|
|
16
|
+
version = "2.0.1"
|
|
17
17
|
# TODO: Can use `importlib` in Python 3.8 and up instead of hard coding the
|
|
18
18
|
# version here:
|
|
19
19
|
#
|
|
@@ -24,7 +24,6 @@ class BaseCommand:
|
|
|
24
24
|
usage:
|
|
25
25
|
okdata datasets [options]
|
|
26
26
|
okdata permissions [options]
|
|
27
|
-
okdata pipelines [options]
|
|
28
27
|
okdata pubreg [options]
|
|
29
28
|
okdata status [options]
|
|
30
29
|
okdata teams [options]
|
|
@@ -33,7 +32,6 @@ usage:
|
|
|
33
32
|
Commands available:
|
|
34
33
|
datasets
|
|
35
34
|
permissions
|
|
36
|
-
pipelines
|
|
37
35
|
pubreg
|
|
38
36
|
status
|
|
39
37
|
teams
|
|
@@ -125,7 +123,7 @@ Options:{BASE_COMMAND_OPTIONS}
|
|
|
125
123
|
print(self.__doc__, end="")
|
|
126
124
|
|
|
127
125
|
def print_error_response(self, response_body):
|
|
128
|
-
if
|
|
126
|
+
if not isinstance(response_body, dict):
|
|
129
127
|
print(response_body)
|
|
130
128
|
return
|
|
131
129
|
|
|
@@ -135,19 +133,29 @@ Options:{BASE_COMMAND_OPTIONS}
|
|
|
135
133
|
print(json.dumps(response_body))
|
|
136
134
|
else:
|
|
137
135
|
try:
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
136
|
+
print(
|
|
137
|
+
_format_error_message(
|
|
138
|
+
response_body["message"], response_body.get("errors")
|
|
139
|
+
)
|
|
141
140
|
)
|
|
142
|
-
print(feedback)
|
|
143
141
|
except KeyError:
|
|
144
142
|
self.log.debug("Got unexpected response body from api.")
|
|
145
143
|
print(response_body)
|
|
146
144
|
|
|
147
145
|
|
|
148
|
-
def
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
feedback += f"\nCause:\n\t{errors}"
|
|
146
|
+
def _format_error_message(message, errors=None):
|
|
147
|
+
msg = f"An error occurred: {message}"
|
|
148
|
+
sep = "\n - "
|
|
152
149
|
|
|
153
|
-
|
|
150
|
+
if isinstance(errors, list):
|
|
151
|
+
msg += "\nCause{}:{}{}".format(
|
|
152
|
+
"s" if len(errors) > 1 else "",
|
|
153
|
+
sep,
|
|
154
|
+
sep.join(
|
|
155
|
+
err.get("msg", "") if isinstance(err, dict) else err for err in errors
|
|
156
|
+
),
|
|
157
|
+
)
|
|
158
|
+
elif errors:
|
|
159
|
+
msg += f"\nCause:{sep}{errors}"
|
|
160
|
+
|
|
161
|
+
return msg
|
|
@@ -246,8 +246,7 @@ Options:{BASE_COMMAND_OPTIONS}
|
|
|
246
246
|
except HTTPError as he:
|
|
247
247
|
if he.response.status_code == 404:
|
|
248
248
|
return self._auto_create_edition(dataset_id, version)
|
|
249
|
-
|
|
250
|
-
raise he
|
|
249
|
+
raise
|
|
251
250
|
|
|
252
251
|
# #################################### #
|
|
253
252
|
# Distribution
|
|
@@ -351,7 +350,16 @@ Options:{BASE_COMMAND_OPTIONS}
|
|
|
351
350
|
"trace_id": res["trace_id"],
|
|
352
351
|
}
|
|
353
352
|
out.add_row(data)
|
|
354
|
-
self.print(
|
|
353
|
+
self.print(
|
|
354
|
+
"\n".join(
|
|
355
|
+
[
|
|
356
|
+
f"Uploaded file to dataset: {dataset_id}",
|
|
357
|
+
str(out),
|
|
358
|
+
"\nYou can check the data processing status by running:\n",
|
|
359
|
+
f" okdata status {res['trace_id']}",
|
|
360
|
+
]
|
|
361
|
+
)
|
|
362
|
+
)
|
|
355
363
|
|
|
356
364
|
def download_files(self, source, target):
|
|
357
365
|
dataset_id, version, edition = self._dataset_components_from_uri(source)
|
|
@@ -3,8 +3,8 @@ from datetime import datetime
|
|
|
3
3
|
from operator import itemgetter
|
|
4
4
|
|
|
5
5
|
from okdata.sdk.team.client import TeamClient
|
|
6
|
-
from requests.exceptions import HTTPError
|
|
7
6
|
|
|
7
|
+
from okdata.cli import MAINTAINER
|
|
8
8
|
from okdata.cli.command import BASE_COMMAND_OPTIONS, BaseCommand
|
|
9
9
|
from okdata.cli.commands.pubreg.client import PubregClient
|
|
10
10
|
from okdata.cli.commands.pubreg.questions import NoClientsError, NoKeysError
|
|
@@ -72,7 +72,7 @@ Options:{BASE_COMMAND_OPTIONS}
|
|
|
72
72
|
except NoTeamError:
|
|
73
73
|
self.print(
|
|
74
74
|
"We haven't yet registered you as member of any Origo team. "
|
|
75
|
-
"Please contact
|
|
75
|
+
f"Please contact {MAINTAINER} to get it done."
|
|
76
76
|
)
|
|
77
77
|
return
|
|
78
78
|
|
|
@@ -88,22 +88,18 @@ Options:{BASE_COMMAND_OPTIONS}
|
|
|
88
88
|
f"scopes {scopes}."
|
|
89
89
|
)
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
f"""
|
|
91
|
+
self.print("Creating client...")
|
|
92
|
+
response = self.pubreg_client.create_client(
|
|
93
|
+
team_id, provider_id, integration, scopes, env
|
|
94
|
+
)
|
|
95
|
+
client_name = response["client_name"]
|
|
96
|
+
self.print(
|
|
97
|
+
f"""
|
|
99
98
|
Done! Created a new client '{client_name}'.
|
|
100
99
|
You may now go ahead and create a key for it by running:
|
|
101
100
|
|
|
102
101
|
okdata pubreg create-key"""
|
|
103
|
-
|
|
104
|
-
except HTTPError as e:
|
|
105
|
-
message = e.response.json()["message"]
|
|
106
|
-
self.print(f"Something went wrong: {message}")
|
|
102
|
+
)
|
|
107
103
|
|
|
108
104
|
def list_clients(self):
|
|
109
105
|
config = list_clients_wizard()
|
|
@@ -135,34 +131,28 @@ You may now go ahead and create a key for it by running:
|
|
|
135
131
|
),
|
|
136
132
|
)
|
|
137
133
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
env, client_id, aws_account, aws_region
|
|
142
|
-
)
|
|
143
|
-
deleted_ssm_params = res["deleted_ssm_params"]
|
|
144
|
-
self.print("\nDone! The client is deleted and will no longer work.")
|
|
145
|
-
|
|
146
|
-
if delete_from_aws:
|
|
147
|
-
if deleted_ssm_params:
|
|
148
|
-
self.print(
|
|
149
|
-
"\nThe following {} deleted from SSM:".format(
|
|
150
|
-
"parameter was"
|
|
151
|
-
if len(deleted_ssm_params) == 1
|
|
152
|
-
else "parameters were"
|
|
153
|
-
)
|
|
154
|
-
)
|
|
155
|
-
for param in deleted_ssm_params:
|
|
156
|
-
self.print(f"- {param}")
|
|
157
|
-
else:
|
|
158
|
-
self.print(
|
|
159
|
-
"However the key secrets couldn't be deleted from SSM "
|
|
160
|
-
"as requested."
|
|
161
|
-
)
|
|
134
|
+
self.print(f"Deleting client '{client_name}' [{env}]...")
|
|
135
|
+
res = self.pubreg_client.delete_client(env, client_id, aws_account, aws_region)
|
|
136
|
+
deleted_ssm_params = res["deleted_ssm_params"]
|
|
162
137
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
138
|
+
self.print("\nDone! The client is deleted and will no longer work.")
|
|
139
|
+
|
|
140
|
+
if delete_from_aws:
|
|
141
|
+
if deleted_ssm_params:
|
|
142
|
+
self.print(
|
|
143
|
+
"\nThe following {} deleted from SSM:".format(
|
|
144
|
+
"parameter was"
|
|
145
|
+
if len(deleted_ssm_params) == 1
|
|
146
|
+
else "parameters were"
|
|
147
|
+
)
|
|
148
|
+
)
|
|
149
|
+
for param in deleted_ssm_params:
|
|
150
|
+
self.print(f"- {param}")
|
|
151
|
+
else:
|
|
152
|
+
self.print(
|
|
153
|
+
"However the key secrets couldn't be deleted from SSM as "
|
|
154
|
+
"requested."
|
|
155
|
+
)
|
|
166
156
|
|
|
167
157
|
def _handle_new_key_aws(self, key, enabled_auto_rotate):
|
|
168
158
|
params = key.get("ssm_params")
|
|
@@ -186,7 +176,7 @@ You may now go ahead and create a key for it by running:
|
|
|
186
176
|
self.print(
|
|
187
177
|
"The key was created, but it appears that the relevant "
|
|
188
178
|
"parameters weren't added to SSM. This should not happen, "
|
|
189
|
-
"please contact
|
|
179
|
+
f"please contact {MAINTAINER}!"
|
|
190
180
|
)
|
|
191
181
|
|
|
192
182
|
def _handle_new_key_local(self, key, client_name, env):
|
|
@@ -251,14 +241,9 @@ You may now go ahead and create a key for it by running:
|
|
|
251
241
|
|
|
252
242
|
self.print("Creating key for '{}' [{}]...".format(client_name, env))
|
|
253
243
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
)
|
|
258
|
-
except HTTPError as e:
|
|
259
|
-
message = e.response.json()["message"]
|
|
260
|
-
self.print(f"Something went wrong: {message}")
|
|
261
|
-
return
|
|
244
|
+
key = self.pubreg_client.create_key(
|
|
245
|
+
env, client_id, aws_account, aws_region, enable_auto_rotate
|
|
246
|
+
)
|
|
262
247
|
|
|
263
248
|
if key.get("ssm_params") is not None:
|
|
264
249
|
self._handle_new_key_aws(key, enable_auto_rotate)
|
|
@@ -267,8 +252,7 @@ You may now go ahead and create a key for it by running:
|
|
|
267
252
|
else:
|
|
268
253
|
self.print(
|
|
269
254
|
"The key was neither added to AWS nor returned to the "
|
|
270
|
-
"client. This should not happen, please contact "
|
|
271
|
-
"Datapatruljen!"
|
|
255
|
+
f"client. This should not happen, please contact {MAINTAINER}!"
|
|
272
256
|
)
|
|
273
257
|
|
|
274
258
|
def _list_client_keys_single(self, client_id, client_name, env):
|
|
@@ -321,15 +305,9 @@ You may now go ahead and create a key for it by running:
|
|
|
321
305
|
f"Will delete key '{key_id}' from '{client_name}' [{env}]."
|
|
322
306
|
)
|
|
323
307
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
)
|
|
328
|
-
self.pubreg_client.delete_key(env, client_id, key_id)
|
|
329
|
-
self.print("Done! The key is deleted and will no longer work.")
|
|
330
|
-
except HTTPError as e:
|
|
331
|
-
message = e.response.json()["message"]
|
|
332
|
-
self.print(f"Something went wrong: {message}")
|
|
308
|
+
self.print(f"Deleting key '{key_id}' from '{client_name}' [{env}]...")
|
|
309
|
+
self.pubreg_client.delete_key(env, client_id, key_id)
|
|
310
|
+
self.print("Done! The key is deleted and will no longer work.")
|
|
333
311
|
|
|
334
312
|
def audit_log(self):
|
|
335
313
|
choices = audit_log_wizard(self.pubreg_client)
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
from operator import itemgetter
|
|
2
|
+
|
|
3
|
+
from okdata.sdk.team.client import TeamClient
|
|
4
|
+
|
|
5
|
+
from okdata.cli import MAINTAINER
|
|
6
|
+
from okdata.cli.command import BASE_COMMAND_OPTIONS, BaseCommand
|
|
7
|
+
from okdata.cli.commands.teams.questions import NoTeamError
|
|
8
|
+
from okdata.cli.commands.teams.util import (
|
|
9
|
+
member_representation,
|
|
10
|
+
sorted_member_list,
|
|
11
|
+
)
|
|
12
|
+
from okdata.cli.commands.teams.wizards import (
|
|
13
|
+
add_member_wizard,
|
|
14
|
+
edit_team_wizard,
|
|
15
|
+
list_members_wizard,
|
|
16
|
+
remove_member_wizard,
|
|
17
|
+
)
|
|
18
|
+
from okdata.cli.output import create_output
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class TeamsCommand(BaseCommand):
|
|
22
|
+
__doc__ = f"""Oslo :: Teams
|
|
23
|
+
|
|
24
|
+
Usage:
|
|
25
|
+
okdata teams ls [--my] [options]
|
|
26
|
+
okdata teams edit [options]
|
|
27
|
+
okdata teams list-members [--my] [options]
|
|
28
|
+
okdata teams add-member [options]
|
|
29
|
+
okdata teams remove-member [options]
|
|
30
|
+
|
|
31
|
+
Examples:
|
|
32
|
+
okdata teams ls
|
|
33
|
+
okdata teams ls --my
|
|
34
|
+
okdata teams edit
|
|
35
|
+
okdata teams list-members --my
|
|
36
|
+
okdata teams add-member
|
|
37
|
+
okdata teams remove-member
|
|
38
|
+
|
|
39
|
+
Options:{BASE_COMMAND_OPTIONS}
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def __init__(self):
|
|
43
|
+
super().__init__()
|
|
44
|
+
self.client = TeamClient(env=self.opt("env"))
|
|
45
|
+
|
|
46
|
+
def handler(self):
|
|
47
|
+
if self.cmd("ls"):
|
|
48
|
+
self.ls(self.opt("my"))
|
|
49
|
+
if self.cmd("edit"):
|
|
50
|
+
self.edit()
|
|
51
|
+
if self.cmd("list-members"):
|
|
52
|
+
self.list_members(self.opt("my"))
|
|
53
|
+
if self.cmd("add-member"):
|
|
54
|
+
self.add_member()
|
|
55
|
+
if self.cmd("remove-member"):
|
|
56
|
+
self.remove_member()
|
|
57
|
+
|
|
58
|
+
def ls(self, my):
|
|
59
|
+
teams = self.client.get_teams(
|
|
60
|
+
include=None if my else "all", has_role="origo-team"
|
|
61
|
+
)
|
|
62
|
+
out = create_output(self.opt("format"), "teams_config.json")
|
|
63
|
+
out.add_rows(sorted(teams, key=itemgetter("name")))
|
|
64
|
+
self.print("{} teams:".format("My" if my else "All"), out)
|
|
65
|
+
|
|
66
|
+
def edit(self):
|
|
67
|
+
try:
|
|
68
|
+
config = edit_team_wizard(self.client)
|
|
69
|
+
except NoTeamError:
|
|
70
|
+
self.print(
|
|
71
|
+
"We haven't yet registered you as member of any Origo team. "
|
|
72
|
+
f"Please contact {MAINTAINER} to get it done."
|
|
73
|
+
)
|
|
74
|
+
return
|
|
75
|
+
|
|
76
|
+
if config["attribute"] == "name":
|
|
77
|
+
self.client.update_team_name(config["team_id"], config["team_name"])
|
|
78
|
+
else:
|
|
79
|
+
self.client.update_team_attribute(
|
|
80
|
+
config["team_id"], config["attribute"], config["attribute_value"]
|
|
81
|
+
)
|
|
82
|
+
self.print("Done!")
|
|
83
|
+
|
|
84
|
+
def list_members(self, my):
|
|
85
|
+
try:
|
|
86
|
+
config = list_members_wizard(self.client, my)
|
|
87
|
+
members = self.client.get_team_members(config["team_id"])
|
|
88
|
+
except NoTeamError:
|
|
89
|
+
self.print(
|
|
90
|
+
"We haven't yet registered you as member of any Origo team. "
|
|
91
|
+
f"Please contact {MAINTAINER} to get it done."
|
|
92
|
+
if my
|
|
93
|
+
else "No teams exist yet."
|
|
94
|
+
)
|
|
95
|
+
return
|
|
96
|
+
|
|
97
|
+
out = create_output(self.opt("format"), "team_members_config.json")
|
|
98
|
+
|
|
99
|
+
out.add_rows(sorted_member_list(members))
|
|
100
|
+
self.print("Team members", out)
|
|
101
|
+
|
|
102
|
+
def add_member(self):
|
|
103
|
+
try:
|
|
104
|
+
config = add_member_wizard(self.client)
|
|
105
|
+
except NoTeamError:
|
|
106
|
+
self.print(
|
|
107
|
+
"We haven't yet registered you as member of any Origo team. "
|
|
108
|
+
f"Please contact {MAINTAINER} to get it done."
|
|
109
|
+
)
|
|
110
|
+
return
|
|
111
|
+
|
|
112
|
+
user = self.client.get_user_by_username(config["username"])
|
|
113
|
+
team_members = [
|
|
114
|
+
m["username"] for m in self.client.get_team_members(config["team_id"])
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
if user["username"] in team_members:
|
|
118
|
+
self.print(
|
|
119
|
+
"User {} is already a member of this team.".format(
|
|
120
|
+
member_representation(user)
|
|
121
|
+
)
|
|
122
|
+
)
|
|
123
|
+
return
|
|
124
|
+
|
|
125
|
+
self.confirm_to_continue(
|
|
126
|
+
"Add {} to the team?".format(member_representation(user))
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
self.client.update_team_members(
|
|
130
|
+
config["team_id"], team_members + [user["username"]]
|
|
131
|
+
)
|
|
132
|
+
self.print("Done!")
|
|
133
|
+
|
|
134
|
+
def remove_member(self):
|
|
135
|
+
try:
|
|
136
|
+
config = remove_member_wizard(self.client)
|
|
137
|
+
except NoTeamError:
|
|
138
|
+
self.print(
|
|
139
|
+
"We haven't yet registered you as member of any Origo team. "
|
|
140
|
+
f"Please contact {MAINTAINER} to get it done."
|
|
141
|
+
)
|
|
142
|
+
return
|
|
143
|
+
|
|
144
|
+
team_members = self.client.get_team_members(config["team_id"])
|
|
145
|
+
members_to_remove, members_to_keep = [], []
|
|
146
|
+
for member in team_members:
|
|
147
|
+
if member["username"] in config["usernames"]:
|
|
148
|
+
members_to_remove.append(member)
|
|
149
|
+
else:
|
|
150
|
+
members_to_keep.append(member)
|
|
151
|
+
|
|
152
|
+
if len(members_to_keep) == 0:
|
|
153
|
+
self.confirm_to_continue(
|
|
154
|
+
"You are about to delete all members from the team, including "
|
|
155
|
+
"yourself. It will not be possible to edit this team any "
|
|
156
|
+
"further without being re-added by a systems administrator."
|
|
157
|
+
)
|
|
158
|
+
else:
|
|
159
|
+
self.confirm_to_continue(
|
|
160
|
+
"Remove the following member{} from the team?\n - {}".format(
|
|
161
|
+
"s" if len(members_to_remove) > 1 else "",
|
|
162
|
+
"\n - ".join(
|
|
163
|
+
[
|
|
164
|
+
member_representation(m)
|
|
165
|
+
for m in sorted_member_list(members_to_remove)
|
|
166
|
+
]
|
|
167
|
+
),
|
|
168
|
+
)
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
self.client.update_team_members(
|
|
172
|
+
config["team_id"], [m["username"] for m in members_to_keep]
|
|
173
|
+
)
|
|
174
|
+
self.print("Done!")
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import inspect
|
|
2
1
|
import json
|
|
3
2
|
import logging
|
|
4
3
|
import os
|
|
@@ -31,30 +30,6 @@ def create_output(format, configfile):
|
|
|
31
30
|
return TableOutput(config)
|
|
32
31
|
|
|
33
32
|
|
|
34
|
-
def table_config_from_schema(resource, exclude=None):
|
|
35
|
-
if exclude is None:
|
|
36
|
-
exclude = []
|
|
37
|
-
|
|
38
|
-
def _for(properties):
|
|
39
|
-
for property in properties:
|
|
40
|
-
body = properties[property]
|
|
41
|
-
if "properties" not in body:
|
|
42
|
-
yield body["title"], {"name": body["title"], "key": property}
|
|
43
|
-
else:
|
|
44
|
-
_for(body["properties"])
|
|
45
|
-
|
|
46
|
-
with open(
|
|
47
|
-
os.path.dirname(inspect.getfile(resource))
|
|
48
|
-
+ f"/schemas/{resource.__resource_name__}.json",
|
|
49
|
-
"r",
|
|
50
|
-
) as f:
|
|
51
|
-
schema = json.loads(f.read())
|
|
52
|
-
config = {
|
|
53
|
-
key: body for key, body in _for(schema["properties"]) if key not in exclude
|
|
54
|
-
}
|
|
55
|
-
return TableOutput(config)
|
|
56
|
-
|
|
57
|
-
|
|
58
33
|
class TableOutput(PrettyTable):
|
|
59
34
|
def __init__(self, config):
|
|
60
35
|
self.config = config
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: okdata-cli
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.1
|
|
4
4
|
Summary: CLI for services provided by Oslo Origo
|
|
5
5
|
Home-page: https://github.com/oslokommune/okdata-cli/
|
|
6
6
|
Author: Oslo Origo
|
|
@@ -24,8 +24,7 @@ Okdata CLI provides a unified interface to data services for Oslo Origo teams.
|
|
|
24
24
|
|
|
25
25
|
* [Install](doc/install.md)
|
|
26
26
|
* [Configuration](doc/configuration.md)
|
|
27
|
-
* [Datasets](doc/datasets.md)
|
|
28
|
-
* [Permissions](doc/permissions.md)
|
|
29
|
-
* [Pipelines](doc/pipelines.md)
|
|
30
27
|
* [Public registers](doc/pubreg.md)
|
|
31
28
|
* [Teams](doc/teams.md)
|
|
29
|
+
* [Datasets](doc/datasets.md)
|
|
30
|
+
* [Permissions](doc/permissions.md)
|
|
@@ -18,11 +18,6 @@ okdata/cli/commands/datasets/datasets.py
|
|
|
18
18
|
okdata/cli/commands/datasets/questions.py
|
|
19
19
|
okdata/cli/commands/datasets/validators.py
|
|
20
20
|
okdata/cli/commands/datasets/wizards.py
|
|
21
|
-
okdata/cli/commands/pipelines/__init__.py
|
|
22
|
-
okdata/cli/commands/pipelines/inputs.py
|
|
23
|
-
okdata/cli/commands/pipelines/instances.py
|
|
24
|
-
okdata/cli/commands/pipelines/pipelines.py
|
|
25
|
-
okdata/cli/commands/pipelines/schemas.py
|
|
26
21
|
okdata/cli/commands/pubreg/__init__.py
|
|
27
22
|
okdata/cli/commands/pubreg/client.py
|
|
28
23
|
okdata/cli/commands/pubreg/pubreg.py
|
|
@@ -42,10 +37,6 @@ okdata/cli/data/output-format/datasets_dataset_version_edition_distributions_con
|
|
|
42
37
|
okdata/cli/data/output-format/datasets_dataset_versions_config.json
|
|
43
38
|
okdata/cli/data/output-format/my_permissions_config.json
|
|
44
39
|
okdata/cli/data/output-format/permissions_config.json
|
|
45
|
-
okdata/cli/data/output-format/pipelines_config.json
|
|
46
|
-
okdata/cli/data/output-format/pipelines_instances_config.json
|
|
47
|
-
okdata/cli/data/output-format/pipelines_instances_inputs_config.json
|
|
48
|
-
okdata/cli/data/output-format/pipelines_instances_schemas_config.json
|
|
49
40
|
okdata/cli/data/output-format/pubreg_audit_log_config.json
|
|
50
41
|
okdata/cli/data/output-format/pubreg_clients_config.json
|
|
51
42
|
okdata/cli/data/output-format/pubreg_multiple_client_keys_config.json
|
|
File without changes
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
|
|
3
|
-
from okdata.cli.command import BaseCommand
|
|
4
|
-
from okdata.cli.output import create_output
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class PipelinesInputsLs(BaseCommand):
|
|
8
|
-
"""
|
|
9
|
-
usage:
|
|
10
|
-
okdata pipelines inputs ls <pipeline-instance> [options]
|
|
11
|
-
|
|
12
|
-
options:
|
|
13
|
-
-d --debug
|
|
14
|
-
--format=<format>
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
def handler(self):
|
|
18
|
-
out = create_output(
|
|
19
|
-
self.opt("format"), "pipelines_instances_inputs_config.json"
|
|
20
|
-
)
|
|
21
|
-
data = self.sdk.get_pipeline_inputs(self.arg("pipeline-instance"))
|
|
22
|
-
data = list(map(lambda x: x.__dict__, data))
|
|
23
|
-
out.add_rows(data)
|
|
24
|
-
self.print("Available pipepline inputs", out)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class PipelinesInputsCreate(BaseCommand):
|
|
28
|
-
"""
|
|
29
|
-
usage:
|
|
30
|
-
okdata pipelines inputs create - [options]
|
|
31
|
-
okdata pipelines inputs create <file> [options]
|
|
32
|
-
|
|
33
|
-
options:
|
|
34
|
-
-d --debug
|
|
35
|
-
--format=<format>
|
|
36
|
-
"""
|
|
37
|
-
|
|
38
|
-
def handler(self):
|
|
39
|
-
content = self.handle_input()
|
|
40
|
-
data = json.loads(content)
|
|
41
|
-
self.sdk.create_pipeline_input(data)
|
|
42
|
-
self.print(f"Created input with dataset URI: {data['datasetUri']}", data)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
class PipelinesInputs(BaseCommand):
|
|
46
|
-
"""
|
|
47
|
-
usage:
|
|
48
|
-
okdata pipelines inputs ls <pipeline-instance> [options]
|
|
49
|
-
okdata pipelines inputs create (<file> | -) [options]
|
|
50
|
-
|
|
51
|
-
options:
|
|
52
|
-
-d --debug
|
|
53
|
-
--format=<format>
|
|
54
|
-
"""
|
|
55
|
-
|
|
56
|
-
def __init__(self, sdk):
|
|
57
|
-
super().__init__(sdk)
|
|
58
|
-
self.sub_commands = [PipelinesInputsLs, PipelinesInputsCreate]
|
|
59
|
-
|
|
60
|
-
def handler(self):
|
|
61
|
-
if self.opt("help"):
|
|
62
|
-
return self.help()
|
|
63
|
-
schema = self.sdk.get_schema(self.opt("id"))
|
|
64
|
-
schema.schema = json.loads(schema.schema)
|
|
65
|
-
self.pretty_json(schema.__dict__)
|
|
66
|
-
return None
|