adalab-cli 1.4.0__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.
- adalab_cli-1.4.0/PKG-INFO +58 -0
- adalab_cli-1.4.0/README.md +30 -0
- adalab_cli-1.4.0/adalab_cli/__init__.py +11 -0
- adalab_cli-1.4.0/adalab_cli/cli/__init__.py +5 -0
- adalab_cli-1.4.0/adalab_cli/cli/app.py +191 -0
- adalab_cli-1.4.0/adalab_cli/cli/authentication_flows.py +147 -0
- adalab_cli-1.4.0/adalab_cli/cli/completion_tree.py +67 -0
- adalab_cli-1.4.0/adalab_cli/cli/databases_commands.py +221 -0
- adalab_cli-1.4.0/adalab_cli/cli/factory.py +100 -0
- adalab_cli-1.4.0/adalab_cli/cli/gallery_commands.py +166 -0
- adalab_cli-1.4.0/adalab_cli/cli/interactive.py +65 -0
- adalab_cli-1.4.0/adalab_cli/cli/kernel_commands.py +48 -0
- adalab_cli-1.4.0/adalab_cli/cli/logger.py +125 -0
- adalab_cli-1.4.0/adalab_cli/cli/login_commands.py +267 -0
- adalab_cli-1.4.0/adalab_cli/cli/oci_commands.py +77 -0
- adalab_cli-1.4.0/adalab_cli/cli/schedule_commands.py +188 -0
- adalab_cli-1.4.0/adalab_cli/cli/user_commands.py +75 -0
- adalab_cli-1.4.0/adalab_cli/cli/utils.py +163 -0
- adalab_cli-1.4.0/pyproject.toml +123 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: adalab-cli
|
|
3
|
+
Version: 1.4.0
|
|
4
|
+
Summary: The CLI app to interact with AdaLab.
|
|
5
|
+
Home-page: https://adamatics.com
|
|
6
|
+
Author: Adamatics ApS
|
|
7
|
+
Author-email: info@adamatics.com
|
|
8
|
+
Requires-Python: >=3.10.0,<4.0.0
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Classifier: Typing :: Typed
|
|
18
|
+
Requires-Dist: adalib (>=2.6.0)
|
|
19
|
+
Requires-Dist: adalib-auth (>=1.1.0)
|
|
20
|
+
Requires-Dist: loguru (>=0.7.2)
|
|
21
|
+
Requires-Dist: prompt-toolkit (>=3.0.47)
|
|
22
|
+
Requires-Dist: sh (>=2.0.6)
|
|
23
|
+
Requires-Dist: tabulate (>=0.9.0)
|
|
24
|
+
Requires-Dist: typer (>=0.9.0)
|
|
25
|
+
Project-URL: Repository, https://gitlab.com/adamatics/python/adalab-cli
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# adalab-cli
|
|
29
|
+
|
|
30
|
+
This repository contains the source code of `adalab-cli`, the CLI app to interact with the AdaLab platform.
|
|
31
|
+
|
|
32
|
+
## Installation
|
|
33
|
+
|
|
34
|
+
`adalab-cli` can be installed from PyPI or a `devpi` index:
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
# PyPI
|
|
38
|
+
pip install adalab-cli
|
|
39
|
+
# devpi
|
|
40
|
+
pip install --extra-index-url <devpi_index_url> adalab-cli
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
In order to add it to the dependencies of a Python project using `poetry` use:
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
poetry source add --priority=supplemental <repo_name> <devpi_index_url>
|
|
47
|
+
poetry source add --priority=primary PyPI
|
|
48
|
+
poetry add --source <repo_name> adalab-cli
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Usage
|
|
52
|
+
|
|
53
|
+
See the corresponding documentation pages.
|
|
54
|
+
|
|
55
|
+
## Contributing
|
|
56
|
+
|
|
57
|
+
See the [contributor's guide](CONTRIBUTING.md).
|
|
58
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# adalab-cli
|
|
2
|
+
|
|
3
|
+
This repository contains the source code of `adalab-cli`, the CLI app to interact with the AdaLab platform.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
`adalab-cli` can be installed from PyPI or a `devpi` index:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
# PyPI
|
|
11
|
+
pip install adalab-cli
|
|
12
|
+
# devpi
|
|
13
|
+
pip install --extra-index-url <devpi_index_url> adalab-cli
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
In order to add it to the dependencies of a Python project using `poetry` use:
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
poetry source add --priority=supplemental <repo_name> <devpi_index_url>
|
|
20
|
+
poetry source add --priority=primary PyPI
|
|
21
|
+
poetry add --source <repo_name> adalab-cli
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
See the corresponding documentation pages.
|
|
27
|
+
|
|
28
|
+
## Contributing
|
|
29
|
+
|
|
30
|
+
See the [contributor's guide](CONTRIBUTING.md).
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""The adalab-cli base module exposes the CLI application.
|
|
2
|
+
"""
|
|
3
|
+
|
|
4
|
+
import importlib.metadata
|
|
5
|
+
|
|
6
|
+
_DISTRIBUTION_METADATA = importlib.metadata.metadata("adalab-cli")
|
|
7
|
+
__project__ = _DISTRIBUTION_METADATA["name"]
|
|
8
|
+
__version__ = _DISTRIBUTION_METADATA["version"]
|
|
9
|
+
__description__ = _DISTRIBUTION_METADATA["description"]
|
|
10
|
+
|
|
11
|
+
__all__ = ["cli"]
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"""Main module for the adalib CLI.
|
|
2
|
+
|
|
3
|
+
This module initializes the Typer application and integrates various
|
|
4
|
+
submodules that handle different command groups for the adalib CLI.
|
|
5
|
+
|
|
6
|
+
Submodules:
|
|
7
|
+
- oci_commands: Handles commands related to Open Container Initiative (OCI).
|
|
8
|
+
- gallery_commands: Manages commands for gallery operations.
|
|
9
|
+
- kernel_commands: Contains commands for kernel-related operations.
|
|
10
|
+
- user_commands: Deals with user-related commands.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import importlib.metadata
|
|
14
|
+
import os
|
|
15
|
+
|
|
16
|
+
import requests
|
|
17
|
+
import typer
|
|
18
|
+
from loguru import logger
|
|
19
|
+
from prompt_toolkit.completion import NestedCompleter
|
|
20
|
+
from rich import print as rich_print
|
|
21
|
+
from rich.console import Console
|
|
22
|
+
from rich.table import Table
|
|
23
|
+
|
|
24
|
+
from . import authentication_flows as auth
|
|
25
|
+
from .completion_tree import completion_tree
|
|
26
|
+
from .databases_commands import db_app
|
|
27
|
+
from .gallery_commands import gallery_app
|
|
28
|
+
from .interactive import interactive_mode
|
|
29
|
+
from .logger import Logger
|
|
30
|
+
from .login_commands import load_config
|
|
31
|
+
from .schedule_commands import schedules_app
|
|
32
|
+
from .user_commands import user_app
|
|
33
|
+
|
|
34
|
+
app = typer.Typer(no_args_is_help=False)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@app.callback("adalab", invoke_without_command=True, no_args_is_help=True)
|
|
38
|
+
def main(
|
|
39
|
+
token: str = typer.Option(None, help="User token for authentication"),
|
|
40
|
+
adalab_url: str = typer.Option(None, help="URL of the AdaLab server"),
|
|
41
|
+
adalab_secret: str = typer.Option(None, help="Client secret for AdaLab"),
|
|
42
|
+
interactive: bool = typer.Option(
|
|
43
|
+
False, "-i", "--interactive", help="Activate interactive mode"
|
|
44
|
+
),
|
|
45
|
+
verbose: int = typer.Option(
|
|
46
|
+
0,
|
|
47
|
+
"-v",
|
|
48
|
+
count=True,
|
|
49
|
+
help="Verbosity level of the logs: -v (default): INFO | -vv: DEBUG | -vvv: TRACE",
|
|
50
|
+
min=0,
|
|
51
|
+
max=3,
|
|
52
|
+
),
|
|
53
|
+
no_output: bool = typer.Option(False, "--no-output", help="Disable output from the CLI."),
|
|
54
|
+
):
|
|
55
|
+
if no_output:
|
|
56
|
+
logger.remove()
|
|
57
|
+
else:
|
|
58
|
+
Logger(verbosity=verbose)
|
|
59
|
+
logger.info("Starting adalab CLI.")
|
|
60
|
+
logger.debug("Debugging mode activated.")
|
|
61
|
+
logger.trace("Tracing mode activated.")
|
|
62
|
+
|
|
63
|
+
# Attempt to configure adalib with user token.
|
|
64
|
+
# This works when token is either provided or stored in environment.
|
|
65
|
+
try:
|
|
66
|
+
auth.in_line_authentication(adalab_url, adalab_secret, token)
|
|
67
|
+
except AssertionError as e:
|
|
68
|
+
logger.info(f"{str(e)}")
|
|
69
|
+
|
|
70
|
+
# Start the interactive mode
|
|
71
|
+
if interactive:
|
|
72
|
+
rich_print("🏡 Welcome to AdaLab CLI interactive mode.")
|
|
73
|
+
rich_print("👋 Type 'exit' to quit.")
|
|
74
|
+
rich_print("ℹ️ Type 'help' for help.")
|
|
75
|
+
interactive_mode(
|
|
76
|
+
this_app=app,
|
|
77
|
+
title="adalab",
|
|
78
|
+
nested=True,
|
|
79
|
+
color="seagreen",
|
|
80
|
+
completion=NestedCompleter.from_nested_dict(completion_tree),
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@app.command("login")
|
|
85
|
+
def login_commands(
|
|
86
|
+
auth_flow: str = typer.Option(
|
|
87
|
+
default="browser",
|
|
88
|
+
help="Authentication flow. Options: browser, device-code, user-token",
|
|
89
|
+
),
|
|
90
|
+
token: str = typer.Option(None, help="Token for authentication"),
|
|
91
|
+
):
|
|
92
|
+
"""
|
|
93
|
+
Login to adalab
|
|
94
|
+
"""
|
|
95
|
+
stored_configuration = load_config()
|
|
96
|
+
adalab_server_url = stored_configuration.get(
|
|
97
|
+
"adalab_url"
|
|
98
|
+
) # Look for the URL in the config file
|
|
99
|
+
if adalab_server_url is None:
|
|
100
|
+
adalab_server_url = os.getenv("ADALAB_URL") # Look for the URL in env vars
|
|
101
|
+
if adalab_server_url is None:
|
|
102
|
+
adalab_server_url = typer.prompt("What is the AdaLab url?") # Ask for the URL
|
|
103
|
+
logger.info(f"AdaLab server URL: {adalab_server_url}")
|
|
104
|
+
|
|
105
|
+
adalab_client_secret = stored_configuration.get(
|
|
106
|
+
"adalab_secret"
|
|
107
|
+
) # Look for the client secret in the config file
|
|
108
|
+
if adalab_client_secret is None:
|
|
109
|
+
adalab_client_secret = os.getenv("ADALAB_CLIENT_SECRET")
|
|
110
|
+
if "ADALAB_CLIENT_SECRET" not in os.environ:
|
|
111
|
+
adalab_client_secret = typer.prompt(
|
|
112
|
+
"What is the AdaLab client secret?", hide_input=True
|
|
113
|
+
)
|
|
114
|
+
logger.info("AdaLab client secret: ********")
|
|
115
|
+
# Check validity of URL
|
|
116
|
+
response = requests.get(adalab_server_url + "/adaboard/api", timeout=10)
|
|
117
|
+
if response.status_code != 200:
|
|
118
|
+
typer.echo("Invalid URL. Please try again.")
|
|
119
|
+
raise typer.Exit()
|
|
120
|
+
|
|
121
|
+
# Check which of the three kinds of authentication flows was set
|
|
122
|
+
if auth_flow == "browser":
|
|
123
|
+
auth.start_browser_auth(
|
|
124
|
+
adalab_server_url=adalab_server_url, adalab_client_secret=adalab_client_secret
|
|
125
|
+
)
|
|
126
|
+
elif auth_flow == "user-token":
|
|
127
|
+
auth.start_user_token_auth(
|
|
128
|
+
adalab_server_url=adalab_server_url,
|
|
129
|
+
token=token,
|
|
130
|
+
adalab_client_secret=adalab_client_secret,
|
|
131
|
+
)
|
|
132
|
+
elif auth_flow == "device-code":
|
|
133
|
+
auth.start_device_code_auth(
|
|
134
|
+
adalab_server_url=adalab_server_url, adalab_client_secret=adalab_client_secret
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
else:
|
|
138
|
+
typer.echo(
|
|
139
|
+
"Invalid authentication flow. Please try again."
|
|
140
|
+
"Options: browser, device-code, user-token"
|
|
141
|
+
)
|
|
142
|
+
raise typer.Exit()
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@app.command("version")
|
|
146
|
+
def get_version():
|
|
147
|
+
"""
|
|
148
|
+
Prints the version of adalib.
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
version_string_adalib = importlib.metadata.version("adalib")
|
|
152
|
+
version_string_adalib_auth = importlib.metadata.version("adalib-auth")
|
|
153
|
+
version_string_adalab_cli = importlib.metadata.version("adalab-cli")
|
|
154
|
+
|
|
155
|
+
table = Table("Package", "Version")
|
|
156
|
+
table.add_row("adalib", version_string_adalib)
|
|
157
|
+
table.add_row("adalib-auth", version_string_adalib_auth)
|
|
158
|
+
table.add_row("adalab-cli", version_string_adalab_cli)
|
|
159
|
+
|
|
160
|
+
console = Console()
|
|
161
|
+
|
|
162
|
+
console.print(table)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
app.add_typer(
|
|
166
|
+
db_app,
|
|
167
|
+
name="databases",
|
|
168
|
+
help="Commands for interacting with databases.",
|
|
169
|
+
no_args_is_help=True,
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
app.add_typer(
|
|
173
|
+
gallery_app,
|
|
174
|
+
name="cards",
|
|
175
|
+
help="Commands for interacting with the gallery.",
|
|
176
|
+
no_args_is_help=True,
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
app.add_typer(
|
|
180
|
+
user_app,
|
|
181
|
+
name="user",
|
|
182
|
+
help="Commands for interacting with user information.",
|
|
183
|
+
no_args_is_help=True,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
app.add_typer(
|
|
187
|
+
schedules_app,
|
|
188
|
+
name="schedules",
|
|
189
|
+
help="Commands for interacting with schedules.",
|
|
190
|
+
no_args_is_help=True,
|
|
191
|
+
)
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from time import sleep
|
|
3
|
+
|
|
4
|
+
import requests
|
|
5
|
+
import typer
|
|
6
|
+
from adalib_auth.config import get_config
|
|
7
|
+
from keycloak import exceptions
|
|
8
|
+
from loguru import logger
|
|
9
|
+
from rich import print as rich_print
|
|
10
|
+
|
|
11
|
+
from .login_commands import CLIENT_ID, KeycloakAuth, save_credentials
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def start_browser_auth(adalab_server_url: str = None, adalab_client_secret: str = None):
|
|
15
|
+
"""Starts the browser-based authentication flow.
|
|
16
|
+
|
|
17
|
+
:param adalab_server_url: The URL of the Adalab server, defaults to None
|
|
18
|
+
:type adalab_server_url: str, optional
|
|
19
|
+
"""
|
|
20
|
+
auth = KeycloakAuth(
|
|
21
|
+
adalab_server_url=adalab_server_url, adalab_client_secret=adalab_client_secret
|
|
22
|
+
)
|
|
23
|
+
auth.login()
|
|
24
|
+
logger.success("Authentication successful. Credentials saved.")
|
|
25
|
+
rich_print(
|
|
26
|
+
"🎉 [bold green]Authentication successful[/bold green]. You can now enjoy the AdaLab CLI."
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def start_user_token_auth(
|
|
31
|
+
token: str = None,
|
|
32
|
+
adalab_server_url: str = None,
|
|
33
|
+
adalab_client_secret: str = None,
|
|
34
|
+
store_credentials: bool = True,
|
|
35
|
+
):
|
|
36
|
+
"""Starts the user token authentication flow.
|
|
37
|
+
|
|
38
|
+
This function exchanges the user token for an access and refresh token. The token can be given
|
|
39
|
+
directly in the prompt or as an environment variable.
|
|
40
|
+
The access token and refresh token are saved to a file for future use.
|
|
41
|
+
|
|
42
|
+
:param token: The user token, it will be retrieve from ADALAB_USER_TOKEN environment variable
|
|
43
|
+
or prompted from the user.
|
|
44
|
+
:type token: str, optional
|
|
45
|
+
:param adalab_server_url: The URL of the ADALab server. If not provided, it will be retrieved
|
|
46
|
+
from the adalab_server_url argument.
|
|
47
|
+
:type adalab_server_url: str, optional
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
if token is None:
|
|
51
|
+
token = os.getenv("ADALAB_USER_TOKEN") or typer.prompt(
|
|
52
|
+
"What is your user token", hide_input=True
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
resp = requests.get(
|
|
56
|
+
adalab_server_url + "/adaboard/api/adalib/token",
|
|
57
|
+
headers={"Authorization": f"Token {token}"},
|
|
58
|
+
)
|
|
59
|
+
if resp.status_code != 200:
|
|
60
|
+
raise AssertionError(f"Failed to authenticate with user token. {resp.text}")
|
|
61
|
+
|
|
62
|
+
jh_token = resp.json()["access_token"]
|
|
63
|
+
new_token = KeycloakAuth(
|
|
64
|
+
adalab_server_url=adalab_server_url, adalab_client_secret=adalab_client_secret
|
|
65
|
+
).client.exchange_token(token=jh_token, audience=CLIENT_ID)
|
|
66
|
+
if store_credentials:
|
|
67
|
+
save_credentials(
|
|
68
|
+
my_access_token=new_token["access_token"],
|
|
69
|
+
my_refresh_token=new_token["refresh_token"],
|
|
70
|
+
)
|
|
71
|
+
logger.success("Authentication successful. Credentials saved.")
|
|
72
|
+
rich_print(
|
|
73
|
+
"🎉 [bold green]Authentication successful[/bold green]. You can now enjoy the AdaLab CLI."
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def start_device_code_auth(adalab_server_url: str = None, adalab_client_secret: str = None):
|
|
78
|
+
"""
|
|
79
|
+
Starts the device code authentication flow.
|
|
80
|
+
|
|
81
|
+
This function initiates the device code authentication flow using the AdaLab server URL.
|
|
82
|
+
It retrieves the device code information from the Keycloak authentication client,
|
|
83
|
+
prompts the user to visit the verification URI and enter the user code,
|
|
84
|
+
and waits for the user authentication to complete.
|
|
85
|
+
Once the authentication is successful, the access token and refresh token are saved.
|
|
86
|
+
|
|
87
|
+
:param adalab_server_url: The AdaLab server URL, defaults to None
|
|
88
|
+
:type adalab_server_url: str, optional
|
|
89
|
+
"""
|
|
90
|
+
auth = KeycloakAuth(
|
|
91
|
+
adalab_server_url=adalab_server_url, adalab_client_secret=adalab_client_secret
|
|
92
|
+
)
|
|
93
|
+
device_code_info = auth.client.device()
|
|
94
|
+
device_code = device_code_info["device_code"]
|
|
95
|
+
user_code = device_code_info["user_code"]
|
|
96
|
+
verification_uri = device_code_info["verification_uri"]
|
|
97
|
+
rich_print("Please visit %s and enter the code: %s", verification_uri, user_code)
|
|
98
|
+
rich_print("This code expires in %s seconds", device_code_info["expires_in"])
|
|
99
|
+
token = None
|
|
100
|
+
while token is None:
|
|
101
|
+
try:
|
|
102
|
+
token = auth.client.token(
|
|
103
|
+
grant_type="urn:ietf:params:oauth:grant-type:device_code",
|
|
104
|
+
device_code=device_code,
|
|
105
|
+
)
|
|
106
|
+
except exceptions.KeycloakPostError as e:
|
|
107
|
+
if "authorization_pending" in str(e):
|
|
108
|
+
logger.info("Waiting for user authentication...")
|
|
109
|
+
sleep(device_code_info["interval"])
|
|
110
|
+
else:
|
|
111
|
+
logger.error("Error during device polling: %s", str(e))
|
|
112
|
+
exit(1)
|
|
113
|
+
save_credentials(
|
|
114
|
+
my_access_token=token["access_token"],
|
|
115
|
+
my_refresh_token=token["refresh_token"],
|
|
116
|
+
)
|
|
117
|
+
logger.success("Authentication successful. Credentials saved.")
|
|
118
|
+
rich_print(
|
|
119
|
+
"🎉 [bold green]Authentication successful[/bold green]. You can now enjoy the AdaLab CLI."
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def in_line_authentication(
|
|
124
|
+
adalab_server_url: str = None, adalab_secret: str = None, user_token: str = None
|
|
125
|
+
) -> None:
|
|
126
|
+
"""Auxiliary function for in-line authentication. This will not store credentials in the
|
|
127
|
+
configuration file. Instead it will be used for one-time authentication. Only valid for the
|
|
128
|
+
user token authentication flow.
|
|
129
|
+
|
|
130
|
+
:param adalab_server_url: The AdaLab server URL, defaults to None
|
|
131
|
+
:type adalab_server_url: str, optional
|
|
132
|
+
:param adalab_secret: The AdaLab JupyterHub client secret, defaults to None
|
|
133
|
+
:type adalab_secret: str, optional
|
|
134
|
+
:param user_token: The user token retrieved from AdaLab, defaults to None
|
|
135
|
+
:type user_token: str, optional
|
|
136
|
+
"""
|
|
137
|
+
if adalab_server_url is None:
|
|
138
|
+
adalab_server_url = os.getenv("ADALAB_URL") or None
|
|
139
|
+
if adalab_secret is None:
|
|
140
|
+
adalab_secret = os.getenv("ADALAB_CLIENT_SECRET") or None
|
|
141
|
+
if user_token is None:
|
|
142
|
+
user_token = os.getenv("ADALAB_USER_TOKEN") or None
|
|
143
|
+
|
|
144
|
+
if None in (adalab_server_url, adalab_secret, user_token):
|
|
145
|
+
raise AssertionError("Missing required variables for in-line authentication.")
|
|
146
|
+
|
|
147
|
+
get_config(adaboard_api_url=adalab_server_url + "/adaboard/api", token=user_token)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""Map of the CLI commands and subcommands for the CLI completion tree."""
|
|
2
|
+
|
|
3
|
+
completion_tree = {
|
|
4
|
+
"cards": {
|
|
5
|
+
"approve-card": {"--help": None},
|
|
6
|
+
"expose-card": {"--help": None},
|
|
7
|
+
"get-card": {"--help": None},
|
|
8
|
+
"hide-card": {"--help": None},
|
|
9
|
+
"list-cards": {
|
|
10
|
+
"all": None,
|
|
11
|
+
"notebook": None,
|
|
12
|
+
"voila": None,
|
|
13
|
+
"url": None,
|
|
14
|
+
"group": None,
|
|
15
|
+
"--help": None,
|
|
16
|
+
},
|
|
17
|
+
"help": None,
|
|
18
|
+
"exit": None,
|
|
19
|
+
},
|
|
20
|
+
"databases": {
|
|
21
|
+
"list-databases": {"--no-pretty": None, "--help": None},
|
|
22
|
+
"list-datasets": {"--no-pretty": None, "--return-sql": None, "--help": None},
|
|
23
|
+
"list-tables": {"--no-pretty": None, "--help": None},
|
|
24
|
+
"view-dataset": {"--head": None, "--no-pretty": None, "--help": None},
|
|
25
|
+
"help": None,
|
|
26
|
+
"exit": None,
|
|
27
|
+
},
|
|
28
|
+
"schedules": {
|
|
29
|
+
"create-schedule": {
|
|
30
|
+
"--schedule": None,
|
|
31
|
+
"--pool": None,
|
|
32
|
+
"--active": None,
|
|
33
|
+
"--concurrent": None,
|
|
34
|
+
"--cleanup": None,
|
|
35
|
+
"--timeout": None,
|
|
36
|
+
"--help": None,
|
|
37
|
+
},
|
|
38
|
+
"delete-run": {"--help": None},
|
|
39
|
+
"delete-schedule": {"--help": None},
|
|
40
|
+
"start-run": {
|
|
41
|
+
"--cleanup": None,
|
|
42
|
+
"--pool": None,
|
|
43
|
+
"--timeout": None,
|
|
44
|
+
"--help": None,
|
|
45
|
+
},
|
|
46
|
+
"stop-run": {"--help": None},
|
|
47
|
+
"update-schedule": {
|
|
48
|
+
"--schedule": None,
|
|
49
|
+
"--pool": None,
|
|
50
|
+
"--active": None,
|
|
51
|
+
"--concurrent": None,
|
|
52
|
+
"--cleanup": None,
|
|
53
|
+
"--timeout": None,
|
|
54
|
+
"--help": None,
|
|
55
|
+
},
|
|
56
|
+
"help": None,
|
|
57
|
+
"exit": None,
|
|
58
|
+
},
|
|
59
|
+
"user": {
|
|
60
|
+
"whoami": {"--full-information": None, "--with-notifications": None, "--help": None},
|
|
61
|
+
"help": None,
|
|
62
|
+
"exit": None,
|
|
63
|
+
},
|
|
64
|
+
"version": None,
|
|
65
|
+
"help": None,
|
|
66
|
+
"exit": None,
|
|
67
|
+
}
|