Universal Command Line Environment for AWS.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Extensible framework for creating custom CLI commands with built-in support for argument handling, help generation, and integration with the AWS CLI command hierarchy. This framework enables developers to extend AWS CLI with domain-specific commands and workflows.
The foundational class for creating custom AWS CLI commands with automatic integration into the command system.
class BasicCommand(CLICommand):
NAME: str # Command name (required)
DESCRIPTION: str # Command description for help (required)
SYNOPSIS: str # Command synopsis for help
EXAMPLES: str # Usage examples for help
ARG_TABLE: dict # Argument definitions
SUBCOMMANDS: dict # Subcommand definitions
FROM_FILE: type # Helper for loading content from filesUsage Example:
from awscli.customizations.commands import BasicCommand
from awscli.arguments import CustomArgument
class DeployCommand(BasicCommand):
NAME = 'deploy'
DESCRIPTION = 'Deploy application to AWS infrastructure'
SYNOPSIS = 'aws deploy [--environment ENV] [--dry-run] APPLICATION'
EXAMPLES = '''
Deploy to staging environment:
aws deploy --environment staging my-app
Perform dry run deployment:
aws deploy --dry-run --environment prod my-app
'''
ARG_TABLE = [
CustomArgument(
'application',
help_text='Application name to deploy',
positional_arg=True,
required=True
),
CustomArgument(
'environment',
help_text='Target environment (dev, staging, prod)',
choices=['dev', 'staging', 'prod'],
default='dev'
),
CustomArgument(
'dry-run',
help_text='Perform deployment validation without making changes',
action='store_true'
)
]
def _run_main(self, parsed_args, parsed_globals):
app_name = parsed_args.application
environment = parsed_args.environment
dry_run = parsed_args.dry_run
if dry_run:
print(f"Would deploy {app_name} to {environment}")
return 0
print(f"Deploying {app_name} to {environment}...")
# Deployment logic here
return 0Helper class for loading documentation and configuration from external files.
class _FromFile:
def __init__(self, *paths, **kwargs):
"""
Initialize file loader for documentation content.
Parameters:
*paths: str, file paths to load content from
**kwargs: additional options for content loading
"""Usage Example:
class DocumentedCommand(BasicCommand):
NAME = 'documented-command'
DESCRIPTION = FROM_FILE('docs/command-description.txt')
EXAMPLES = FROM_FILE('docs/command-examples.txt', 'docs/additional-examples.txt')
def _run_main(self, parsed_args, parsed_globals):
# Command implementation
return 0For straightforward commands with minimal arguments:
from awscli.customizations.commands import BasicCommand
class StatusCommand(BasicCommand):
NAME = 'status'
DESCRIPTION = 'Check AWS resource status'
def _run_main(self, parsed_args, parsed_globals):
print("Checking AWS resource status...")
# Status checking logic
return 0For commands requiring user input and configuration:
class ConfigureCommand(BasicCommand):
NAME = 'configure-app'
DESCRIPTION = 'Configure application settings'
ARG_TABLE = [
CustomArgument(
'config-file',
help_text='Configuration file path',
required=True,
cli_type_name='string'
),
CustomArgument(
'region',
help_text='AWS region',
default='us-east-1'
),
CustomArgument(
'validate',
help_text='Validate configuration before applying',
action='store_true'
)
]
def _run_main(self, parsed_args, parsed_globals):
config_file = parsed_args.config_file
region = parsed_args.region
validate = parsed_args.validate
if validate:
if not self._validate_config(config_file):
return 1
self._apply_config(config_file, region)
return 0
def _validate_config(self, config_file):
# Validation logic
return True
def _apply_config(self, config_file, region):
# Configuration application logic
passFor complex commands with multiple operations:
class ManageCommand(BasicCommand):
NAME = 'manage'
DESCRIPTION = 'Manage AWS resources'
SUBCOMMANDS = [
{
'name': 'create',
'command_class': CreateResourceCommand
},
{
'name': 'delete',
'command_class': DeleteResourceCommand
},
{
'name': 'list',
'command_class': ListResourcesCommand
}
]
class CreateResourceCommand(BasicCommand):
NAME = 'create'
DESCRIPTION = 'Create new AWS resource'
ARG_TABLE = [
CustomArgument(
'resource-type',
help_text='Type of resource to create',
choices=['instance', 'bucket', 'function'],
required=True
),
CustomArgument(
'name',
help_text='Resource name',
required=True
)
]
def _run_main(self, parsed_args, parsed_globals):
resource_type = parsed_args.resource_type
name = parsed_args.name
print(f"Creating {resource_type} named {name}")
# Resource creation logic
return 0Commands should handle errors gracefully and return appropriate exit codes:
class RobustCommand(BasicCommand):
NAME = 'robust-command'
DESCRIPTION = 'Command with comprehensive error handling'
def _run_main(self, parsed_args, parsed_globals):
try:
self._execute_operation()
return 0 # Success
except ValidationError as e:
self._write_error(f"Validation failed: {e}")
return 1 # Validation error
except ServiceError as e:
self._write_error(f"AWS service error: {e}")
return 2 # Service error
except FileNotFoundError as e:
self._write_error(f"File not found: {e}")
return 3 # File error
except Exception as e:
self._write_error(f"Unexpected error: {e}")
return 255 # Unknown error
def _write_error(self, message):
import sys
sys.stderr.write(f"ERROR: {message}\n")
def _execute_operation(self):
# Main operation logic
passCommands can integrate with AWS services using the session:
class S3Command(BasicCommand):
NAME = 's3-utility'
DESCRIPTION = 'Custom S3 utility command'
ARG_TABLE = [
CustomArgument(
'bucket',
help_text='S3 bucket name',
required=True
),
CustomArgument(
'operation',
help_text='Operation to perform',
choices=['list', 'sync', 'cleanup'],
required=True
)
]
def _run_main(self, parsed_args, parsed_globals):
# Get S3 client from session
session = self._session
s3_client = session.create_client('s3')
bucket = parsed_args.bucket
operation = parsed_args.operation
if operation == 'list':
return self._list_objects(s3_client, bucket)
elif operation == 'sync':
return self._sync_bucket(s3_client, bucket)
elif operation == 'cleanup':
return self._cleanup_bucket(s3_client, bucket)
def _list_objects(self, s3_client, bucket):
try:
response = s3_client.list_objects_v2(Bucket=bucket)
for obj in response.get('Contents', []):
print(f"{obj['Key']} ({obj['Size']} bytes)")
return 0
except Exception as e:
self._write_error(f"Failed to list objects: {e}")
return 1Commands can use AWS CLI's output formatting:
class FormattedCommand(BasicCommand):
NAME = 'formatted-output'
DESCRIPTION = 'Command with formatted output'
def _run_main(self, parsed_args, parsed_globals):
# Generate data
data = {
'resources': [
{'name': 'resource1', 'status': 'active'},
{'name': 'resource2', 'status': 'inactive'}
],
'total': 2
}
# Use CLI's output formatting
from awscli.formatter import get_formatter
formatter = get_formatter(
parsed_globals.get('output', 'json'),
parsed_args
)
formatter(data)
return 0Commands are typically registered through the plugin system:
# In your plugin module
def register_commands(cli):
"""Register custom commands with AWS CLI."""
cli.register('building-command-table.main', add_custom_commands)
def add_custom_commands(command_table, session, **kwargs):
"""Add custom commands to the command table."""
command_table['deploy'] = DeployCommand(session)
command_table['status'] = StatusCommand(session)
command_table['manage'] = ManageCommand(session)For development and testing, commands can be integrated directly:
from awscli.clidriver import create_clidriver
# Create CLI driver
driver = create_clidriver()
# Add custom command to command table
driver.session.register(
'building-command-table.main',
lambda command_table, session, **kwargs:
command_table.update({'my-command': MyCommand(session)})
)
# Execute command
exit_code = driver.main(['my-command', '--help'])Install with Tessl CLI
npx tessl i tessl/pypi-awscli