pltr-cli 0.11.0__py3-none-any.whl → 0.13.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.
- pltr/__init__.py +1 -1
- pltr/cli.py +40 -0
- pltr/commands/admin.py +565 -11
- pltr/commands/aip_agents.py +333 -0
- pltr/commands/connectivity.py +309 -1
- pltr/commands/cp.py +103 -0
- pltr/commands/dataset.py +104 -4
- pltr/commands/functions.py +503 -0
- pltr/commands/language_models.py +515 -0
- pltr/commands/mediasets.py +176 -0
- pltr/commands/models.py +362 -0
- pltr/commands/ontology.py +44 -13
- pltr/commands/orchestration.py +167 -11
- pltr/commands/project.py +231 -22
- pltr/commands/resource.py +416 -17
- pltr/commands/space.py +25 -303
- pltr/commands/sql.py +54 -7
- pltr/commands/streams.py +616 -0
- pltr/commands/third_party_applications.py +82 -0
- pltr/services/admin.py +331 -3
- pltr/services/aip_agents.py +147 -0
- pltr/services/base.py +104 -1
- pltr/services/connectivity.py +139 -0
- pltr/services/copy.py +391 -0
- pltr/services/dataset.py +77 -4
- pltr/services/folder.py +6 -1
- pltr/services/functions.py +223 -0
- pltr/services/language_models.py +281 -0
- pltr/services/mediasets.py +144 -9
- pltr/services/models.py +179 -0
- pltr/services/ontology.py +48 -1
- pltr/services/orchestration.py +133 -1
- pltr/services/project.py +213 -39
- pltr/services/resource.py +229 -60
- pltr/services/space.py +24 -175
- pltr/services/sql.py +44 -20
- pltr/services/streams.py +290 -0
- pltr/services/third_party_applications.py +53 -0
- pltr/utils/formatting.py +195 -1
- pltr/utils/pagination.py +325 -0
- {pltr_cli-0.11.0.dist-info → pltr_cli-0.13.0.dist-info}/METADATA +55 -4
- pltr_cli-0.13.0.dist-info/RECORD +70 -0
- {pltr_cli-0.11.0.dist-info → pltr_cli-0.13.0.dist-info}/WHEEL +1 -1
- pltr_cli-0.11.0.dist-info/RECORD +0 -55
- {pltr_cli-0.11.0.dist-info → pltr_cli-0.13.0.dist-info}/entry_points.txt +0 -0
- {pltr_cli-0.11.0.dist-info → pltr_cli-0.13.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AIP Agents management commands for Foundry.
|
|
3
|
+
Provides commands for agent inspection, session management, and version control.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
from typing import Optional
|
|
8
|
+
from rich.console import Console
|
|
9
|
+
|
|
10
|
+
from ..services.aip_agents import AipAgentsService
|
|
11
|
+
from ..utils.formatting import OutputFormatter
|
|
12
|
+
from ..utils.progress import SpinnerProgressTracker
|
|
13
|
+
from ..utils.pagination import PaginationConfig
|
|
14
|
+
from ..auth.base import ProfileNotFoundError, MissingCredentialsError
|
|
15
|
+
from ..utils.completion import (
|
|
16
|
+
complete_rid,
|
|
17
|
+
complete_profile,
|
|
18
|
+
complete_output_format,
|
|
19
|
+
cache_rid,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
# Create main app and sub-apps
|
|
23
|
+
app = typer.Typer(help="Manage AIP Agents, sessions, and versions")
|
|
24
|
+
sessions_app = typer.Typer(help="Manage agent conversation sessions")
|
|
25
|
+
versions_app = typer.Typer(help="Manage agent versions")
|
|
26
|
+
|
|
27
|
+
# Add sub-apps
|
|
28
|
+
app.add_typer(sessions_app, name="sessions")
|
|
29
|
+
app.add_typer(versions_app, name="versions")
|
|
30
|
+
|
|
31
|
+
console = Console()
|
|
32
|
+
formatter = OutputFormatter(console)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@app.command("get")
|
|
36
|
+
def get_agent(
|
|
37
|
+
agent_rid: str = typer.Argument(
|
|
38
|
+
...,
|
|
39
|
+
help="Agent Resource Identifier (e.g., ri.foundry.main.agent.abc123)",
|
|
40
|
+
autocompletion=complete_rid,
|
|
41
|
+
),
|
|
42
|
+
version: Optional[str] = typer.Option(
|
|
43
|
+
None,
|
|
44
|
+
"--version",
|
|
45
|
+
"-v",
|
|
46
|
+
help="Agent version to retrieve (e.g., '1.0'). Defaults to latest published.",
|
|
47
|
+
),
|
|
48
|
+
profile: Optional[str] = typer.Option(
|
|
49
|
+
None,
|
|
50
|
+
"--profile",
|
|
51
|
+
"-p",
|
|
52
|
+
help="Profile name",
|
|
53
|
+
autocompletion=complete_profile,
|
|
54
|
+
),
|
|
55
|
+
format: str = typer.Option(
|
|
56
|
+
"table",
|
|
57
|
+
"--format",
|
|
58
|
+
"-f",
|
|
59
|
+
help="Output format (table, json, csv)",
|
|
60
|
+
autocompletion=complete_output_format,
|
|
61
|
+
),
|
|
62
|
+
output: Optional[str] = typer.Option(
|
|
63
|
+
None, "--output", "-o", help="Output file path"
|
|
64
|
+
),
|
|
65
|
+
):
|
|
66
|
+
"""
|
|
67
|
+
Get detailed information about an AIP Agent.
|
|
68
|
+
|
|
69
|
+
Retrieves agent configuration including name, description, parameters,
|
|
70
|
+
and version information.
|
|
71
|
+
|
|
72
|
+
Examples:
|
|
73
|
+
|
|
74
|
+
# Get latest published version of agent
|
|
75
|
+
pltr aip-agents get ri.foundry.main.agent.abc123
|
|
76
|
+
|
|
77
|
+
# Get specific version
|
|
78
|
+
pltr aip-agents get ri.foundry.main.agent.abc123 --version 1.5
|
|
79
|
+
|
|
80
|
+
# Output as JSON
|
|
81
|
+
pltr aip-agents get ri.foundry.main.agent.abc123 --format json
|
|
82
|
+
"""
|
|
83
|
+
try:
|
|
84
|
+
cache_rid(agent_rid)
|
|
85
|
+
|
|
86
|
+
service = AipAgentsService(profile=profile)
|
|
87
|
+
|
|
88
|
+
with SpinnerProgressTracker().track_spinner(f"Fetching agent {agent_rid}..."):
|
|
89
|
+
agent = service.get_agent(agent_rid, version=version)
|
|
90
|
+
|
|
91
|
+
if output:
|
|
92
|
+
formatter.save_to_file(agent, output, format)
|
|
93
|
+
formatter.print_success(f"Agent information saved to {output}")
|
|
94
|
+
else:
|
|
95
|
+
formatter.display(agent, format)
|
|
96
|
+
|
|
97
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
98
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
99
|
+
raise typer.Exit(1)
|
|
100
|
+
except ValueError as e:
|
|
101
|
+
formatter.print_error(f"Invalid request: {e}")
|
|
102
|
+
raise typer.Exit(1)
|
|
103
|
+
except Exception as e:
|
|
104
|
+
formatter.print_error(f"Failed to get agent: {e}")
|
|
105
|
+
raise typer.Exit(1)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@sessions_app.command("list")
|
|
109
|
+
def list_sessions(
|
|
110
|
+
agent_rid: str = typer.Argument(
|
|
111
|
+
...,
|
|
112
|
+
help="Agent Resource Identifier",
|
|
113
|
+
autocompletion=complete_rid,
|
|
114
|
+
),
|
|
115
|
+
profile: Optional[str] = typer.Option(
|
|
116
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
117
|
+
),
|
|
118
|
+
format: str = typer.Option(
|
|
119
|
+
"table",
|
|
120
|
+
"--format",
|
|
121
|
+
"-f",
|
|
122
|
+
help="Output format (table, json, csv)",
|
|
123
|
+
autocompletion=complete_output_format,
|
|
124
|
+
),
|
|
125
|
+
output: Optional[str] = typer.Option(
|
|
126
|
+
None, "--output", "-o", help="Output file path"
|
|
127
|
+
),
|
|
128
|
+
page_size: Optional[int] = typer.Option(
|
|
129
|
+
None, "--page-size", help="Number of sessions per page"
|
|
130
|
+
),
|
|
131
|
+
max_pages: Optional[int] = typer.Option(
|
|
132
|
+
1, "--max-pages", help="Maximum number of pages to fetch (default: 1)"
|
|
133
|
+
),
|
|
134
|
+
all: bool = typer.Option(
|
|
135
|
+
False, "--all", help="Fetch all available sessions (overrides --max-pages)"
|
|
136
|
+
),
|
|
137
|
+
):
|
|
138
|
+
"""
|
|
139
|
+
List conversation sessions for an agent.
|
|
140
|
+
|
|
141
|
+
Only lists sessions created by this client (API). Sessions created
|
|
142
|
+
in AIP Agent Studio will not appear.
|
|
143
|
+
|
|
144
|
+
Examples:
|
|
145
|
+
|
|
146
|
+
# List first page of sessions
|
|
147
|
+
pltr aip-agents sessions list ri.foundry.main.agent.abc123
|
|
148
|
+
|
|
149
|
+
# List all sessions
|
|
150
|
+
pltr aip-agents sessions list ri.foundry.main.agent.abc123 --all
|
|
151
|
+
|
|
152
|
+
# List first 3 pages with 50 sessions each
|
|
153
|
+
pltr aip-agents sessions list ri.foundry.main.agent.abc123 \\
|
|
154
|
+
--page-size 50 --max-pages 3
|
|
155
|
+
"""
|
|
156
|
+
try:
|
|
157
|
+
cache_rid(agent_rid)
|
|
158
|
+
|
|
159
|
+
service = AipAgentsService(profile=profile)
|
|
160
|
+
config = PaginationConfig(
|
|
161
|
+
page_size=page_size,
|
|
162
|
+
max_pages=max_pages,
|
|
163
|
+
fetch_all=all,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
with SpinnerProgressTracker().track_spinner(
|
|
167
|
+
f"Fetching sessions for agent {agent_rid}..."
|
|
168
|
+
):
|
|
169
|
+
result = service.list_sessions(agent_rid, config)
|
|
170
|
+
|
|
171
|
+
if not result.data:
|
|
172
|
+
console.print("[yellow]No sessions found for this agent[/yellow]")
|
|
173
|
+
return
|
|
174
|
+
|
|
175
|
+
if output:
|
|
176
|
+
formatter.format_paginated_output(result, format, output)
|
|
177
|
+
console.print(f"[green]Results saved to {output}[/green]")
|
|
178
|
+
else:
|
|
179
|
+
formatter.format_paginated_output(result, format)
|
|
180
|
+
|
|
181
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
182
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
183
|
+
raise typer.Exit(1)
|
|
184
|
+
except Exception as e:
|
|
185
|
+
formatter.print_error(f"Failed to list sessions: {e}")
|
|
186
|
+
raise typer.Exit(1)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
@sessions_app.command("get")
|
|
190
|
+
def get_session(
|
|
191
|
+
agent_rid: str = typer.Argument(
|
|
192
|
+
...,
|
|
193
|
+
help="Agent Resource Identifier",
|
|
194
|
+
autocompletion=complete_rid,
|
|
195
|
+
),
|
|
196
|
+
session_rid: str = typer.Argument(
|
|
197
|
+
...,
|
|
198
|
+
help="Session Resource Identifier",
|
|
199
|
+
autocompletion=complete_rid,
|
|
200
|
+
),
|
|
201
|
+
profile: Optional[str] = typer.Option(
|
|
202
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
203
|
+
),
|
|
204
|
+
format: str = typer.Option(
|
|
205
|
+
"table",
|
|
206
|
+
"--format",
|
|
207
|
+
"-f",
|
|
208
|
+
help="Output format (table, json, csv)",
|
|
209
|
+
autocompletion=complete_output_format,
|
|
210
|
+
),
|
|
211
|
+
output: Optional[str] = typer.Option(
|
|
212
|
+
None, "--output", "-o", help="Output file path"
|
|
213
|
+
),
|
|
214
|
+
):
|
|
215
|
+
"""
|
|
216
|
+
Get detailed information about a conversation session.
|
|
217
|
+
|
|
218
|
+
Examples:
|
|
219
|
+
|
|
220
|
+
# Get session details
|
|
221
|
+
pltr aip-agents sessions get \\
|
|
222
|
+
ri.foundry.main.agent.abc123 \\
|
|
223
|
+
ri.foundry.main.session.xyz789
|
|
224
|
+
|
|
225
|
+
# Export session details to JSON
|
|
226
|
+
pltr aip-agents sessions get \\
|
|
227
|
+
ri.foundry.main.agent.abc123 \\
|
|
228
|
+
ri.foundry.main.session.xyz789 \\
|
|
229
|
+
--format json --output session.json
|
|
230
|
+
"""
|
|
231
|
+
try:
|
|
232
|
+
cache_rid(agent_rid)
|
|
233
|
+
cache_rid(session_rid)
|
|
234
|
+
|
|
235
|
+
service = AipAgentsService(profile=profile)
|
|
236
|
+
|
|
237
|
+
with SpinnerProgressTracker().track_spinner(
|
|
238
|
+
f"Fetching session {session_rid}..."
|
|
239
|
+
):
|
|
240
|
+
session = service.get_session(agent_rid, session_rid)
|
|
241
|
+
|
|
242
|
+
if output:
|
|
243
|
+
formatter.save_to_file(session, output, format)
|
|
244
|
+
formatter.print_success(f"Session information saved to {output}")
|
|
245
|
+
else:
|
|
246
|
+
formatter.display(session, format)
|
|
247
|
+
|
|
248
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
249
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
250
|
+
raise typer.Exit(1)
|
|
251
|
+
except Exception as e:
|
|
252
|
+
formatter.print_error(f"Failed to get session: {e}")
|
|
253
|
+
raise typer.Exit(1)
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
@versions_app.command("list")
|
|
257
|
+
def list_versions(
|
|
258
|
+
agent_rid: str = typer.Argument(
|
|
259
|
+
...,
|
|
260
|
+
help="Agent Resource Identifier",
|
|
261
|
+
autocompletion=complete_rid,
|
|
262
|
+
),
|
|
263
|
+
profile: Optional[str] = typer.Option(
|
|
264
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
265
|
+
),
|
|
266
|
+
format: str = typer.Option(
|
|
267
|
+
"table",
|
|
268
|
+
"--format",
|
|
269
|
+
"-f",
|
|
270
|
+
help="Output format (table, json, csv)",
|
|
271
|
+
autocompletion=complete_output_format,
|
|
272
|
+
),
|
|
273
|
+
output: Optional[str] = typer.Option(
|
|
274
|
+
None, "--output", "-o", help="Output file path"
|
|
275
|
+
),
|
|
276
|
+
page_size: Optional[int] = typer.Option(
|
|
277
|
+
None, "--page-size", help="Number of versions per page"
|
|
278
|
+
),
|
|
279
|
+
max_pages: Optional[int] = typer.Option(
|
|
280
|
+
1, "--max-pages", help="Maximum number of pages to fetch (default: 1)"
|
|
281
|
+
),
|
|
282
|
+
all: bool = typer.Option(
|
|
283
|
+
False, "--all", help="Fetch all available versions (overrides --max-pages)"
|
|
284
|
+
),
|
|
285
|
+
):
|
|
286
|
+
"""
|
|
287
|
+
List all versions for an AIP Agent.
|
|
288
|
+
|
|
289
|
+
Versions are returned in descending order (most recent first).
|
|
290
|
+
|
|
291
|
+
Examples:
|
|
292
|
+
|
|
293
|
+
# List first page of versions
|
|
294
|
+
pltr aip-agents versions list ri.foundry.main.agent.abc123
|
|
295
|
+
|
|
296
|
+
# List all versions
|
|
297
|
+
pltr aip-agents versions list ri.foundry.main.agent.abc123 --all
|
|
298
|
+
|
|
299
|
+
# Export all versions to CSV
|
|
300
|
+
pltr aip-agents versions list ri.foundry.main.agent.abc123 \\
|
|
301
|
+
--all --format csv --output versions.csv
|
|
302
|
+
"""
|
|
303
|
+
try:
|
|
304
|
+
cache_rid(agent_rid)
|
|
305
|
+
|
|
306
|
+
service = AipAgentsService(profile=profile)
|
|
307
|
+
config = PaginationConfig(
|
|
308
|
+
page_size=page_size,
|
|
309
|
+
max_pages=max_pages,
|
|
310
|
+
fetch_all=all,
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
with SpinnerProgressTracker().track_spinner(
|
|
314
|
+
f"Fetching versions for agent {agent_rid}..."
|
|
315
|
+
):
|
|
316
|
+
result = service.list_versions(agent_rid, config)
|
|
317
|
+
|
|
318
|
+
if not result.data:
|
|
319
|
+
console.print("[yellow]No versions found for this agent[/yellow]")
|
|
320
|
+
return
|
|
321
|
+
|
|
322
|
+
if output:
|
|
323
|
+
formatter.format_paginated_output(result, format, output)
|
|
324
|
+
console.print(f"[green]Results saved to {output}[/green]")
|
|
325
|
+
else:
|
|
326
|
+
formatter.format_paginated_output(result, format)
|
|
327
|
+
|
|
328
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
329
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
330
|
+
raise typer.Exit(1)
|
|
331
|
+
except Exception as e:
|
|
332
|
+
formatter.print_error(f"Failed to list versions: {e}")
|
|
333
|
+
raise typer.Exit(1)
|
pltr/commands/connectivity.py
CHANGED
|
@@ -4,7 +4,8 @@ Connectivity management commands for Foundry connections and imports.
|
|
|
4
4
|
|
|
5
5
|
import typer
|
|
6
6
|
import json
|
|
7
|
-
from
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import List, Optional
|
|
8
9
|
from rich.console import Console
|
|
9
10
|
|
|
10
11
|
from ..services.connectivity import ConnectivityService
|
|
@@ -29,6 +30,53 @@ app.add_typer(connection_app, name="connection", help="Manage connections")
|
|
|
29
30
|
app.add_typer(import_app, name="import", help="Manage data imports")
|
|
30
31
|
|
|
31
32
|
|
|
33
|
+
def _load_json_param(
|
|
34
|
+
json_str: Optional[str], file_path: Optional[str], param_name: str
|
|
35
|
+
) -> dict:
|
|
36
|
+
"""
|
|
37
|
+
Load JSON from either a string or a file.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
json_str: JSON string (optional)
|
|
41
|
+
file_path: Path to JSON file (optional)
|
|
42
|
+
param_name: Name of parameter for error messages
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Parsed JSON dictionary
|
|
46
|
+
|
|
47
|
+
Raises:
|
|
48
|
+
typer.Exit: If neither or both are provided, or if parsing fails
|
|
49
|
+
"""
|
|
50
|
+
if json_str and file_path:
|
|
51
|
+
console.print(
|
|
52
|
+
f"[red]Cannot specify both {param_name} and {param_name}-file[/red]"
|
|
53
|
+
)
|
|
54
|
+
raise typer.Exit(1)
|
|
55
|
+
|
|
56
|
+
if not json_str and not file_path:
|
|
57
|
+
console.print(
|
|
58
|
+
f"[red]Must specify either {param_name} or --{param_name}-file[/red]"
|
|
59
|
+
)
|
|
60
|
+
raise typer.Exit(1)
|
|
61
|
+
|
|
62
|
+
if file_path:
|
|
63
|
+
path = Path(file_path)
|
|
64
|
+
if not path.exists():
|
|
65
|
+
console.print(f"[red]File not found: {file_path}[/red]")
|
|
66
|
+
raise typer.Exit(1)
|
|
67
|
+
try:
|
|
68
|
+
json_str = path.read_text()
|
|
69
|
+
except Exception as e:
|
|
70
|
+
console.print(f"[red]Error reading {file_path}: {e}[/red]")
|
|
71
|
+
raise typer.Exit(1)
|
|
72
|
+
|
|
73
|
+
try:
|
|
74
|
+
return json.loads(json_str) # type: ignore[arg-type]
|
|
75
|
+
except json.JSONDecodeError as e:
|
|
76
|
+
console.print(f"[red]Invalid JSON for {param_name}: {e}[/red]")
|
|
77
|
+
raise typer.Exit(1)
|
|
78
|
+
|
|
79
|
+
|
|
32
80
|
@connection_app.command("list")
|
|
33
81
|
def list_connections(
|
|
34
82
|
profile: Optional[str] = typer.Option(
|
|
@@ -104,6 +152,266 @@ def get_connection(
|
|
|
104
152
|
raise typer.Exit(1)
|
|
105
153
|
|
|
106
154
|
|
|
155
|
+
@connection_app.command("create")
|
|
156
|
+
def create_connection(
|
|
157
|
+
display_name: str = typer.Argument(..., help="Display name for the connection"),
|
|
158
|
+
parent_folder_rid: str = typer.Argument(
|
|
159
|
+
..., help="Parent folder Resource Identifier", autocompletion=complete_rid
|
|
160
|
+
),
|
|
161
|
+
configuration: Optional[str] = typer.Argument(
|
|
162
|
+
None, help="Connection configuration in JSON format"
|
|
163
|
+
),
|
|
164
|
+
worker: Optional[str] = typer.Argument(
|
|
165
|
+
None, help="Worker configuration in JSON format"
|
|
166
|
+
),
|
|
167
|
+
config_file: Optional[str] = typer.Option(
|
|
168
|
+
None, "--config-file", help="Path to JSON file with connection configuration"
|
|
169
|
+
),
|
|
170
|
+
worker_file: Optional[str] = typer.Option(
|
|
171
|
+
None, "--worker-file", help="Path to JSON file with worker configuration"
|
|
172
|
+
),
|
|
173
|
+
profile: Optional[str] = typer.Option(
|
|
174
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
175
|
+
),
|
|
176
|
+
format: str = typer.Option(
|
|
177
|
+
"table",
|
|
178
|
+
"--format",
|
|
179
|
+
"-f",
|
|
180
|
+
help="Output format (table, json, csv)",
|
|
181
|
+
autocompletion=complete_output_format,
|
|
182
|
+
),
|
|
183
|
+
output: Optional[str] = typer.Option(
|
|
184
|
+
None, "--output", "-o", help="Output file path"
|
|
185
|
+
),
|
|
186
|
+
):
|
|
187
|
+
"""Create a new connection.
|
|
188
|
+
|
|
189
|
+
Configuration and worker can be provided as JSON strings or via file options.
|
|
190
|
+
"""
|
|
191
|
+
try:
|
|
192
|
+
cache_rid(parent_folder_rid)
|
|
193
|
+
|
|
194
|
+
# Load configuration from string or file
|
|
195
|
+
config_dict = _load_json_param(configuration, config_file, "configuration")
|
|
196
|
+
worker_dict = _load_json_param(worker, worker_file, "worker")
|
|
197
|
+
|
|
198
|
+
service = ConnectivityService(profile=profile)
|
|
199
|
+
|
|
200
|
+
with SpinnerProgressTracker().track_spinner("Creating connection..."):
|
|
201
|
+
connection = service.create_connection(
|
|
202
|
+
display_name=display_name,
|
|
203
|
+
parent_folder_rid=parent_folder_rid,
|
|
204
|
+
configuration=config_dict,
|
|
205
|
+
worker=worker_dict,
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
cache_rid(connection.get("rid", ""))
|
|
209
|
+
console.print(f"[green]Connection created: {connection.get('rid')}[/green]")
|
|
210
|
+
formatter.format_output([connection], format, output)
|
|
211
|
+
|
|
212
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
213
|
+
console.print(f"[red]Authentication error: {e}[/red]")
|
|
214
|
+
raise typer.Exit(1)
|
|
215
|
+
except Exception as e:
|
|
216
|
+
console.print(f"[red]Error creating connection: {e}[/red]")
|
|
217
|
+
raise typer.Exit(1)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
@connection_app.command("get-config")
|
|
221
|
+
def get_connection_configuration(
|
|
222
|
+
connection_rid: str = typer.Argument(
|
|
223
|
+
..., help="Connection Resource Identifier", autocompletion=complete_rid
|
|
224
|
+
),
|
|
225
|
+
profile: Optional[str] = typer.Option(
|
|
226
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
227
|
+
),
|
|
228
|
+
format: str = typer.Option(
|
|
229
|
+
"json",
|
|
230
|
+
"--format",
|
|
231
|
+
"-f",
|
|
232
|
+
help="Output format (table, json, csv)",
|
|
233
|
+
autocompletion=complete_output_format,
|
|
234
|
+
),
|
|
235
|
+
output: Optional[str] = typer.Option(
|
|
236
|
+
None, "--output", "-o", help="Output file path"
|
|
237
|
+
),
|
|
238
|
+
):
|
|
239
|
+
"""Get connection configuration."""
|
|
240
|
+
try:
|
|
241
|
+
cache_rid(connection_rid)
|
|
242
|
+
|
|
243
|
+
with SpinnerProgressTracker().track_spinner(
|
|
244
|
+
f"Fetching configuration for {connection_rid}..."
|
|
245
|
+
):
|
|
246
|
+
service = ConnectivityService(profile=profile)
|
|
247
|
+
config = service.get_connection_configuration(connection_rid)
|
|
248
|
+
|
|
249
|
+
formatter.format_output([config], format, output)
|
|
250
|
+
|
|
251
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
252
|
+
console.print(f"[red]Authentication error: {e}[/red]")
|
|
253
|
+
raise typer.Exit(1)
|
|
254
|
+
except Exception as e:
|
|
255
|
+
console.print(f"[red]Error getting connection configuration: {e}[/red]")
|
|
256
|
+
raise typer.Exit(1)
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
@connection_app.command("update-secrets")
|
|
260
|
+
def update_connection_secrets(
|
|
261
|
+
connection_rid: str = typer.Argument(
|
|
262
|
+
..., help="Connection Resource Identifier", autocompletion=complete_rid
|
|
263
|
+
),
|
|
264
|
+
secrets_file: str = typer.Option(
|
|
265
|
+
...,
|
|
266
|
+
"--secrets-file",
|
|
267
|
+
"-s",
|
|
268
|
+
help="Path to JSON file containing secrets (mapping secret names to values)",
|
|
269
|
+
),
|
|
270
|
+
profile: Optional[str] = typer.Option(
|
|
271
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
272
|
+
),
|
|
273
|
+
):
|
|
274
|
+
"""Update connection secrets.
|
|
275
|
+
|
|
276
|
+
Secrets must be provided via a file for security (to avoid exposure in shell
|
|
277
|
+
history or process listings).
|
|
278
|
+
"""
|
|
279
|
+
try:
|
|
280
|
+
cache_rid(connection_rid)
|
|
281
|
+
|
|
282
|
+
# Load secrets from file
|
|
283
|
+
path = Path(secrets_file)
|
|
284
|
+
if not path.exists():
|
|
285
|
+
console.print(f"[red]Secrets file not found: {secrets_file}[/red]")
|
|
286
|
+
raise typer.Exit(1)
|
|
287
|
+
|
|
288
|
+
try:
|
|
289
|
+
secrets_content = path.read_text()
|
|
290
|
+
secrets_dict = json.loads(secrets_content)
|
|
291
|
+
except json.JSONDecodeError as e:
|
|
292
|
+
console.print(f"[red]Invalid JSON in secrets file: {e}[/red]")
|
|
293
|
+
raise typer.Exit(1)
|
|
294
|
+
except Exception as e:
|
|
295
|
+
console.print(f"[red]Error reading secrets file: {e}[/red]")
|
|
296
|
+
raise typer.Exit(1)
|
|
297
|
+
|
|
298
|
+
service = ConnectivityService(profile=profile)
|
|
299
|
+
|
|
300
|
+
with SpinnerProgressTracker().track_spinner("Updating secrets..."):
|
|
301
|
+
service.update_secrets(connection_rid, secrets_dict)
|
|
302
|
+
|
|
303
|
+
console.print(
|
|
304
|
+
f"[green]Secrets updated for connection: {connection_rid}[/green]"
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
308
|
+
console.print(f"[red]Authentication error: {e}[/red]")
|
|
309
|
+
raise typer.Exit(1)
|
|
310
|
+
except Exception as e:
|
|
311
|
+
console.print(f"[red]Error updating secrets: {e}[/red]")
|
|
312
|
+
raise typer.Exit(1)
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
@connection_app.command("update-export-settings")
|
|
316
|
+
def update_export_settings(
|
|
317
|
+
connection_rid: str = typer.Argument(
|
|
318
|
+
..., help="Connection Resource Identifier", autocompletion=complete_rid
|
|
319
|
+
),
|
|
320
|
+
settings: Optional[str] = typer.Argument(
|
|
321
|
+
None, help="Export settings in JSON format"
|
|
322
|
+
),
|
|
323
|
+
settings_file: Optional[str] = typer.Option(
|
|
324
|
+
None, "--settings-file", help="Path to JSON file with export settings"
|
|
325
|
+
),
|
|
326
|
+
profile: Optional[str] = typer.Option(
|
|
327
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
328
|
+
),
|
|
329
|
+
):
|
|
330
|
+
"""Update connection export settings.
|
|
331
|
+
|
|
332
|
+
Settings can be provided as a JSON string or via --settings-file.
|
|
333
|
+
"""
|
|
334
|
+
try:
|
|
335
|
+
cache_rid(connection_rid)
|
|
336
|
+
|
|
337
|
+
# Load settings from string or file
|
|
338
|
+
settings_dict = _load_json_param(settings, settings_file, "settings")
|
|
339
|
+
|
|
340
|
+
service = ConnectivityService(profile=profile)
|
|
341
|
+
|
|
342
|
+
with SpinnerProgressTracker().track_spinner("Updating export settings..."):
|
|
343
|
+
service.update_export_settings(connection_rid, settings_dict)
|
|
344
|
+
|
|
345
|
+
console.print(
|
|
346
|
+
f"[green]Export settings updated for connection: {connection_rid}[/green]"
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
350
|
+
console.print(f"[red]Authentication error: {e}[/red]")
|
|
351
|
+
raise typer.Exit(1)
|
|
352
|
+
except Exception as e:
|
|
353
|
+
console.print(f"[red]Error updating export settings: {e}[/red]")
|
|
354
|
+
raise typer.Exit(1)
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
@connection_app.command("upload-jdbc-drivers")
|
|
358
|
+
def upload_jdbc_drivers(
|
|
359
|
+
connection_rid: str = typer.Argument(
|
|
360
|
+
..., help="Connection Resource Identifier", autocompletion=complete_rid
|
|
361
|
+
),
|
|
362
|
+
driver_files: List[str] = typer.Argument(
|
|
363
|
+
..., help="Path(s) to JAR file(s) to upload"
|
|
364
|
+
),
|
|
365
|
+
profile: Optional[str] = typer.Option(
|
|
366
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
367
|
+
),
|
|
368
|
+
format: str = typer.Option(
|
|
369
|
+
"table",
|
|
370
|
+
"--format",
|
|
371
|
+
"-f",
|
|
372
|
+
help="Output format (table, json, csv)",
|
|
373
|
+
autocompletion=complete_output_format,
|
|
374
|
+
),
|
|
375
|
+
output: Optional[str] = typer.Option(
|
|
376
|
+
None, "--output", "-o", help="Output file path"
|
|
377
|
+
),
|
|
378
|
+
):
|
|
379
|
+
"""Upload custom JDBC drivers to a connection.
|
|
380
|
+
|
|
381
|
+
Only JAR files are supported.
|
|
382
|
+
"""
|
|
383
|
+
try:
|
|
384
|
+
cache_rid(connection_rid)
|
|
385
|
+
|
|
386
|
+
# Validate files exist and are JAR files before uploading
|
|
387
|
+
for driver_file in driver_files:
|
|
388
|
+
path = Path(driver_file)
|
|
389
|
+
if not path.exists():
|
|
390
|
+
console.print(f"[red]File not found: {driver_file}[/red]")
|
|
391
|
+
raise typer.Exit(1)
|
|
392
|
+
if path.suffix.lower() != ".jar":
|
|
393
|
+
console.print(f"[red]File must be a JAR file: {driver_file}[/red]")
|
|
394
|
+
raise typer.Exit(1)
|
|
395
|
+
|
|
396
|
+
service = ConnectivityService(profile=profile)
|
|
397
|
+
results = []
|
|
398
|
+
|
|
399
|
+
for driver_file in driver_files:
|
|
400
|
+
with SpinnerProgressTracker().track_spinner(f"Uploading {driver_file}..."):
|
|
401
|
+
result = service.upload_custom_jdbc_drivers(connection_rid, driver_file)
|
|
402
|
+
results.append(result)
|
|
403
|
+
console.print(f"[green]Uploaded: {driver_file}[/green]")
|
|
404
|
+
|
|
405
|
+
formatter.format_output(results, format, output)
|
|
406
|
+
|
|
407
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
408
|
+
console.print(f"[red]Authentication error: {e}[/red]")
|
|
409
|
+
raise typer.Exit(1)
|
|
410
|
+
except Exception as e:
|
|
411
|
+
console.print(f"[red]Error uploading JDBC drivers: {e}[/red]")
|
|
412
|
+
raise typer.Exit(1)
|
|
413
|
+
|
|
414
|
+
|
|
107
415
|
@import_app.command("file")
|
|
108
416
|
def import_file(
|
|
109
417
|
connection_rid: str = typer.Argument(
|