Remote command execution library for SSH-based cluster operations. Execute commands on multiple servers concurrently with retry logic, error classification, and Slack notifications.
Project description
grass-remote-cli
Remote command execution library for SSH-based cluster operations.
Features
- ClusterCmd: Execute commands on multiple servers concurrently
- SshCmd: Single-server SSH execution with retry logic
- StderrClassifier: Intelligent error classification (real errors vs innocent warnings)
- Notifications: Slack integration for alerts (optional)
- AnsibleInventory: Parse Ansible inventory files (optional)
Installation
# Core (SSH execution)
pip install grass-remote-cli
# With Ansible inventory support
pip install grass-remote-cli[inventory]
# With Slack notifications
pip install grass-remote-cli[notifications]
# Everything
pip install grass-remote-cli[all]
Quick Start
from grass_remote_cli import ClusterCmd
# Execute command on multiple servers
cluster = ClusterCmd(
servers_ips=["<ip1>", "<ip2>", "<ip3>"],
username="<ssh_user>",
password="<ssh_password>",
timeout_in_sec=300,
)
results, timed_out = cluster.execute("docker ps")
for ip, (_, stdout, stderr) in results:
print(f"{ip}: {stdout}")
Single Server Execution
from grass_remote_cli import SshCmd
ssh = SshCmd()
ip, stdout, stderr = ssh.execute(
host_ip="<server_ip>",
username="<ssh_user>",
password="<ssh_password>",
commands="hostname && uptime"
)
print(stdout)
With Ansible Inventory
from grass_remote_cli import ClusterCmd
from grass_remote_cli.inventory import AnsibleInventory
# Load servers from Ansible inventory
inventory = AnsibleInventory("/path/to/ansible/inventories")
hosts = inventory.get_hosts_by_cluster("<cluster_name>")
# Deploy to cluster
ips = [host[1] for host in hosts] # Extract IPs
cluster = ClusterCmd(ips, username="<ssh_user>", password="<ssh_password>")
results, _ = cluster.execute("docker pull <image>")
Error Classification
The library intelligently classifies stderr output:
from grass_remote_cli.stderr_classifier import StderrClassifier
classifier = StderrClassifier()
result = classifier.classify(stderr_output)
if result['is_error']:
print(f"Real error: {result['summary']}")
else:
print("Innocent warning, safe to ignore")
Slack Notifications
import os
from grass_remote_cli.notifications import post_to_slack
# Set webhook via environment variable
os.environ["SLACK_WEBHOOK_URL"] = "https://hooks.slack.com/services/..."
post_to_slack("Deployment complete!", channel="#deployments")
# Or pass webhook directly
post_to_slack(
"Deployment complete!",
channel="#deployments",
webhook_url="https://hooks.slack.com/services/..."
)
Environment Variables
| Variable | Description |
|---|---|
SLACK_WEBHOOK_URL |
Slack webhook URL for notifications |
SSH_AUTH_TIMEOUT |
SSH authentication timeout (default: 120s) |
SSH_EXEC_TIMEOUT |
Command execution timeout (default: 900s) |
SSH_MAX_RETRIES |
Connection retry attempts (default: 3) |
SSH_MAX_WORKERS |
Concurrent SSH connections (default: 50) |
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file grass_remote_cli-0.2.0.tar.gz.
File metadata
- Download URL: grass_remote_cli-0.2.0.tar.gz
- Upload date:
- Size: 16.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3c14d0a3d38dd8d516a0792b046565dfa3069b91c00d90c97e985e0888179936
|
|
| MD5 |
a41bea873a88f0a9c81367a18e0d9ceb
|
|
| BLAKE2b-256 |
b716938a012c5b89d81ab670b486a7135344270a6500f2b76c5c4b0e24d85473
|
File details
Details for the file grass_remote_cli-0.2.0-py3-none-any.whl.
File metadata
- Download URL: grass_remote_cli-0.2.0-py3-none-any.whl
- Upload date:
- Size: 13.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8cb35b087478319ddaf00055dfd604bf8f054eb2331a75d2d2733e0d2ecbf981
|
|
| MD5 |
12e24fcf25163db45aed18176f10b058
|
|
| BLAKE2b-256 |
9bc359d7b9eefd4fe436f15c4b9c6c1c98180d50542a70ce1c125e9f0aea8bea
|