amd-oneclick-sdk 1.0.0__py3-none-any.whl

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.
@@ -0,0 +1,45 @@
1
+ """Radeon Cloud SDK for scoped account and instance operations.
2
+
3
+ Browser login issues a dedicated ``rcc_`` token. Model-forwarding ``rc-``
4
+ tokens are intentionally outside this SDK's resource-management trust domain.
5
+ """
6
+ from .auth import AuthProgress, AuthResult, authenticate
7
+ from .client import OneClickClient, RadeonCloudClient
8
+ from .errors import (
9
+ ApiError,
10
+ AuthenticationError,
11
+ AuthorizationError,
12
+ ConfigurationError,
13
+ NetworkError,
14
+ OneClickError,
15
+ ProtocolError,
16
+ RateLimitError,
17
+ TlsError,
18
+ UrlPolicyError,
19
+ WaitTimeout,
20
+ )
21
+ from .rcc_config import ConnectionResolution, resolve_connection_info
22
+
23
+ __version__ = "1.0.0"
24
+
25
+ __all__ = [
26
+ "ApiError",
27
+ "AuthProgress",
28
+ "AuthResult",
29
+ "AuthenticationError",
30
+ "AuthorizationError",
31
+ "ConnectionResolution",
32
+ "ConfigurationError",
33
+ "NetworkError",
34
+ "OneClickClient",
35
+ "OneClickError",
36
+ "ProtocolError",
37
+ "RateLimitError",
38
+ "RadeonCloudClient",
39
+ "TlsError",
40
+ "UrlPolicyError",
41
+ "WaitTimeout",
42
+ "__version__",
43
+ "authenticate",
44
+ "resolve_connection_info",
45
+ ]
@@ -0,0 +1,7 @@
1
+ """Internal implementation modules for the RCC command-line interface.
2
+
3
+ The supported import remains amd_oneclick_sdk.cli. This package separates
4
+ argument parsing and top-level dispatch from device authentication, local
5
+ profiles, read-only credits, catalog discovery, and instance lifecycle
6
+ commands. Deferred product areas are intentionally absent from this release.
7
+ """
@@ -0,0 +1,225 @@
1
+ """Workstation authentication and account-switching commands."""
2
+ from __future__ import annotations
3
+
4
+ from ..client import OneClickClient
5
+ from ..errors import ConfigurationError, OneClickError
6
+ from ..rcc_config import (
7
+ account_names,
8
+ active_account_name,
9
+ get_account,
10
+ load_config,
11
+ remove_account,
12
+ resolve_connection,
13
+ resolve_connection_info,
14
+ )
15
+ from .common import _client_for, _write_json
16
+ from .device_auth import _authorize_account
17
+
18
+
19
+ _LOGOUT_WARNINGS = [
20
+ "Only the selected RCC access token is revoked.",
21
+ "Running instances, GPU billing, other device tokens, and web sessions are unchanged.",
22
+ ]
23
+
24
+
25
+ def _command_auth_login(args, out, err) -> int:
26
+ base_url, _ = resolve_connection(
27
+ args.base_url,
28
+ "",
29
+ require_token=False,
30
+ account=getattr(args, "account", None),
31
+ allow_missing_account=True,
32
+ )
33
+ result, path = _authorize_account(
34
+ base_url=base_url,
35
+ device_name=args.device_name,
36
+ timeout=args.timeout,
37
+ no_browser=args.no_browser,
38
+ out=out,
39
+ err=err,
40
+ json_output=args.json,
41
+ account_name=getattr(args, "account", None),
42
+ derive_name=not bool(getattr(args, "account", None)),
43
+ )
44
+ if args.json:
45
+ _write_json(
46
+ {
47
+ **result.public_payload(),
48
+ "status": "authenticated",
49
+ "config_path": str(path),
50
+ },
51
+ out,
52
+ )
53
+ else:
54
+ out.write(
55
+ f"Authenticated as {result.user.get('email') or 'unknown user'}.\n"
56
+ f"Credentials saved to {path}\n"
57
+ )
58
+ return 0
59
+
60
+
61
+ def _command_auth_status(args, out, err) -> int:
62
+ if getattr(args, "all", False):
63
+ return _command_auth_list(args, out, err, include_remote=True)
64
+ payload = _client_for(args).auth_status()
65
+ if args.json:
66
+ _write_json(payload, out)
67
+ return 0
68
+ user = payload.get("user") or {}
69
+ token = payload.get("token") or {}
70
+ out.write(
71
+ f"authenticated: {user.get('email') or 'unknown'}\n"
72
+ f"provider: {user.get('provider') or 'unknown'}\n"
73
+ f"credits: {user.get('credits', 0)}\n"
74
+ f"token expires: {token.get('expires_at') or 'unknown'}\n"
75
+ )
76
+ return 0
77
+
78
+
79
+ def _command_auth_logout(args, out, err) -> int:
80
+ if getattr(args, "all", False):
81
+ if any(getattr(args, name, None) is not None for name in ("account", "base_url", "token")):
82
+ raise ConfigurationError("auth logout --all cannot use --account, --base-url, or --token")
83
+ removed = []
84
+ failures = []
85
+ for name in list(account_names()):
86
+ try:
87
+ _logout_one_account(name)
88
+ except OneClickError as exc:
89
+ failures.append({"account": name, "error": str(exc)})
90
+ else:
91
+ removed.append(name)
92
+ payload = {
93
+ "logged_out": removed,
94
+ "failed": failures,
95
+ "active_account": active_account_name() or None,
96
+ "warnings": list(_LOGOUT_WARNINGS),
97
+ }
98
+ if args.json:
99
+ _write_json(payload, out)
100
+ else:
101
+ out.write(
102
+ f"Revoked and removed {len(removed)} workstation login(s).\n"
103
+ "Warning: running resources and billing continue; other device "
104
+ "tokens and web sessions are unchanged.\n"
105
+ )
106
+ for failure in failures:
107
+ out.write(
108
+ f" {failure['account']} was kept locally: "
109
+ f"{failure['error']}\n"
110
+ )
111
+ return 1 if failures else 0
112
+ connection = resolve_connection_info(
113
+ getattr(args, "base_url", None),
114
+ getattr(args, "token", None),
115
+ account=getattr(args, "account", None),
116
+ )
117
+ payload = OneClickClient(connection.base_url, connection.token).auth_logout()
118
+ selected = (
119
+ connection.account
120
+ if connection.token_source == f"account:{connection.account}"
121
+ else ""
122
+ )
123
+ if selected:
124
+ # A concurrent login must survive revocation of the older token.
125
+ remove_account(selected, expected_token=connection.token)
126
+ payload = {
127
+ **payload,
128
+ "account": selected or None,
129
+ "base_url": connection.base_url,
130
+ "token_source": connection.token_source,
131
+ "local_profile_removed": bool(selected),
132
+ "warnings": list(_LOGOUT_WARNINGS),
133
+ }
134
+ if args.json:
135
+ _write_json(payload, out)
136
+ else:
137
+ result = (
138
+ f"RCC token for {selected!r} was revoked and its local profile removed.\n"
139
+ if selected else f"RCC token for {connection.base_url} was revoked.\n"
140
+ )
141
+ out.write(
142
+ result +
143
+ "Warning: running resources and billing continue; other device tokens "
144
+ "and web sessions are unchanged.\n"
145
+ )
146
+ return 0
147
+
148
+
149
+ def _logout_one_account(name: str) -> dict:
150
+ selected, entry = get_account(name)
151
+ token = str(entry.get("token") or "")
152
+ payload: dict = {"revoked": False}
153
+ if token:
154
+ payload = OneClickClient(str(entry.get("base_url") or ""), token).auth_logout()
155
+ remove_account(selected, expected_token=token)
156
+ return {
157
+ **payload,
158
+ "account": selected,
159
+ "local_profile_removed": True,
160
+ "warnings": list(_LOGOUT_WARNINGS),
161
+ }
162
+
163
+
164
+ def _public_accounts() -> tuple[str, list[dict]]:
165
+ document = load_config()
166
+ active = str(document.get("active_account") or "")
167
+ rows = []
168
+ for name, entry in (document.get("accounts") or {}).items():
169
+ rows.append(
170
+ {
171
+ "name": name,
172
+ "active": name == active,
173
+ "email": str(entry.get("email") or ""),
174
+ "base_url": str(entry.get("base_url") or ""),
175
+ "expires_at": str(entry.get("expires_at") or ""),
176
+ "logged_in": bool(entry.get("token")),
177
+ }
178
+ )
179
+ return active, rows
180
+
181
+
182
+ def _account_rows_with_remote_state() -> tuple[str, list[dict]]:
183
+ active, rows = _public_accounts()
184
+ for row in rows:
185
+ row["provider"] = None
186
+ row["credits"] = None
187
+ row["remote_account"] = None
188
+ row["remote_error"] = None
189
+ if not row["logged_in"]:
190
+ continue
191
+ try:
192
+ base_url, token = resolve_connection(account=row["name"])
193
+ client = OneClickClient(base_url, token)
194
+ account = client.account().get("account") or {}
195
+ row["provider"] = account.get("provider")
196
+ row["credits"] = account.get("credits")
197
+ row["remote_account"] = account
198
+ except OneClickError as exc:
199
+ row["remote_error"] = str(exc)
200
+ return active, rows
201
+
202
+
203
+ def _command_auth_list(args, out, err, *, include_remote: bool = True) -> int:
204
+ active, rows = (
205
+ _account_rows_with_remote_state() if include_remote else _public_accounts()
206
+ )
207
+ if args.json:
208
+ _write_json({"active_account": active or None, "accounts": rows}, out)
209
+ return 0
210
+ if not rows:
211
+ out.write("No workstation accounts. Run 'rcc auth login'.\n")
212
+ return 0
213
+ for row in rows:
214
+ marker = "*" if row["active"] else " "
215
+ login = "logged in" if row["logged_in"] else "logged out"
216
+ credits = row.get("credits")
217
+ credit_text = "unknown" if credits is None else str(credits)
218
+ out.write(
219
+ f"{marker} {row['name']} {row['email'] or 'unknown email'} "
220
+ f"[{login}; credits={credit_text}; "
221
+ f"expires={row['expires_at'] or 'unknown'}]\n"
222
+ )
223
+ if row.get("remote_error"):
224
+ out.write(f" remote status: {row['remote_error']}\n")
225
+ return 0