mantatech-sdk 0.5b0.dev65__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.
Files changed (54) hide show
  1. manta/__init__.light.py +22 -0
  2. manta/__init__.py +83 -0
  3. manta/__main__.py +21 -0
  4. manta/apis/__init__.py +7 -0
  5. manta/apis/async_user_api.py +6458 -0
  6. manta/apis/graph.py +498 -0
  7. manta/apis/module.py +316 -0
  8. manta/apis/results.py +251 -0
  9. manta/apis/swarm.py +206 -0
  10. manta/apis/user_api.py +1016 -0
  11. manta/cli/__init__.py +1 -0
  12. manta/cli/commands/__init__.py +1 -0
  13. manta/cli/commands/base_handler.py +229 -0
  14. manta/cli/commands/doc.py +192 -0
  15. manta/cli/commands/install.py +346 -0
  16. manta/cli/commands/sdk.py +9 -0
  17. manta/cli/commands/sdk_cluster.py +211 -0
  18. manta/cli/commands/sdk_config.py +347 -0
  19. manta/cli/commands/sdk_globals.py +280 -0
  20. manta/cli/commands/sdk_logs.py +174 -0
  21. manta/cli/commands/sdk_main.py +167 -0
  22. manta/cli/commands/sdk_module.py +516 -0
  23. manta/cli/commands/sdk_nodes.py +168 -0
  24. manta/cli/commands/sdk_original.py +3873 -0
  25. manta/cli/commands/sdk_results.py +265 -0
  26. manta/cli/commands/sdk_swarm.py +454 -0
  27. manta/cli/commands/sdk_user.py +234 -0
  28. manta/cli/commands/status.py +292 -0
  29. manta/cli/component_detector.py +112 -0
  30. manta/cli/config_manager.py +445 -0
  31. manta/cli/main.py +265 -0
  32. manta/cli/utils/__init__.py +27 -0
  33. manta/cli/utils/converters.py +140 -0
  34. manta/clients/cluster_management_client.py +486 -0
  35. manta/clients/local_client.py +149 -0
  36. manta/clients/module_management_client.py +217 -0
  37. manta/clients/swarm_management_client.py +562 -0
  38. manta/clients/user_management_client.py +395 -0
  39. manta/clients/world_client.py +195 -0
  40. manta/light/__init__.py +31 -0
  41. manta/light/globals.py +245 -0
  42. manta/light/local.py +407 -0
  43. manta/light/logging_config.py +39 -0
  44. manta/light/path.py +116 -0
  45. manta/light/results.py +236 -0
  46. manta/light/task.py +100 -0
  47. manta/light/utils.py +217 -0
  48. manta/light/world.py +177 -0
  49. mantatech_sdk-0.5b0.dev65.dist-info/METADATA +1039 -0
  50. mantatech_sdk-0.5b0.dev65.dist-info/RECORD +54 -0
  51. mantatech_sdk-0.5b0.dev65.dist-info/WHEEL +5 -0
  52. mantatech_sdk-0.5b0.dev65.dist-info/entry_points.txt +2 -0
  53. mantatech_sdk-0.5b0.dev65.dist-info/licenses/LICENSE +683 -0
  54. mantatech_sdk-0.5b0.dev65.dist-info/top_level.txt +1 -0
@@ -0,0 +1,346 @@
1
+ """Installation helper commands for Manta CLI."""
2
+
3
+ import subprocess
4
+ import sys
5
+ from typing import List, Optional
6
+
7
+ from rich.console import Console
8
+ from rich.progress import Progress, SpinnerColumn, TextColumn
9
+ from rich.prompt import Confirm
10
+ from rich.table import Table
11
+
12
+ from ..component_detector import ComponentDetector
13
+
14
+
15
+ class InstallCommands:
16
+ """Handle installation-related CLI commands."""
17
+
18
+ def __init__(self, detector: ComponentDetector, console: Optional[Console] = None):
19
+ self.detector = detector
20
+ self.console = console
21
+
22
+ def print(self, *args, **kwargs):
23
+ """Print with console if available."""
24
+ self.console.print(*args, **kwargs)
25
+
26
+ def print_error(self, message: str):
27
+ """Print error message."""
28
+ self.console.print(f"[red]Error:[/red] {message}")
29
+
30
+ def print_success(self, message: str):
31
+ """Print success message."""
32
+ self.console.print(f"[green]Success:[/green] {message}")
33
+
34
+ def print_warning(self, message: str):
35
+ """Print warning message."""
36
+ self.console.print(f"[yellow]Warning:[/yellow] {message}")
37
+
38
+ def handle(self, args) -> int:
39
+ """Handle installation commands."""
40
+ if hasattr(args, "install_command") and args.install_command:
41
+ if args.install_command == "wizard":
42
+ return self.run_installation_wizard()
43
+ elif args.install_command == "check":
44
+ return self.check_requirements()
45
+ elif args.install_command == "component":
46
+ # Handle component installation with name
47
+ if hasattr(args, "name") and args.name:
48
+ return self.install_component(args.name)
49
+ else:
50
+ self.print_error("Component name is required")
51
+ return 1
52
+ elif args.install_command == "sdk":
53
+ return self.install_component("sdk")
54
+ elif args.install_command == "admin":
55
+ return self.install_component("admin")
56
+ elif args.install_command == "node":
57
+ return self.install_component("node")
58
+ elif args.install_command == "all":
59
+ return self.install_all_components()
60
+ else:
61
+ self.print_error(f"Unknown install command: {args.install_command}")
62
+ return 1
63
+ else:
64
+ # Show installation help
65
+ return self.show_installation_help()
66
+
67
+ def show_installation_help(self) -> int:
68
+ """Show installation help and current status."""
69
+ self.print("📦 Manta Installation Guide")
70
+ self.print("=" * 30)
71
+
72
+ # Refresh detection
73
+ self.detector.refresh()
74
+
75
+ # Show current status
76
+ table = Table(title="Component Status")
77
+ table.add_column("Component", style="cyan")
78
+ table.add_column("Status", style="green")
79
+ table.add_column("Install Command", style="magenta")
80
+
81
+ for comp_name in self.detector.list_components():
82
+ comp_info = self.detector.get_component_info(comp_name)
83
+ if comp_info:
84
+ status = "✅ Installed" if comp_info.installed else "❌ Not Installed"
85
+ install_cmd = (
86
+ self.detector.get_installation_command(comp_name)
87
+ if not comp_info.installed
88
+ else "-"
89
+ )
90
+ table.add_row(comp_info.name, status, install_cmd)
91
+
92
+ self.console.print(table)
93
+
94
+ # Show available commands
95
+ self.print("\n💡 Available Commands:")
96
+ self.print(" • manta install wizard - Interactive installation wizard")
97
+ self.print(" • manta install check - Check system requirements")
98
+ self.print(" • manta install sdk - Install Manta SDK")
99
+ self.print(" • manta install admin - Install Manta Admin")
100
+ self.print(" • manta install node - Install Manta Node")
101
+ self.print(" • manta install all - Install all components")
102
+
103
+ return 0
104
+
105
+ def run_installation_wizard(self) -> int:
106
+ """Run interactive installation wizard."""
107
+ self.print("🧙 Manta Installation Wizard")
108
+ self.print("=" * 30)
109
+
110
+ # Check requirements first
111
+ self.print("\n1️⃣ Checking system requirements...")
112
+ if not self._check_python_version():
113
+ return 1
114
+
115
+ if not self._check_pip():
116
+ return 1
117
+
118
+ self.print_success("System requirements met!")
119
+
120
+ # Detect missing components
121
+ self.detector.refresh()
122
+ summary = self.detector.get_status_summary()
123
+
124
+ if not summary["missing"]:
125
+ self.print_success("\n✅ All components are already installed!")
126
+ return 0
127
+
128
+ # Ask what to install
129
+ self.print(f"\n2️⃣ Found {len(summary['missing'])} missing component(s):")
130
+ for comp in summary["missing"]:
131
+ self.print(f" • {comp}")
132
+
133
+ if Confirm.ask("\nWould you like to install all missing components?"):
134
+ return self._install_components(summary["missing"])
135
+ else:
136
+ # Let user select specific components
137
+ to_install = []
138
+ for comp in summary["missing"]:
139
+ if Confirm.ask(f"Install {comp}?"):
140
+ to_install.append(comp)
141
+
142
+ if to_install:
143
+ return self._install_components(to_install)
144
+ else:
145
+ self.print("No components selected for installation.")
146
+ return 0
147
+
148
+ def check_requirements(self) -> int:
149
+ """Check system requirements."""
150
+ self.print("🔍 Checking System Requirements")
151
+ self.print("=" * 35)
152
+
153
+ all_good = True
154
+
155
+ # Check Python version
156
+ if not self._check_python_version():
157
+ all_good = False
158
+
159
+ # Check pip
160
+ if not self._check_pip():
161
+ all_good = False
162
+
163
+ # Check git
164
+ if not self._check_git():
165
+ all_good = False
166
+
167
+ # Check Docker (optional)
168
+ self._check_docker()
169
+
170
+ if all_good:
171
+ self.print_success("\n✅ All requirements met!")
172
+ else:
173
+ self.print_error(
174
+ "\n❌ Some requirements are not met. Please install missing dependencies."
175
+ )
176
+ return 1
177
+
178
+ return 0
179
+
180
+ def install_component(self, component: str) -> int:
181
+ """Install a specific component."""
182
+ comp_info = self.detector.get_component_info(component)
183
+
184
+ if not comp_info:
185
+ self.print_error(f"Unknown component: {component}")
186
+ return 1
187
+
188
+ if comp_info.installed:
189
+ self.print_success(f"{comp_info.name} is already installed!")
190
+ return 0
191
+
192
+ return self._install_components([component])
193
+
194
+ def install_all_components(self) -> int:
195
+ """Install all missing components."""
196
+ self.detector.refresh()
197
+ summary = self.detector.get_status_summary()
198
+
199
+ if not summary["missing"]:
200
+ self.print_success("All components are already installed!")
201
+ return 0
202
+
203
+ return self._install_components(summary["missing"])
204
+
205
+ def _install_components(self, components: List[str]) -> int:
206
+ """Install multiple components."""
207
+ self.print(f"\n📦 Installing {len(components)} component(s)...")
208
+
209
+ failed = []
210
+
211
+ with Progress(
212
+ SpinnerColumn(),
213
+ TextColumn("[progress.description]{task.description}"),
214
+ console=self.console,
215
+ ) as progress:
216
+ for comp in components:
217
+ task = progress.add_task(f"Installing {comp}...", total=None)
218
+
219
+ install_cmd = self.detector.get_installation_command(comp)
220
+ if not install_cmd:
221
+ progress.update(
222
+ task,
223
+ description=f"[red]Failed to get install command for {comp}",
224
+ )
225
+ failed.append(comp)
226
+ continue
227
+
228
+ try:
229
+ # Run pip install
230
+ result = subprocess.run(
231
+ [sys.executable, "-m", "pip", "install"]
232
+ + install_cmd.split()[2:],
233
+ capture_output=True,
234
+ text=True,
235
+ check=False,
236
+ )
237
+
238
+ if result.returncode == 0:
239
+ progress.update(
240
+ task, description=f"[green]✅ {comp} installed successfully"
241
+ )
242
+ else:
243
+ progress.update(
244
+ task, description=f"[red]❌ Failed to install {comp}"
245
+ )
246
+ failed.append(comp)
247
+ if result.stderr:
248
+ self.print_error(f"Error: {result.stderr}")
249
+
250
+ except Exception as e:
251
+ progress.update(
252
+ task, description=f"[red]❌ Error installing {comp}: {e}"
253
+ )
254
+ failed.append(comp)
255
+
256
+ # Show summary
257
+ if failed:
258
+ self.print_error(
259
+ f"\n❌ Failed to install {len(failed)} component(s): {', '.join(failed)}"
260
+ )
261
+ return 1
262
+ else:
263
+ self.print_success(
264
+ f"\n✅ Successfully installed {len(components)} component(s)!"
265
+ )
266
+ self.print("\n💡 Next steps:")
267
+ self.print(" • Configure the platform: manta config init --interactive")
268
+ self.print(" • View documentation: manta doc")
269
+ return 0
270
+
271
+ def _check_python_version(self) -> bool:
272
+ """Check Python version requirement."""
273
+ python_version = f"{sys.version_info.major}.{sys.version_info.minor}"
274
+ required_version = "3.9"
275
+
276
+ if sys.version_info.major == 3 and sys.version_info.minor >= 9:
277
+ self.print(f"✅ Python {python_version} (>= {required_version} required)")
278
+ return True
279
+ else:
280
+ self.print_error(
281
+ f"❌ Python {python_version} (>= {required_version} required)"
282
+ )
283
+ return False
284
+
285
+ def _check_pip(self) -> bool:
286
+ """Check if pip is available."""
287
+ try:
288
+ result = subprocess.run(
289
+ [sys.executable, "-m", "pip", "--version"],
290
+ capture_output=True,
291
+ text=True,
292
+ check=False,
293
+ timeout=5,
294
+ )
295
+ if result.returncode == 0:
296
+ pip_version = result.stdout.split()[1] if result.stdout else "Unknown"
297
+ self.print(f"✅ pip {pip_version}")
298
+ return True
299
+ else:
300
+ self.print_error("❌ pip is not available")
301
+ return False
302
+ except Exception:
303
+ self.print_error("❌ pip is not available")
304
+ return False
305
+
306
+ def _check_git(self) -> bool:
307
+ """Check if git is available."""
308
+ try:
309
+ result = subprocess.run(
310
+ ["git", "--version"],
311
+ capture_output=True,
312
+ text=True,
313
+ check=False,
314
+ timeout=5,
315
+ )
316
+ if result.returncode == 0:
317
+ git_version = result.stdout.strip()
318
+ self.print(f"✅ {git_version}")
319
+ return True
320
+ else:
321
+ self.print_warning("⚠️ Git is not available (optional)")
322
+ return True # Git is optional
323
+ except Exception:
324
+ self.print_warning("⚠️ Git is not available (optional)")
325
+ return True # Git is optional
326
+
327
+ def _check_docker(self) -> bool:
328
+ """Check if Docker is available."""
329
+ try:
330
+ result = subprocess.run(
331
+ ["docker", "--version"],
332
+ capture_output=True,
333
+ text=True,
334
+ check=False,
335
+ timeout=5,
336
+ )
337
+ if result.returncode == 0:
338
+ docker_version = result.stdout.strip()
339
+ self.print(f"✅ {docker_version} (optional)")
340
+ return True
341
+ else:
342
+ self.print_warning("⚠️ Docker is not available (optional)")
343
+ return True # Docker is optional
344
+ except Exception:
345
+ self.print_warning("⚠️ Docker is not available (optional)")
346
+ return True # Docker is optional
@@ -0,0 +1,9 @@
1
+ """SDK Commands for Manta CLI.
2
+
3
+ This module exports the main SDKCommands class that integrates
4
+ with the unified Manta CLI system.
5
+ """
6
+
7
+ from .sdk_main import SDKCommands
8
+
9
+ __all__ = ["SDKCommands"]
@@ -0,0 +1,211 @@
1
+ """SDK cluster information and management commands."""
2
+
3
+ from rich.panel import Panel
4
+ from rich.table import Table
5
+
6
+ from .base_handler import BaseSDKHandler
7
+ from ..utils import (
8
+ enum_to_string,
9
+ timestamp_to_string,
10
+ extract_platform_type,
11
+ NODE_STATUS_MAP,
12
+ CLUSTER_STATUS_MAP,
13
+ )
14
+
15
+
16
+ class SDKClusterHandler(BaseSDKHandler):
17
+ """Handle cluster-related SDK commands."""
18
+
19
+ def add_subparsers(self, parent_parser):
20
+ """Add cluster command subparsers."""
21
+ self.parser = parent_parser # Store parser reference
22
+ subparsers = parent_parser.add_subparsers(
23
+ dest="cluster_command", help="Cluster commands"
24
+ )
25
+
26
+ # List clusters command
27
+ list_parser = subparsers.add_parser("list", help="List available clusters")
28
+
29
+ # Show cluster command
30
+ show_parser = subparsers.add_parser(
31
+ "show", help="Show detailed cluster information"
32
+ )
33
+ show_parser.add_argument("cluster_id", help="Cluster ID to show")
34
+
35
+ # Get cluster nodes command
36
+ nodes_parser = subparsers.add_parser("nodes", help="List nodes in cluster")
37
+ nodes_parser.add_argument("cluster_id", help="Cluster ID to show nodes for")
38
+
39
+ # Add common arguments to all subcommands
40
+ for parser in [list_parser, show_parser, nodes_parser]:
41
+ parser.add_argument("--profile", help="Use specific profile")
42
+ parser.add_argument(
43
+ "--debug", action="store_true", help="Enable debug output"
44
+ )
45
+
46
+ def handle(self, args) -> int:
47
+ """Handle cluster commands."""
48
+ # Enable debug if requested
49
+ if getattr(args, "debug", False):
50
+ self.enable_debug(True)
51
+
52
+ if not args.cluster_command:
53
+ if hasattr(self, "parser"):
54
+ self.parser.print_help()
55
+ return 0 # Return 0 for help display
56
+
57
+ if args.cluster_command == "list":
58
+ return self.list_clusters()
59
+ elif args.cluster_command == "show":
60
+ return self.show_cluster(args.cluster_id)
61
+ elif args.cluster_command == "nodes":
62
+ return self.show_cluster_nodes(args.cluster_id)
63
+ else:
64
+ self.print_error(f"Unknown cluster command: {args.cluster_command}")
65
+ return 1
66
+
67
+ def list_clusters(self) -> int:
68
+ """List available clusters."""
69
+ api = self._get_user_api()
70
+ if not api:
71
+ return 1
72
+
73
+ try:
74
+
75
+ async def run():
76
+ clusters = await api.stream_and_fetch_clusters()
77
+ return clusters
78
+
79
+ clusters = self._run_with_progress(run, "Fetching clusters...")
80
+
81
+ # Check if the operation failed
82
+ if clusters is None:
83
+ return 1
84
+
85
+ # Display clusters
86
+ if not clusters:
87
+ self.print("No clusters found.")
88
+ return 0
89
+
90
+ # Always use console (it's always available in SDK context)
91
+ table = Table(title="Available Clusters")
92
+ table.add_column("Cluster ID", style="cyan")
93
+ table.add_column("Name", style="blue")
94
+ table.add_column("Status", style="green")
95
+ table.add_column("Nodes", style="magenta")
96
+
97
+ for cluster in clusters:
98
+ status = enum_to_string(cluster.get("status", 0), CLUSTER_STATUS_MAP)
99
+
100
+ table.add_row(
101
+ cluster.get("cluster_id", "Unknown"),
102
+ cluster.get("name", "Unknown"),
103
+ status,
104
+ str(cluster.get("node_count", 0)),
105
+ )
106
+
107
+ self.console.print(table)
108
+
109
+ return 0
110
+
111
+ except KeyboardInterrupt:
112
+ return 130 # Standard exit code for SIGINT
113
+ except Exception:
114
+ # Error already printed by base handler
115
+ return 1
116
+
117
+ def show_cluster(self, cluster_id: str) -> int:
118
+ """Show detailed cluster information."""
119
+ api = self._get_user_api()
120
+ if not api:
121
+ return 1
122
+
123
+ try:
124
+
125
+ async def run():
126
+ return await api.get_cluster(cluster_id)
127
+
128
+ cluster = self._run_with_progress(run, f"Fetching cluster {cluster_id}...")
129
+
130
+ # Check if the operation failed
131
+ if cluster is None:
132
+ return 1
133
+
134
+ # Extract and format fields
135
+ status = enum_to_string(cluster.get("status", 0), CLUSTER_STATUS_MAP)
136
+ created = timestamp_to_string(
137
+ cluster.get("created_at") or cluster.get("creation_date")
138
+ )
139
+
140
+ # Display cluster details
141
+ panel = Panel.fit(
142
+ f"[cyan]Cluster ID:[/cyan] {cluster.get('cluster_id', 'Unknown')}\n"
143
+ f"[cyan]Name:[/cyan] {cluster.get('name', 'Unknown')}\n"
144
+ f"[cyan]Status:[/cyan] {status}\n"
145
+ f"[cyan]Node Count:[/cyan] {cluster.get('node_count', 0)}\n"
146
+ f"[cyan]Created:[/cyan] {created}",
147
+ title=f"Cluster: {cluster_id}",
148
+ )
149
+ self.console.print(panel)
150
+
151
+ return 0
152
+
153
+ except KeyboardInterrupt:
154
+ return 130
155
+ except Exception:
156
+ # Error already printed by base handler
157
+ return 1
158
+
159
+ def show_cluster_nodes(self, cluster_id: str) -> int:
160
+ """Show nodes in a cluster."""
161
+ api = self._get_user_api()
162
+ if not api:
163
+ return 1
164
+
165
+ try:
166
+
167
+ async def run():
168
+ return await api.stream_and_fetch_nodes(cluster_id)
169
+
170
+ nodes = self._run_with_progress(
171
+ run, f"Fetching nodes for cluster {cluster_id}..."
172
+ )
173
+
174
+ # Check if the operation failed
175
+ if nodes is None:
176
+ return 1
177
+
178
+ if not nodes:
179
+ self.print("No nodes found in this cluster.")
180
+ return 0
181
+
182
+ # Create and display nodes table
183
+ table = Table(title=f"Nodes in Cluster: {cluster_id}")
184
+ table.add_column("Node ID", style="cyan")
185
+ table.add_column("Status", style="green")
186
+ table.add_column("Type", style="blue")
187
+ table.add_column("Last Seen", style="yellow")
188
+
189
+ for node in nodes:
190
+ # Use converter functions for consistent parsing
191
+ status = enum_to_string(node.get("node_status", 0), NODE_STATUS_MAP)
192
+
193
+ node_type = extract_platform_type(node.get("platform_info"))
194
+
195
+ last_seen = timestamp_to_string(
196
+ node.get("updated_at") or node.get("created_at")
197
+ )
198
+
199
+ table.add_row(
200
+ node.get("node_id", "Unknown"), status, node_type, last_seen
201
+ )
202
+
203
+ self.console.print(table)
204
+
205
+ return 0
206
+
207
+ except KeyboardInterrupt:
208
+ return 130
209
+ except Exception:
210
+ # Error already printed by base handler
211
+ return 1