-
-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for remote execution with ssh, similar to ansible #98
Comments
it seems that ansible uses cryptography for the ssh connections. |
for now we will just support ssh remote host, if another protocol is given, it should fail. |
@abhijeetSaroha , I just updated the first comment here with all the details. |
from gpt, suggestion for the implementation: Integrating remote execution capabilities into Makim using Paramiko is a valuable enhancement that can significantly broaden the tool's applicability. Your initial approach to segregate local and remote execution by introducing separate functions ( 1. Structuring Remote and Local Executiona. Separate Execution FunctionsPros:
Implementation: def _call_shell_app_local(self, cmd: str) -> None:
"""Execute command locally using the specified shell application."""
# Existing implementation of local execution
self._load_shell_app()
# ... rest of the local execution code ...
def _call_shell_remote(self, cmd: str, host_config: dict) -> None:
"""Execute command remotely using Paramiko."""
import paramiko
try:
# Initialize SSH client
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# Establish SSH connection
ssh.connect(
hostname=host_config['host'],
port=host_config.get('port', 22),
username=host_config['user'],
key_filename=host_config['file'],
timeout=host_config.get('timeout', 30),
allow_agent=host_config.get('allow_agent', True),
look_for_keys=host_config.get('look_for_keys', True),
)
# Execute the command
stdin, stdout, stderr = ssh.exec_command(cmd)
# Optionally, handle output
output = stdout.read().decode('utf-8')
error = stderr.read().decode('utf-8')
if self.verbose:
MakimLogs.print_info(output)
if error:
MakimLogs.print_error(error)
# Close the connection
ssh.close()
except paramiko.AuthenticationException:
MakimLogs.raise_error(
"Authentication failed when connecting to {}".format(host_config['host']),
MakimError.SSH_AUTHENTICATION_FAILED,
)
except paramiko.SSHException as sshException:
MakimLogs.raise_error(
"Unable to establish SSH connection: {}".format(sshException),
MakimError.SSH_CONNECTION_ERROR,
)
except Exception as e:
MakimLogs.raise_error(
"Error occurred during SSH execution: {}".format(e),
MakimError.SSH_EXECUTION_ERROR,
) b. Dispatcher FunctionModify def _call_shell_app(self, cmd: str) -> None:
"""Dispatch command execution to local or remote."""
remote_name = self.task_data.get('remote')
if remote_name:
host_config = self.global_data.get('hosts', {}).get(remote_name)
if not host_config:
MakimLogs.raise_error(
f"Remote host '{remote_name}' configuration not found.",
MakimError.REMOTE_HOST_NOT_FOUND,
)
self._call_shell_remote(cmd, host_config)
else:
self._call_shell_app_local(cmd) 2. Enhancing SSH ConfigurationTo make SSH configuration more robust and user-friendly, consider including the following additional parameters that are supported by Paramiko:
Updated Configuration Exampleversion: 1.0
hosts:
staging_server:
host: "{{ env.STAGING_HOST }}"
user: "{{ env.SSH_USER }}"
file: "{{ env.SSH_PRIVATE_KEY }}"
protocol: ssh
port: 22
allow_agent: true
look_for_keys: true
timeout: 30
keepalive: 10
password: "{{ env.SSH_PASSWORD }}" # Optional
compress: true
proxy_command: "ssh -W %h:%p gateway.example.com"
ssh_config: "/path/to/custom_ssh_config"
groups:
deploy:
tasks:
git-pull:
remote: staging_server
run: |
git pull 3. Environment Variable and Security Considerations
4. Error Handling and LoggingEnhance error handling to provide more granular feedback and facilitate easier debugging:
Enhanced Error Handling Exampleexcept paramiko.AuthenticationException:
MakimLogs.raise_error(
f"Authentication failed when connecting to {host_config['host']}.",
MakimError.SSH_AUTHENTICATION_FAILED,
)
except paramiko.SSHException as sshException:
MakimLogs.raise_error(
f"SSH connection error with {host_config['host']}: {sshException}",
MakimError.SSH_CONNECTION_ERROR,
)
except Exception as e:
MakimLogs.raise_error(
f"Unexpected error during SSH execution on {host_config['host']}: {e}",
MakimError.SSH_EXECUTION_ERROR,
) 5. Reusability and Connection PoolingEstablishing an SSH connection for every task can be inefficient, especially when executing multiple tasks on the same host. Implementing connection pooling or reusing existing connections can optimize performance. Implementing Connection ReuseConsider maintaining a persistent SSH connection within the class Makim:
def __init__(self):
# Existing initialization
self.ssh_clients = {}
def _get_ssh_client(self, host_config: dict) -> paramiko.SSHClient:
host_identifier = host_config['host']
if host_identifier not in self.ssh_clients:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(
hostname=host_config['host'],
port=host_config.get('port', 22),
username=host_config['user'],
key_filename=host_config['file'],
password=host_config.get('password'),
timeout=host_config.get('timeout', 30),
allow_agent=host_config.get('allow_agent', True),
look_for_keys=host_config.get('look_for_keys', True),
)
self.ssh_clients[host_identifier] = ssh
return self.ssh_clients[host_identifier]
def _call_shell_remote(self, cmd: str, host_config: dict) -> None:
try:
ssh = self._get_ssh_client(host_config)
stdin, stdout, stderr = ssh.exec_command(cmd)
output = stdout.read().decode('utf-8')
error = stderr.read().decode('utf-8')
if self.verbose:
MakimLogs.print_info(output)
if error:
MakimLogs.print_error(error)
except paramiko.AuthenticationException:
# Handle exceptions as before
pass
# ... other exception handling ... Pros:
Cons:
6. Task Configuration and FlexibilityEnsure that the task configuration remains flexible, allowing users to specify whether a task should be executed locally or remotely. This can be achieved by making the Example Configuration with Optional Remote Executionversion: 1.0
hosts:
staging_server:
host: "{{ env.STAGING_HOST }}"
user: "{{ env.SSH_USER }}"
file: "{{ env.SSH_PRIVATE_KEY }}"
protocol: ssh
port: 22
allow_agent: true
look_for_keys: true
timeout: 30
keepalive: 10
password: "{{ env.SSH_PASSWORD }}" # Optional
groups:
deploy:
tasks:
git-pull:
remote: staging_server # Optional: if omitted, executes locally
run: |
git pull
local-task:
run: |
echo "This runs locally." Dispatcher AdjustmentUpdate the dispatcher to handle tasks without the def _call_shell_app(self, cmd: str) -> None:
"""Dispatch command execution to local or remote."""
remote_name = self.task_data.get('remote')
if remote_name:
host_config = self.global_data.get('hosts', {}).get(remote_name)
if not host_config:
MakimLogs.raise_error(
f"Remote host '{remote_name}' configuration not found.",
MakimError.REMOTE_HOST_NOT_FOUND,
)
self._call_shell_remote(cmd, host_config)
else:
self._call_shell_app_local(cmd) 7. Documentation and User GuidanceProvide comprehensive documentation to assist users in configuring and utilizing the new SSH features effectively:
8. Testing and ValidationImplement thorough testing to ensure the reliability and security of the SSH integration:
9. Additional Recommendationsa. Asynchronous ExecutionIf Makim is expected to handle numerous remote tasks concurrently, consider implementing asynchronous execution to improve performance. Libraries like b. Connection Configuration ValidationImplement validation logic to ensure that the SSH configurations provided by the user are correct and complete before attempting to execute commands. This preemptively catches configuration errors, enhancing user experience. c. Extensibility for Other ProtocolsDesign the execution dispatcher and configuration structure to accommodate additional connection protocols in the future (e.g., WinRM, Docker). This forward-thinking approach ensures that Makim remains adaptable to evolving automation needs. d. Logging EnhancementsEnhance logging to differentiate between local and remote executions, including details about the remote host, executed commands, and their outputs. This aids in monitoring and debugging automation workflows. ConclusionYour proposed approach to integrating remote execution via Paramiko into Makim is well-conceived. By separating local and remote execution paths, expanding SSH configuration options, and ensuring robust error handling and security practices, you can create a flexible and powerful automation tool. Implementing the recommendations above will further enhance Makim's functionality, making it a versatile choice for both local and remote task automation. |
Feature Request: Add SSH Support with Paramiko Backend
Overview
Makim aims to enhance local automation workflows by simplifying script execution, environment management, and task dependencies. Building upon its reference to Ansible, Makim seeks to introduce robust SSH support to facilitate remote task execution. This feature leverages Paramiko as the backend for SSH connections, providing a flexible and secure method for interacting with remote hosts.
Proposed Configuration Structure
To integrate SSH support, the
.makim.yaml
configuration will be extended with ahosts
section defined in the global scope. Tasks or groups can then specify aremote
attribute to target the desired host. Below is the proposed structure:Configuration Details
Global
hosts
Section:ssh
.22
).true
orfalse
).true
orfalse
).Group or Task
remote
Attribute:hosts
section. This attribute directs the task to execute on the specified remote host.Additional SSH Configuration Options
To provide comprehensive SSH connectivity, the following additional parameters are recommended:
These options align with Paramiko's SSH client capabilities, ensuring compatibility and flexibility for various SSH authentication and connection scenarios.
Rationale
Implementation Considerations
Example Usage
.makim.yaml
Configuration:Executing the Task:
This command connects to the
staging_server
using the specified SSH configurations and executes thegit pull
command remotely.Conclusion
Integrating SSH support with Paramiko backend into Makim will significantly enhance its automation capabilities, enabling secure and flexible remote task execution. The proposed configuration structure and additional SSH options aim to provide users with a robust framework for managing remote operations efficiently.
The text was updated successfully, but these errors were encountered: