refactor: Major upgrade to v5.1b6 - AWS SSM support & Distributed Architecture
Core & Protocols: - Native AWS SSM support added (aws ssm start-session). - Improved Pexpect logic for ssm, kubectl, and docker. - Cleaned connection success messages (omitting ports for non-IP protocols). gRPC Layer: - Migrated gRPC modules to 'connpy/grpc_layer/'. - Implemented dynamic node naming (e.g. ssm-i-xxxx@aws) for accurate server-side logging. - Added automatic sys.path resolution for gRPC generated modules. - Enhanced InteractNode response with initial connection status. Printer & Concurrency: - Implemented ThreadLocalStream for isolated thread-safe output. - Self-healing Console objects to prevent 'closed file' errors in test/async environments. - Capture clean plugin output in remote executions. AI & Services: - Improved tool registration and debug visualization. - Restored native dictionary returns for AI tools to fix Web UI rendering. - Increased backup retention to 100 copies in SyncService. - Silenced noisy auto-sync CLI messages. Quality & Docs: - Total tests: 267 (all passing). - New test suites for gRPC layer and printer concurrency. - Updated .gitignore to exclude internal planning docs. - Full technical documentation regenerated with pdoc.
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
|
||||
<meta name="generator" content="pdoc3 0.11.5">
|
||||
<meta name="generator" content="pdoc3 0.11.6">
|
||||
<title>connpy.services.node_service API documentation</title>
|
||||
<meta name="description" content="">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
|
||||
@@ -123,10 +123,13 @@ el.replaceWith(d);
|
||||
|
||||
def get_node_details(self, unique_id):
|
||||
"""Return full configuration dictionary for a specific node."""
|
||||
details = self.config.getitem(unique_id)
|
||||
if not details:
|
||||
try:
|
||||
details = self.config.getitem(unique_id)
|
||||
if not details:
|
||||
raise NodeNotFoundError(f"Node '{unique_id}' not found.")
|
||||
return details
|
||||
except (KeyError, TypeError):
|
||||
raise NodeNotFoundError(f"Node '{unique_id}' not found.")
|
||||
return details
|
||||
|
||||
def explode_unique(self, unique_id):
|
||||
"""Explode a unique ID into a dictionary of its parts."""
|
||||
@@ -136,6 +139,14 @@ el.replaceWith(d);
|
||||
"""Generate and update the internal nodes cache."""
|
||||
self.config._generate_nodes_cache(nodes=nodes, folders=folders, profiles=profiles)
|
||||
|
||||
def validate_parent_folder(self, unique_id):
|
||||
"""Check if parent folder exists for a given node unique ID."""
|
||||
node_folder = unique_id.partition("@")[2]
|
||||
if node_folder:
|
||||
parent_folder = f"@{node_folder}"
|
||||
if parent_folder not in self.config._getallfolders():
|
||||
raise NodeNotFoundError(f"Folder '{parent_folder}' not found.")
|
||||
|
||||
|
||||
def add_node(self, unique_id, data, is_folder=False):
|
||||
"""Logic for adding a new node or folder to configuration."""
|
||||
@@ -154,9 +165,7 @@ el.replaceWith(d);
|
||||
|
||||
# Check if parent folder exists when creating a subfolder
|
||||
if "subfolder" in uniques:
|
||||
parent_folder = f"@{uniques['folder']}"
|
||||
if parent_folder not in all_folders:
|
||||
raise NodeNotFoundError(f"Folder '{parent_folder}' not found.")
|
||||
self.validate_parent_folder(unique_id)
|
||||
|
||||
self.config._folder_add(**uniques)
|
||||
self.config._saveconfig(self.config.file)
|
||||
@@ -165,11 +174,7 @@ el.replaceWith(d);
|
||||
raise NodeAlreadyExistsError(f"Node '{unique_id}' already exists.")
|
||||
|
||||
# Check if parent folder exists when creating a node in a folder
|
||||
node_folder = unique_id.partition("@")[2]
|
||||
if node_folder:
|
||||
parent_folder = f"@{node_folder}"
|
||||
if parent_folder not in all_folders:
|
||||
raise NodeNotFoundError(f"Folder '{parent_folder}' not found.")
|
||||
self.validate_parent_folder(unique_id)
|
||||
|
||||
# Ensure 'id' is in data for config._connections_add
|
||||
if "id" not in data:
|
||||
@@ -342,9 +347,7 @@ el.replaceWith(d);
|
||||
|
||||
# Check if parent folder exists when creating a subfolder
|
||||
if "subfolder" in uniques:
|
||||
parent_folder = f"@{uniques['folder']}"
|
||||
if parent_folder not in all_folders:
|
||||
raise NodeNotFoundError(f"Folder '{parent_folder}' not found.")
|
||||
self.validate_parent_folder(unique_id)
|
||||
|
||||
self.config._folder_add(**uniques)
|
||||
self.config._saveconfig(self.config.file)
|
||||
@@ -353,11 +356,7 @@ el.replaceWith(d);
|
||||
raise NodeAlreadyExistsError(f"Node '{unique_id}' already exists.")
|
||||
|
||||
# Check if parent folder exists when creating a node in a folder
|
||||
node_folder = unique_id.partition("@")[2]
|
||||
if node_folder:
|
||||
parent_folder = f"@{node_folder}"
|
||||
if parent_folder not in all_folders:
|
||||
raise NodeNotFoundError(f"Folder '{parent_folder}' not found.")
|
||||
self.validate_parent_folder(unique_id)
|
||||
|
||||
# Ensure 'id' is in data for config._connections_add
|
||||
if "id" not in data:
|
||||
@@ -540,10 +539,13 @@ el.replaceWith(d);
|
||||
</summary>
|
||||
<pre><code class="python">def get_node_details(self, unique_id):
|
||||
"""Return full configuration dictionary for a specific node."""
|
||||
details = self.config.getitem(unique_id)
|
||||
if not details:
|
||||
raise NodeNotFoundError(f"Node '{unique_id}' not found.")
|
||||
return details</code></pre>
|
||||
try:
|
||||
details = self.config.getitem(unique_id)
|
||||
if not details:
|
||||
raise NodeNotFoundError(f"Node '{unique_id}' not found.")
|
||||
return details
|
||||
except (KeyError, TypeError):
|
||||
raise NodeNotFoundError(f"Node '{unique_id}' not found.")</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Return full configuration dictionary for a specific node.</p></div>
|
||||
</dd>
|
||||
@@ -690,6 +692,24 @@ el.replaceWith(d);
|
||||
</details>
|
||||
<div class="desc"><p>Explicitly update an existing node.</p></div>
|
||||
</dd>
|
||||
<dt id="connpy.services.node_service.NodeService.validate_parent_folder"><code class="name flex">
|
||||
<span>def <span class="ident">validate_parent_folder</span></span>(<span>self, unique_id)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def validate_parent_folder(self, unique_id):
|
||||
"""Check if parent folder exists for a given node unique ID."""
|
||||
node_folder = unique_id.partition("@")[2]
|
||||
if node_folder:
|
||||
parent_folder = f"@{node_folder}"
|
||||
if parent_folder not in self.config._getallfolders():
|
||||
raise NodeNotFoundError(f"Folder '{parent_folder}' not found.")</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Check if parent folder exists for a given node unique ID.</p></div>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Inherited members</h3>
|
||||
<ul class="hlist">
|
||||
@@ -717,7 +737,7 @@ el.replaceWith(d);
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="connpy.services.node_service.NodeService" href="#connpy.services.node_service.NodeService">NodeService</a></code></h4>
|
||||
<ul class="two-column">
|
||||
<ul class="">
|
||||
<li><code><a title="connpy.services.node_service.NodeService.add_node" href="#connpy.services.node_service.NodeService.add_node">add_node</a></code></li>
|
||||
<li><code><a title="connpy.services.node_service.NodeService.bulk_add" href="#connpy.services.node_service.NodeService.bulk_add">bulk_add</a></code></li>
|
||||
<li><code><a title="connpy.services.node_service.NodeService.connect_node" href="#connpy.services.node_service.NodeService.connect_node">connect_node</a></code></li>
|
||||
@@ -731,6 +751,7 @@ el.replaceWith(d);
|
||||
<li><code><a title="connpy.services.node_service.NodeService.list_nodes" href="#connpy.services.node_service.NodeService.list_nodes">list_nodes</a></code></li>
|
||||
<li><code><a title="connpy.services.node_service.NodeService.move_node" href="#connpy.services.node_service.NodeService.move_node">move_node</a></code></li>
|
||||
<li><code><a title="connpy.services.node_service.NodeService.update_node" href="#connpy.services.node_service.NodeService.update_node">update_node</a></code></li>
|
||||
<li><code><a title="connpy.services.node_service.NodeService.validate_parent_folder" href="#connpy.services.node_service.NodeService.validate_parent_folder">validate_parent_folder</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -739,7 +760,7 @@ el.replaceWith(d);
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p>
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user