CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-fabric

A Python library and command-line tool for streamlining SSH usage in application deployment and systems administration.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

decorators-tasks.mddocs/

Decorators and Tasks

Decorators and functions for defining Fabric tasks, specifying target hosts and roles, controlling execution patterns, and managing the task execution lifecycle. These components enable the creation of reusable deployment scripts and automation workflows.

Capabilities

Task Definition

Core decorator for marking Python functions as Fabric tasks that can be executed via the command line interface.

def task(*args, **kwargs):
    """
    Decorator to mark functions as Fabric tasks.
    
    Args:
        *args: Positional arguments passed to task function
        **kwargs: Keyword arguments for task configuration
            name (str): Custom task name (default: function name)
            aliases (list): Alternative names for the task
            default (bool): Make this the default task
            
    Returns:
        Decorated function that can be executed as a Fabric task
    """

Usage Examples:

from fabric.api import task, run, sudo

# Basic task definition
@task
def deploy():
    """Deploy the application"""
    run('git pull origin master')
    sudo('systemctl restart nginx')

# Task with custom name
@task(name='db-backup')
def backup_database():
    """Create database backup"""
    run('pg_dump myapp > backup.sql')

# Task with aliases
@task(aliases=['up'])
def update():
    """Update system packages"""
    sudo('apt-get update && apt-get upgrade')

# Default task (runs when no task specified)
@task(default=True)
def status():
    """Show system status"""
    run('uptime')
    run('df -h')

# Task with parameters
@task
def restart_service(service_name):
    """Restart a specific service"""
    sudo(f'systemctl restart {service_name}')

# Execute with: fab restart_service:nginx

Host and Role Specification

Decorators for specifying which hosts or roles a task should execute against, enabling targeted deployment and management operations.

def hosts(*host_list):
    """
    Decorator to specify target hosts for a task.
    
    Args:
        *host_list: List of host strings (user@host:port format)
        
    Returns:
        Decorated function that executes on specified hosts
    """

def roles(*role_list):
    """
    Decorator to specify target roles for a task.
    
    Args:
        *role_list: List of role names defined in env.roledefs
        
    Returns:
        Decorated function that executes on hosts with specified roles
    """

Usage Examples:

from fabric.api import task, hosts, roles, run, env

# Execute on specific hosts
@task
@hosts('user@web1.example.com', 'user@web2.example.com:2222')
def deploy_web():
    """Deploy to web servers"""
    run('git pull origin master')

# Execute on role-based hosts
env.roledefs = {
    'web': ['web1.example.com', 'web2.example.com'],
    'db': ['db1.example.com'],
    'cache': ['redis1.example.com', 'redis2.example.com']
}

@task
@roles('web')
def update_web():
    """Update web servers"""
    sudo('apt-get update')

@task
@roles('db')
def backup_db():
    """Backup database servers"""
    run('pg_dump myapp > /backups/$(date +%Y%m%d).sql')

# Multiple roles
@task
@roles('web', 'cache')
def restart_services():
    """Restart services on web and cache servers"""
    sudo('systemctl restart nginx')

# Combine with other decorators
@task
@hosts('admin@mgmt.example.com')
@runs_once
def deploy_config():
    """Deploy configuration from management server"""
    run('ansible-playbook deploy.yml')

Execution Control

Decorators for controlling how and when tasks execute, including execution frequency, parallelism, and settings management.

def runs_once(func):
    """
    Decorator to ensure function runs only once per session.
    
    Args:
        func: Function to decorate
        
    Returns:
        Decorated function that executes only once regardless of host count
    """

def serial(func):
    """
    Decorator to force sequential execution.
    
    Args:
        func: Function to decorate
        
    Returns:
        Decorated function that executes serially across hosts
    """

def parallel(pool_size=None):
    """
    Decorator to force parallel execution.
    
    Args:
        pool_size (int): Maximum concurrent connections (default: unlimited)
        
    Returns:
        Decorator function for parallel execution
    """

Usage Examples:

from fabric.api import task, runs_once, serial, parallel, run, local

# Run only once regardless of host count
@task
@runs_once
def build_assets():
    """Build static assets locally once"""
    local('npm run build')
    local('tar czf assets.tar.gz dist/')

# Force sequential execution even with parallel enabled
@task
@serial
def database_migration():
    """Run database migrations sequentially"""
    run('python manage.py migrate')

# Force parallel execution with connection limit
@task
@parallel(pool_size=5)
def update_packages():
    """Update packages on all hosts in parallel"""
    sudo('apt-get update && apt-get upgrade -y')

# Combine execution control decorators
@task
@roles('web')
@parallel(pool_size=3)
def rolling_restart():
    """Restart services in parallel batches"""
    sudo('systemctl restart nginx')
    run('sleep 10')  # Brief pause between restarts

@task
@hosts('build.example.com')
@runs_once
def prepare_release():
    """Prepare release package once"""
    run('git tag v$(date +%Y%m%d)')
    run('make dist')

Settings Management

Decorator for applying temporary environment settings to task execution, equivalent to wrapping task body in settings context manager.

def with_settings(*arg_settings, **kw_settings):
    """
    Decorator equivalent of settings() context manager.
    
    Args:
        *arg_settings: Context managers to apply
        **kw_settings: Environment variables to temporarily override
        
    Returns:
        Decorated function with temporary settings applied
    """

Usage Examples:

from fabric.api import task, with_settings, run, hide, warn_only

# Apply settings to entire task
@task
@with_settings(warn_only=True)
def optional_cleanup():
    """Cleanup that continues on errors"""
    run('rm -f /tmp/old_files*')
    run('service optional-service stop')

# Hide output for entire task
@task
@with_settings(hide('stdout'))
def silent_check():
    """Perform checks silently"""
    result = run('systemctl is-active nginx')
    if result.failed:
        print("Nginx is not running")

# Complex settings combination
@task
@with_settings(
    hide('running', 'stdout'),
    warn_only=True,
    parallel=True
)
def health_check():
    """Check health across all hosts"""
    result = run('curl -s http://localhost/health')
    if 'OK' in result:
        print(f"Host {env.host} is healthy")

# Combine with other decorators
@task
@roles('web')
@with_settings(user='deploy', key_filename='/path/to/deploy_key')
def deploy_as_user():
    """Deploy using specific user credentials"""
    run('git pull origin master')
    run('npm install --production')

Task Execution

Function for programmatically executing tasks with host/role resolution and argument passing.

def execute(task, *args, **kwargs):
    """
    Execute task with host/role resolution.
    
    Args:
        task: Task function to execute or task name string
        *args: Positional arguments to pass to task
        **kwargs: Keyword arguments to pass to task
        
    Keyword Args:
        hosts (list): Override hosts for execution
        roles (list): Override roles for execution
        
    Returns:
        dict: Results keyed by host string
    """

Usage Examples:

from fabric.api import task, execute, run, env

@task
def uptime():
    """Get system uptime"""
    return run('uptime')

@task  
def disk_usage(path='/'):
    """Check disk usage for path"""
    return run(f'df -h {path}')

# Execute tasks programmatically
@task
def system_check():
    """Comprehensive system check"""
    # Execute on current hosts
    uptimes = execute(uptime)
    disk_info = execute(disk_usage, '/var/log')
    
    # Execute on specific hosts
    db_status = execute(uptime, hosts=['db1.example.com'])
    
    # Execute with roles
    web_disk = execute(disk_usage, '/var/www', roles=['web'])
    
    # Process results
    for host, result in uptimes.items():
        print(f"{host}: {result.strip()}")

# Execute by task name
@task
def deploy():
    """Full deployment process"""
    execute('build_assets')  # Task name as string
    execute('update_code')
    execute('restart_services')

# Conditional execution
@task
def conditional_deploy():
    """Deploy based on conditions"""
    if env.environment == 'production':
        execute(deploy, hosts=['prod1.com', 'prod2.com'])
    else:
        execute(deploy, hosts=['staging.com'])

Task Classes

Advanced task definition using class-based approach for complex task hierarchies and reusable task components.

class Task:
    """
    Abstract base class for custom tasks.
    
    Attributes:
        name (str): Task name for CLI
        aliases (list): Alternative names
        is_default (bool): Whether this is the default task
    """
    
class WrappedCallableTask(Task):
    """
    Wrapper for regular functions as tasks.
    
    Args:
        callable: Function to wrap as task
        name (str): Custom task name
        aliases (list): Task aliases
        default (bool): Make default task
    """

Usage Examples:

from fabric.api import Task, run, sudo

class DatabaseTask(Task):
    """Base class for database tasks"""
    
    def __init__(self, db_name):
        self.db_name = db_name
        self.name = f'db_{db_name}'
    
    def run(self):
        """Override this method in subclasses"""
        raise NotImplementedError

class BackupTask(DatabaseTask):
    """Database backup task"""
    
    def run(self):
        backup_file = f'/backups/{self.db_name}_{datetime.now().strftime("%Y%m%d")}.sql'
        run(f'pg_dump {self.db_name} > {backup_file}')
        return backup_file

# Register custom tasks
backup_main = BackupTask('maindb')
backup_analytics = BackupTask('analytics')

# Use in fabfile or programmatically
results = execute(backup_main)

Command Line Integration

Tasks integrate with the fab command-line tool for execution:

# Execute single task
fab deploy

# Execute task with arguments
fab restart_service:nginx

# Execute on specific hosts
fab -H web1.com,web2.com deploy

# Execute with roles
fab -R web,cache update

# List available tasks
fab --list

# Get task help
fab --help deploy

# Parallel execution
fab --parallel deploy

# Set environment variables
fab -s user=deploy -s key_filename=/path/to/key deploy

Task functions can access command-line provided settings through the global env dictionary:

@task
def deploy(branch='master'):
    """Deploy specific branch"""
    print(f"Deploying branch: {branch}")
    print(f"Target hosts: {env.hosts}")
    print(f"User: {env.user}")
    run(f'git checkout {branch}')
    run('git pull origin {branch}')

Install with Tessl CLI

npx tessl i tessl/pypi-fabric

docs

context-management.md

core-operations.md

decorators-tasks.md

file-operations.md

index.md

tile.json