pltr-cli 0.5.0__py3-none-any.whl → 0.5.2__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 +14 -0
- pltr/commands/connectivity.py +432 -0
- pltr/commands/dataset.py +268 -0
- pltr/commands/project.py +440 -0
- pltr/commands/resource.py +499 -0
- pltr/commands/resource_role.py +454 -0
- pltr/commands/space.py +662 -0
- pltr/services/connectivity.py +305 -0
- pltr/services/dataset.py +149 -15
- pltr/services/project.py +232 -0
- pltr/services/resource.py +289 -0
- pltr/services/resource_role.py +321 -0
- pltr/services/space.py +354 -0
- pltr/utils/formatting.py +108 -1
- {pltr_cli-0.5.0.dist-info → pltr_cli-0.5.2.dist-info}/METADATA +101 -2
- {pltr_cli-0.5.0.dist-info → pltr_cli-0.5.2.dist-info}/RECORD +20 -10
- {pltr_cli-0.5.0.dist-info → pltr_cli-0.5.2.dist-info}/WHEEL +0 -0
- {pltr_cli-0.5.0.dist-info → pltr_cli-0.5.2.dist-info}/entry_points.txt +0 -0
- {pltr_cli-0.5.0.dist-info → pltr_cli-0.5.2.dist-info}/licenses/LICENSE +0 -0
pltr/commands/space.py
ADDED
|
@@ -0,0 +1,662 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Space management commands for Foundry filesystem.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
from typing import Optional, List
|
|
7
|
+
from rich.console import Console
|
|
8
|
+
from rich.table import Table
|
|
9
|
+
|
|
10
|
+
from ..services.space import SpaceService
|
|
11
|
+
from ..utils.formatting import OutputFormatter
|
|
12
|
+
from ..utils.progress import SpinnerProgressTracker
|
|
13
|
+
from ..auth.base import ProfileNotFoundError, MissingCredentialsError
|
|
14
|
+
from ..utils.completion import (
|
|
15
|
+
complete_rid,
|
|
16
|
+
complete_profile,
|
|
17
|
+
complete_output_format,
|
|
18
|
+
cache_rid,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
app = typer.Typer()
|
|
22
|
+
console = Console()
|
|
23
|
+
formatter = OutputFormatter(console)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@app.command("create")
|
|
27
|
+
def create_space(
|
|
28
|
+
name: str = typer.Argument(..., help="Space display name"),
|
|
29
|
+
organization_rid: str = typer.Option(
|
|
30
|
+
...,
|
|
31
|
+
"--organization-rid",
|
|
32
|
+
"-org",
|
|
33
|
+
help="Organization Resource Identifier",
|
|
34
|
+
autocompletion=complete_rid,
|
|
35
|
+
),
|
|
36
|
+
description: Optional[str] = typer.Option(
|
|
37
|
+
None, "--description", "-d", help="Space description"
|
|
38
|
+
),
|
|
39
|
+
profile: Optional[str] = typer.Option(
|
|
40
|
+
None, "--profile", help="Profile name", autocompletion=complete_profile
|
|
41
|
+
),
|
|
42
|
+
format: str = typer.Option(
|
|
43
|
+
"table",
|
|
44
|
+
"--format",
|
|
45
|
+
"-f",
|
|
46
|
+
help="Output format (table, json, csv)",
|
|
47
|
+
autocompletion=complete_output_format,
|
|
48
|
+
),
|
|
49
|
+
):
|
|
50
|
+
"""Create a new space in Foundry."""
|
|
51
|
+
try:
|
|
52
|
+
service = SpaceService(profile=profile)
|
|
53
|
+
|
|
54
|
+
with SpinnerProgressTracker().track_spinner(f"Creating space '{name}'..."):
|
|
55
|
+
space = service.create_space(
|
|
56
|
+
display_name=name,
|
|
57
|
+
organization_rid=organization_rid,
|
|
58
|
+
description=description,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# Cache the RID for future completions
|
|
62
|
+
if space.get("rid"):
|
|
63
|
+
cache_rid(space["rid"])
|
|
64
|
+
|
|
65
|
+
formatter.print_success(f"Successfully created space '{name}'")
|
|
66
|
+
formatter.print_info(f"Space RID: {space.get('rid', 'unknown')}")
|
|
67
|
+
formatter.print_info(
|
|
68
|
+
f"Root Folder RID: {space.get('root_folder_rid', 'unknown')}"
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# Format output
|
|
72
|
+
if format == "json":
|
|
73
|
+
formatter.format_dict(space)
|
|
74
|
+
elif format == "csv":
|
|
75
|
+
formatter.format_list([space])
|
|
76
|
+
else:
|
|
77
|
+
_format_space_table(space)
|
|
78
|
+
|
|
79
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
80
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
81
|
+
raise typer.Exit(1)
|
|
82
|
+
except Exception as e:
|
|
83
|
+
formatter.print_error(f"Failed to create space: {e}")
|
|
84
|
+
raise typer.Exit(1)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@app.command("get")
|
|
88
|
+
def get_space(
|
|
89
|
+
space_rid: str = typer.Argument(
|
|
90
|
+
..., help="Space Resource Identifier", autocompletion=complete_rid
|
|
91
|
+
),
|
|
92
|
+
profile: Optional[str] = typer.Option(
|
|
93
|
+
None, "--profile", help="Profile name", autocompletion=complete_profile
|
|
94
|
+
),
|
|
95
|
+
format: str = typer.Option(
|
|
96
|
+
"table",
|
|
97
|
+
"--format",
|
|
98
|
+
"-f",
|
|
99
|
+
help="Output format (table, json, csv)",
|
|
100
|
+
autocompletion=complete_output_format,
|
|
101
|
+
),
|
|
102
|
+
output: Optional[str] = typer.Option(
|
|
103
|
+
None, "--output", "-o", help="Output file path"
|
|
104
|
+
),
|
|
105
|
+
):
|
|
106
|
+
"""Get detailed information about a specific space."""
|
|
107
|
+
try:
|
|
108
|
+
# Cache the RID for future completions
|
|
109
|
+
cache_rid(space_rid)
|
|
110
|
+
|
|
111
|
+
service = SpaceService(profile=profile)
|
|
112
|
+
|
|
113
|
+
with SpinnerProgressTracker().track_spinner(f"Fetching space {space_rid}..."):
|
|
114
|
+
space = service.get_space(space_rid)
|
|
115
|
+
|
|
116
|
+
# Format output
|
|
117
|
+
if format == "json":
|
|
118
|
+
if output:
|
|
119
|
+
formatter.save_to_file(space, output, "json")
|
|
120
|
+
else:
|
|
121
|
+
formatter.format_dict(space)
|
|
122
|
+
elif format == "csv":
|
|
123
|
+
if output:
|
|
124
|
+
formatter.save_to_file([space], output, "csv")
|
|
125
|
+
else:
|
|
126
|
+
formatter.format_list([space])
|
|
127
|
+
else:
|
|
128
|
+
_format_space_table(space)
|
|
129
|
+
|
|
130
|
+
if output:
|
|
131
|
+
formatter.print_success(f"Space information saved to {output}")
|
|
132
|
+
|
|
133
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
134
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
135
|
+
raise typer.Exit(1)
|
|
136
|
+
except Exception as e:
|
|
137
|
+
formatter.print_error(f"Failed to get space: {e}")
|
|
138
|
+
raise typer.Exit(1)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
@app.command("list")
|
|
142
|
+
def list_spaces(
|
|
143
|
+
organization_rid: Optional[str] = typer.Option(
|
|
144
|
+
None,
|
|
145
|
+
"--organization-rid",
|
|
146
|
+
"-org",
|
|
147
|
+
help="Organization Resource Identifier to filter by",
|
|
148
|
+
autocompletion=complete_rid,
|
|
149
|
+
),
|
|
150
|
+
profile: Optional[str] = typer.Option(
|
|
151
|
+
None, "--profile", help="Profile name", autocompletion=complete_profile
|
|
152
|
+
),
|
|
153
|
+
format: str = typer.Option(
|
|
154
|
+
"table",
|
|
155
|
+
"--format",
|
|
156
|
+
"-f",
|
|
157
|
+
help="Output format (table, json, csv)",
|
|
158
|
+
autocompletion=complete_output_format,
|
|
159
|
+
),
|
|
160
|
+
output: Optional[str] = typer.Option(
|
|
161
|
+
None, "--output", "-o", help="Output file path"
|
|
162
|
+
),
|
|
163
|
+
page_size: Optional[int] = typer.Option(
|
|
164
|
+
None, "--page-size", help="Number of items per page"
|
|
165
|
+
),
|
|
166
|
+
):
|
|
167
|
+
"""List spaces, optionally filtered by organization."""
|
|
168
|
+
try:
|
|
169
|
+
service = SpaceService(profile=profile)
|
|
170
|
+
|
|
171
|
+
filter_desc = f" in organization {organization_rid}" if organization_rid else ""
|
|
172
|
+
with SpinnerProgressTracker().track_spinner(f"Listing spaces{filter_desc}..."):
|
|
173
|
+
spaces = service.list_spaces(
|
|
174
|
+
organization_rid=organization_rid, page_size=page_size
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
if not spaces:
|
|
178
|
+
formatter.print_info("No spaces found.")
|
|
179
|
+
return
|
|
180
|
+
|
|
181
|
+
# Format output
|
|
182
|
+
if format == "json":
|
|
183
|
+
if output:
|
|
184
|
+
formatter.save_to_file(spaces, output, "json")
|
|
185
|
+
else:
|
|
186
|
+
formatter.format_list(spaces)
|
|
187
|
+
elif format == "csv":
|
|
188
|
+
if output:
|
|
189
|
+
formatter.save_to_file(spaces, output, "csv")
|
|
190
|
+
else:
|
|
191
|
+
formatter.format_list(spaces)
|
|
192
|
+
else:
|
|
193
|
+
_format_spaces_table(spaces)
|
|
194
|
+
|
|
195
|
+
if output:
|
|
196
|
+
formatter.print_success(f"Spaces list saved to {output}")
|
|
197
|
+
|
|
198
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
199
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
200
|
+
raise typer.Exit(1)
|
|
201
|
+
except Exception as e:
|
|
202
|
+
formatter.print_error(f"Failed to list spaces: {e}")
|
|
203
|
+
raise typer.Exit(1)
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
@app.command("update")
|
|
207
|
+
def update_space(
|
|
208
|
+
space_rid: str = typer.Argument(
|
|
209
|
+
..., help="Space Resource Identifier", autocompletion=complete_rid
|
|
210
|
+
),
|
|
211
|
+
name: Optional[str] = typer.Option(
|
|
212
|
+
None, "--name", "-n", help="New space display name"
|
|
213
|
+
),
|
|
214
|
+
description: Optional[str] = typer.Option(
|
|
215
|
+
None, "--description", "-d", help="New space description"
|
|
216
|
+
),
|
|
217
|
+
profile: Optional[str] = typer.Option(
|
|
218
|
+
None, "--profile", help="Profile name", autocompletion=complete_profile
|
|
219
|
+
),
|
|
220
|
+
format: str = typer.Option(
|
|
221
|
+
"table",
|
|
222
|
+
"--format",
|
|
223
|
+
"-f",
|
|
224
|
+
help="Output format (table, json, csv)",
|
|
225
|
+
autocompletion=complete_output_format,
|
|
226
|
+
),
|
|
227
|
+
):
|
|
228
|
+
"""Update space information."""
|
|
229
|
+
try:
|
|
230
|
+
if not name and not description:
|
|
231
|
+
formatter.print_error(
|
|
232
|
+
"At least one field (--name or --description) must be provided"
|
|
233
|
+
)
|
|
234
|
+
raise typer.Exit(1)
|
|
235
|
+
|
|
236
|
+
service = SpaceService(profile=profile)
|
|
237
|
+
|
|
238
|
+
with SpinnerProgressTracker().track_spinner(f"Updating space {space_rid}..."):
|
|
239
|
+
space = service.update_space(
|
|
240
|
+
space_rid=space_rid,
|
|
241
|
+
display_name=name,
|
|
242
|
+
description=description,
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
formatter.print_success(f"Successfully updated space {space_rid}")
|
|
246
|
+
|
|
247
|
+
# Format output
|
|
248
|
+
if format == "json":
|
|
249
|
+
formatter.format_dict(space)
|
|
250
|
+
elif format == "csv":
|
|
251
|
+
formatter.format_list([space])
|
|
252
|
+
else:
|
|
253
|
+
_format_space_table(space)
|
|
254
|
+
|
|
255
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
256
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
257
|
+
raise typer.Exit(1)
|
|
258
|
+
except Exception as e:
|
|
259
|
+
formatter.print_error(f"Failed to update space: {e}")
|
|
260
|
+
raise typer.Exit(1)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
@app.command("delete")
|
|
264
|
+
def delete_space(
|
|
265
|
+
space_rid: str = typer.Argument(
|
|
266
|
+
..., help="Space Resource Identifier", autocompletion=complete_rid
|
|
267
|
+
),
|
|
268
|
+
profile: Optional[str] = typer.Option(
|
|
269
|
+
None, "--profile", help="Profile name", autocompletion=complete_profile
|
|
270
|
+
),
|
|
271
|
+
confirm: bool = typer.Option(False, "--confirm", help="Skip confirmation prompt"),
|
|
272
|
+
):
|
|
273
|
+
"""Delete a space."""
|
|
274
|
+
try:
|
|
275
|
+
if not confirm:
|
|
276
|
+
confirm_delete = typer.confirm(
|
|
277
|
+
f"Are you sure you want to delete space {space_rid}?"
|
|
278
|
+
)
|
|
279
|
+
if not confirm_delete:
|
|
280
|
+
formatter.print_info("Space deletion cancelled.")
|
|
281
|
+
return
|
|
282
|
+
|
|
283
|
+
service = SpaceService(profile=profile)
|
|
284
|
+
|
|
285
|
+
with SpinnerProgressTracker().track_spinner(f"Deleting space {space_rid}..."):
|
|
286
|
+
service.delete_space(space_rid)
|
|
287
|
+
|
|
288
|
+
formatter.print_success(f"Successfully deleted space {space_rid}")
|
|
289
|
+
|
|
290
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
291
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
292
|
+
raise typer.Exit(1)
|
|
293
|
+
except Exception as e:
|
|
294
|
+
formatter.print_error(f"Failed to delete space: {e}")
|
|
295
|
+
raise typer.Exit(1)
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
@app.command("batch-get")
|
|
299
|
+
def get_spaces_batch(
|
|
300
|
+
space_rids: List[str] = typer.Argument(
|
|
301
|
+
..., help="Space Resource Identifiers (space-separated)"
|
|
302
|
+
),
|
|
303
|
+
profile: Optional[str] = typer.Option(
|
|
304
|
+
None, "--profile", help="Profile name", autocompletion=complete_profile
|
|
305
|
+
),
|
|
306
|
+
format: str = typer.Option(
|
|
307
|
+
"table",
|
|
308
|
+
"--format",
|
|
309
|
+
"-f",
|
|
310
|
+
help="Output format (table, json, csv)",
|
|
311
|
+
autocompletion=complete_output_format,
|
|
312
|
+
),
|
|
313
|
+
output: Optional[str] = typer.Option(
|
|
314
|
+
None, "--output", "-o", help="Output file path"
|
|
315
|
+
),
|
|
316
|
+
):
|
|
317
|
+
"""Get multiple spaces in a single request (max 1000)."""
|
|
318
|
+
try:
|
|
319
|
+
service = SpaceService(profile=profile)
|
|
320
|
+
|
|
321
|
+
with SpinnerProgressTracker().track_spinner(
|
|
322
|
+
f"Fetching {len(space_rids)} spaces..."
|
|
323
|
+
):
|
|
324
|
+
spaces = service.get_spaces_batch(space_rids)
|
|
325
|
+
|
|
326
|
+
# Cache RIDs for future completions
|
|
327
|
+
for space in spaces:
|
|
328
|
+
if space.get("rid"):
|
|
329
|
+
cache_rid(space["rid"])
|
|
330
|
+
|
|
331
|
+
# Format output
|
|
332
|
+
if format == "json":
|
|
333
|
+
if output:
|
|
334
|
+
formatter.save_to_file(spaces, output, "json")
|
|
335
|
+
else:
|
|
336
|
+
formatter.format_list(spaces)
|
|
337
|
+
elif format == "csv":
|
|
338
|
+
if output:
|
|
339
|
+
formatter.save_to_file(spaces, output, "csv")
|
|
340
|
+
else:
|
|
341
|
+
formatter.format_list(spaces)
|
|
342
|
+
else:
|
|
343
|
+
_format_spaces_table(spaces)
|
|
344
|
+
|
|
345
|
+
if output:
|
|
346
|
+
formatter.print_success(f"Spaces information saved to {output}")
|
|
347
|
+
|
|
348
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
349
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
350
|
+
raise typer.Exit(1)
|
|
351
|
+
except ValueError as e:
|
|
352
|
+
formatter.print_error(f"Invalid request: {e}")
|
|
353
|
+
raise typer.Exit(1)
|
|
354
|
+
except Exception as e:
|
|
355
|
+
formatter.print_error(f"Failed to get spaces batch: {e}")
|
|
356
|
+
raise typer.Exit(1)
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
@app.command("list-members")
|
|
360
|
+
def list_space_members(
|
|
361
|
+
space_rid: str = typer.Argument(
|
|
362
|
+
..., help="Space Resource Identifier", autocompletion=complete_rid
|
|
363
|
+
),
|
|
364
|
+
principal_type: Optional[str] = typer.Option(
|
|
365
|
+
None,
|
|
366
|
+
"--principal-type",
|
|
367
|
+
"-t",
|
|
368
|
+
help="Filter by principal type (User or Group)",
|
|
369
|
+
),
|
|
370
|
+
profile: Optional[str] = typer.Option(
|
|
371
|
+
None, "--profile", help="Profile name", autocompletion=complete_profile
|
|
372
|
+
),
|
|
373
|
+
format: str = typer.Option(
|
|
374
|
+
"table",
|
|
375
|
+
"--format",
|
|
376
|
+
"-f",
|
|
377
|
+
help="Output format (table, json, csv)",
|
|
378
|
+
autocompletion=complete_output_format,
|
|
379
|
+
),
|
|
380
|
+
output: Optional[str] = typer.Option(
|
|
381
|
+
None, "--output", "-o", help="Output file path"
|
|
382
|
+
),
|
|
383
|
+
page_size: Optional[int] = typer.Option(
|
|
384
|
+
None, "--page-size", help="Number of items per page"
|
|
385
|
+
),
|
|
386
|
+
):
|
|
387
|
+
"""Get all members (users/groups) of a space."""
|
|
388
|
+
try:
|
|
389
|
+
service = SpaceService(profile=profile)
|
|
390
|
+
|
|
391
|
+
filter_desc = f" ({principal_type}s only)" if principal_type else ""
|
|
392
|
+
with SpinnerProgressTracker().track_spinner(
|
|
393
|
+
f"Listing members of space {space_rid}{filter_desc}..."
|
|
394
|
+
):
|
|
395
|
+
members = service.get_space_members(
|
|
396
|
+
space_rid=space_rid,
|
|
397
|
+
principal_type=principal_type.title() if principal_type else None,
|
|
398
|
+
page_size=page_size,
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
if not members:
|
|
402
|
+
formatter.print_info(f"No members found in space {space_rid}.")
|
|
403
|
+
return
|
|
404
|
+
|
|
405
|
+
# Format output
|
|
406
|
+
if format == "json":
|
|
407
|
+
if output:
|
|
408
|
+
formatter.save_to_file(members, output, "json")
|
|
409
|
+
else:
|
|
410
|
+
formatter.format_list(members)
|
|
411
|
+
elif format == "csv":
|
|
412
|
+
if output:
|
|
413
|
+
formatter.save_to_file(members, output, "csv")
|
|
414
|
+
else:
|
|
415
|
+
formatter.format_list(members)
|
|
416
|
+
else:
|
|
417
|
+
_format_space_members_table(members)
|
|
418
|
+
|
|
419
|
+
if output:
|
|
420
|
+
formatter.print_success(f"Space members saved to {output}")
|
|
421
|
+
|
|
422
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
423
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
424
|
+
raise typer.Exit(1)
|
|
425
|
+
except Exception as e:
|
|
426
|
+
formatter.print_error(f"Failed to list space members: {e}")
|
|
427
|
+
raise typer.Exit(1)
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
@app.command("add-member")
|
|
431
|
+
def add_space_member(
|
|
432
|
+
space_rid: str = typer.Argument(
|
|
433
|
+
..., help="Space Resource Identifier", autocompletion=complete_rid
|
|
434
|
+
),
|
|
435
|
+
principal_id: str = typer.Option(
|
|
436
|
+
..., "--principal-id", "-p", help="Principal (user/group) identifier"
|
|
437
|
+
),
|
|
438
|
+
principal_type: str = typer.Option(
|
|
439
|
+
...,
|
|
440
|
+
"--principal-type",
|
|
441
|
+
"-t",
|
|
442
|
+
help="Principal type (User or Group)",
|
|
443
|
+
),
|
|
444
|
+
role_name: str = typer.Option(..., "--role", "-r", help="Role name to grant"),
|
|
445
|
+
profile: Optional[str] = typer.Option(
|
|
446
|
+
None, "--profile", help="Profile name", autocompletion=complete_profile
|
|
447
|
+
),
|
|
448
|
+
format: str = typer.Option(
|
|
449
|
+
"table",
|
|
450
|
+
"--format",
|
|
451
|
+
"-f",
|
|
452
|
+
help="Output format (table, json, csv)",
|
|
453
|
+
autocompletion=complete_output_format,
|
|
454
|
+
),
|
|
455
|
+
):
|
|
456
|
+
"""Add a member to a space with a specific role."""
|
|
457
|
+
try:
|
|
458
|
+
service = SpaceService(profile=profile)
|
|
459
|
+
|
|
460
|
+
with SpinnerProgressTracker().track_spinner(
|
|
461
|
+
f"Adding {principal_type} '{principal_id}' to space {space_rid} with role '{role_name}'..."
|
|
462
|
+
):
|
|
463
|
+
member = service.add_space_member(
|
|
464
|
+
space_rid=space_rid,
|
|
465
|
+
principal_id=principal_id,
|
|
466
|
+
principal_type=principal_type.title(),
|
|
467
|
+
role_name=role_name,
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
formatter.print_success(
|
|
471
|
+
f"Successfully added {principal_type} '{principal_id}' to space with role '{role_name}'"
|
|
472
|
+
)
|
|
473
|
+
|
|
474
|
+
# Format output
|
|
475
|
+
if format == "json":
|
|
476
|
+
formatter.format_dict(member)
|
|
477
|
+
elif format == "csv":
|
|
478
|
+
formatter.format_list([member])
|
|
479
|
+
else:
|
|
480
|
+
_format_space_member_table(member)
|
|
481
|
+
|
|
482
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
483
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
484
|
+
raise typer.Exit(1)
|
|
485
|
+
except Exception as e:
|
|
486
|
+
formatter.print_error(f"Failed to add space member: {e}")
|
|
487
|
+
raise typer.Exit(1)
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
@app.command("remove-member")
|
|
491
|
+
def remove_space_member(
|
|
492
|
+
space_rid: str = typer.Argument(
|
|
493
|
+
..., help="Space Resource Identifier", autocompletion=complete_rid
|
|
494
|
+
),
|
|
495
|
+
principal_id: str = typer.Option(
|
|
496
|
+
..., "--principal-id", "-p", help="Principal (user/group) identifier"
|
|
497
|
+
),
|
|
498
|
+
principal_type: str = typer.Option(
|
|
499
|
+
...,
|
|
500
|
+
"--principal-type",
|
|
501
|
+
"-t",
|
|
502
|
+
help="Principal type (User or Group)",
|
|
503
|
+
),
|
|
504
|
+
profile: Optional[str] = typer.Option(
|
|
505
|
+
None, "--profile", help="Profile name", autocompletion=complete_profile
|
|
506
|
+
),
|
|
507
|
+
confirm: bool = typer.Option(False, "--confirm", help="Skip confirmation prompt"),
|
|
508
|
+
):
|
|
509
|
+
"""Remove a member from a space."""
|
|
510
|
+
try:
|
|
511
|
+
if not confirm:
|
|
512
|
+
confirm_remove = typer.confirm(
|
|
513
|
+
f"Are you sure you want to remove {principal_type} '{principal_id}' from space {space_rid}?"
|
|
514
|
+
)
|
|
515
|
+
if not confirm_remove:
|
|
516
|
+
formatter.print_info("Member removal cancelled.")
|
|
517
|
+
return
|
|
518
|
+
|
|
519
|
+
service = SpaceService(profile=profile)
|
|
520
|
+
|
|
521
|
+
with SpinnerProgressTracker().track_spinner(
|
|
522
|
+
f"Removing {principal_type} '{principal_id}' from space {space_rid}..."
|
|
523
|
+
):
|
|
524
|
+
service.remove_space_member(
|
|
525
|
+
space_rid=space_rid,
|
|
526
|
+
principal_id=principal_id,
|
|
527
|
+
principal_type=principal_type.title(),
|
|
528
|
+
)
|
|
529
|
+
|
|
530
|
+
formatter.print_success(
|
|
531
|
+
f"Successfully removed {principal_type} '{principal_id}' from space"
|
|
532
|
+
)
|
|
533
|
+
|
|
534
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
535
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
536
|
+
raise typer.Exit(1)
|
|
537
|
+
except Exception as e:
|
|
538
|
+
formatter.print_error(f"Failed to remove space member: {e}")
|
|
539
|
+
raise typer.Exit(1)
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
def _format_space_table(space: dict):
|
|
543
|
+
"""Format space information as a table."""
|
|
544
|
+
table = Table(title="Space Information", show_header=True, header_style="bold cyan")
|
|
545
|
+
table.add_column("Property", style="cyan")
|
|
546
|
+
table.add_column("Value")
|
|
547
|
+
|
|
548
|
+
table.add_row("RID", space.get("rid", "N/A"))
|
|
549
|
+
table.add_row("Display Name", space.get("display_name", "N/A"))
|
|
550
|
+
table.add_row("Description", space.get("description", "N/A"))
|
|
551
|
+
table.add_row("Organization RID", space.get("organization_rid", "N/A"))
|
|
552
|
+
table.add_row("Root Folder RID", space.get("root_folder_rid", "N/A"))
|
|
553
|
+
table.add_row("Created By", space.get("created_by", "N/A"))
|
|
554
|
+
table.add_row("Created Time", space.get("created_time", "N/A"))
|
|
555
|
+
table.add_row("Modified By", space.get("modified_by", "N/A"))
|
|
556
|
+
table.add_row("Modified Time", space.get("modified_time", "N/A"))
|
|
557
|
+
table.add_row("Trash Status", space.get("trash_status", "N/A"))
|
|
558
|
+
|
|
559
|
+
console.print(table)
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
def _format_spaces_table(spaces: List[dict]):
|
|
563
|
+
"""Format multiple spaces as a table."""
|
|
564
|
+
table = Table(title="Spaces", show_header=True, header_style="bold cyan")
|
|
565
|
+
table.add_column("Display Name")
|
|
566
|
+
table.add_column("RID")
|
|
567
|
+
table.add_column("Organization RID")
|
|
568
|
+
table.add_column("Created By")
|
|
569
|
+
table.add_column("Created Time")
|
|
570
|
+
|
|
571
|
+
for space in spaces:
|
|
572
|
+
table.add_row(
|
|
573
|
+
space.get("display_name", "N/A"),
|
|
574
|
+
space.get("rid", "N/A"),
|
|
575
|
+
space.get("organization_rid", "N/A"),
|
|
576
|
+
space.get("created_by", "N/A"),
|
|
577
|
+
space.get("created_time", "N/A"),
|
|
578
|
+
)
|
|
579
|
+
|
|
580
|
+
console.print(table)
|
|
581
|
+
console.print(f"\nTotal: {len(spaces)} spaces")
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
def _format_space_member_table(member: dict):
|
|
585
|
+
"""Format space member information as a table."""
|
|
586
|
+
table = Table(
|
|
587
|
+
title="Space Member Information", show_header=True, header_style="bold cyan"
|
|
588
|
+
)
|
|
589
|
+
table.add_column("Property", style="cyan")
|
|
590
|
+
table.add_column("Value")
|
|
591
|
+
|
|
592
|
+
table.add_row("Space RID", member.get("space_rid", "N/A"))
|
|
593
|
+
table.add_row("Principal ID", member.get("principal_id", "N/A"))
|
|
594
|
+
table.add_row("Principal Type", member.get("principal_type", "N/A"))
|
|
595
|
+
table.add_row("Role Name", member.get("role_name", "N/A"))
|
|
596
|
+
table.add_row("Added By", member.get("added_by", "N/A"))
|
|
597
|
+
table.add_row("Added Time", member.get("added_time", "N/A"))
|
|
598
|
+
|
|
599
|
+
console.print(table)
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
def _format_space_members_table(members: List[dict]):
|
|
603
|
+
"""Format multiple space members as a table."""
|
|
604
|
+
table = Table(title="Space Members", show_header=True, header_style="bold cyan")
|
|
605
|
+
table.add_column("Principal Type")
|
|
606
|
+
table.add_column("Principal ID")
|
|
607
|
+
table.add_column("Role Name")
|
|
608
|
+
table.add_column("Added By")
|
|
609
|
+
table.add_column("Added Time")
|
|
610
|
+
|
|
611
|
+
for member in members:
|
|
612
|
+
table.add_row(
|
|
613
|
+
member.get("principal_type", "N/A"),
|
|
614
|
+
member.get("principal_id", "N/A"),
|
|
615
|
+
member.get("role_name", "N/A"),
|
|
616
|
+
member.get("added_by", "N/A"),
|
|
617
|
+
member.get("added_time", "N/A"),
|
|
618
|
+
)
|
|
619
|
+
|
|
620
|
+
console.print(table)
|
|
621
|
+
console.print(f"\nTotal: {len(members)} members")
|
|
622
|
+
|
|
623
|
+
|
|
624
|
+
@app.callback()
|
|
625
|
+
def main():
|
|
626
|
+
"""
|
|
627
|
+
Space operations using foundry-platform-sdk.
|
|
628
|
+
|
|
629
|
+
Manage spaces in the Foundry filesystem. Create, retrieve, update, and delete
|
|
630
|
+
spaces, and manage space membership using Resource Identifiers (RIDs).
|
|
631
|
+
|
|
632
|
+
Examples:
|
|
633
|
+
# Create a space in an organization
|
|
634
|
+
pltr space create "My Space" --organization-rid ri.compass.main.organization.xyz123
|
|
635
|
+
|
|
636
|
+
# List all spaces
|
|
637
|
+
pltr space list
|
|
638
|
+
|
|
639
|
+
# List spaces in a specific organization
|
|
640
|
+
pltr space list --organization-rid ri.compass.main.organization.xyz123
|
|
641
|
+
|
|
642
|
+
# Get space information
|
|
643
|
+
pltr space get ri.compass.main.space.abc456
|
|
644
|
+
|
|
645
|
+
# Update space
|
|
646
|
+
pltr space update ri.compass.main.space.abc456 --name "Updated Name"
|
|
647
|
+
|
|
648
|
+
# List space members
|
|
649
|
+
pltr space list-members ri.compass.main.space.abc456
|
|
650
|
+
|
|
651
|
+
# Add a user to a space
|
|
652
|
+
pltr space add-member ri.compass.main.space.abc456 \\
|
|
653
|
+
--principal-id user123 --principal-type User --role viewer
|
|
654
|
+
|
|
655
|
+
# Remove a user from a space
|
|
656
|
+
pltr space remove-member ri.compass.main.space.abc456 \\
|
|
657
|
+
--principal-id user123 --principal-type User
|
|
658
|
+
|
|
659
|
+
# Delete space
|
|
660
|
+
pltr space delete ri.compass.main.space.abc456
|
|
661
|
+
"""
|
|
662
|
+
pass
|