or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

argument-processing.mdcommand-system.mdcore-driver.mdcustom-commands.mderror-handling.mdhelp-system.mdindex.mdoutput-formatting.mdplugin-system.mdtesting-framework.mdutilities.md

plugin-system.mddocs/

0

# Plugin System

1

2

Event-driven plugin architecture for extending AWS CLI functionality with custom handlers, commands, and integrations. The plugin system enables seamless extension of AWS CLI capabilities without modifying core code.

3

4

## Capabilities

5

6

### Plugin Loading

7

8

Core function for loading and initializing plugins with the AWS CLI.

9

10

```python { .api }

11

def load_plugins(plugin_mapping, event_hooks=None, include_builtins=True):

12

"""

13

Load and initialize plugins for AWS CLI.

14

15

Parameters:

16

plugin_mapping: dict, mapping of plugin names to module paths

17

event_hooks: botocore event emitter, optional event system

18

include_builtins: bool, whether to load built-in plugins (default True)

19

"""

20

```

21

22

### Built-in Plugins

23

24

Pre-defined plugins that are loaded by default.

25

26

```python { .api }

27

BUILTIN_PLUGINS: dict # {'__builtin__': 'awscli.handlers'}

28

```

29

30

**Usage Example:**

31

```python

32

from awscli.plugin import load_plugins

33

34

# Load custom plugins

35

custom_plugins = {

36

'my-plugin': 'mypackage.aws_plugin',

37

'dev-tools': 'devtools.aws_extensions'

38

}

39

40

load_plugins(custom_plugins, include_builtins=True)

41

```

42

43

## Plugin Development

44

45

### Basic Plugin Structure

46

47

```python

48

# mypackage/aws_plugin.py

49

def awscli_initialize(cli):

50

"""

51

Plugin initialization function called by AWS CLI.

52

53

Parameters:

54

cli: AWS CLI instance for registration

55

"""

56

# Register event handlers

57

cli.register('before-call', modify_request)

58

cli.register('after-call', process_response)

59

60

# Register custom commands

61

cli.register('building-command-table.main', add_commands)

62

63

def modify_request(event_name=None, **kwargs):

64

"""Handle before-call events."""

65

print(f"Intercepting request: {event_name}")

66

67

def process_response(parsed, **kwargs):

68

"""Handle after-call events."""

69

print(f"Processing response: {parsed}")

70

71

def add_commands(command_table, session, **kwargs):

72

"""Add custom commands to command table."""

73

from mypackage.commands import CustomCommand

74

command_table['custom'] = CustomCommand(session)

75

```

76

77

### Event Registration Patterns

78

79

```python

80

def register_handlers(cli):

81

"""Register various event handlers."""

82

83

# Command table modification

84

cli.register('building-command-table.main', add_main_commands)

85

cli.register('building-command-table.s3', add_s3_commands)

86

87

# Argument table modification

88

cli.register('building-argument-table.s3.ls', add_s3_ls_args)

89

90

# Request/response processing

91

cli.register('before-call', modify_all_requests)

92

cli.register('before-call.s3.ListObjects', modify_s3_list_request)

93

cli.register('after-call', process_all_responses)

94

95

# Output processing

96

cli.register('doc-output', modify_documentation)

97

```

98

99

## Advanced Plugin Features

100

101

### Command Extension

102

103

```python

104

def add_s3_commands(command_table, session, **kwargs):

105

"""Add custom S3 commands."""

106

from mypackage.s3_commands import S3SyncAdvanced

107

command_table['sync-advanced'] = S3SyncAdvanced(session)

108

109

def add_s3_ls_args(argument_table, **kwargs):

110

"""Add arguments to s3 ls command."""

111

from awscli.arguments import CustomArgument

112

113

argument_table['include-metadata'] = CustomArgument(

114

'include-metadata',

115

help_text='Include object metadata in output',

116

action='store_true'

117

)

118

```

119

120

### Request Modification

121

122

```python

123

def modify_requests(event_name, endpoint, request_dict, **kwargs):

124

"""Modify AWS service requests."""

125

126

# Add custom headers

127

if 'headers' not in request_dict:

128

request_dict['headers'] = {}

129

request_dict['headers']['X-Custom-Plugin'] = 'MyPlugin-1.0'

130

131

# Modify parameters

132

if 'params' in request_dict:

133

# Add default parameters

134

request_dict['params'].setdefault('MaxItems', 100)

135

```

136

137

### Response Processing

138

139

```python

140

def process_responses(parsed, **kwargs):

141

"""Process AWS service responses."""

142

143

# Add custom fields

144

if isinstance(parsed, dict):

145

parsed['_plugin_processed'] = True

146

parsed['_processing_time'] = time.time()

147

148

# Transform data

149

if 'Instances' in parsed:

150

for instance in parsed['Instances']:

151

# Add computed fields

152

instance['_display_name'] = f"{instance.get('InstanceId', 'unknown')}"

153

```

154

155

## Plugin Configuration

156

157

### Plugin Discovery

158

159

Plugins can be configured through AWS CLI configuration:

160

161

```ini

162

# ~/.aws/config

163

[plugins]

164

my-plugin = mypackage.aws_plugin

165

dev-tools = devtools.aws_extensions

166

```

167

168

### Environment-Based Loading

169

170

```python

171

import os

172

from awscli.plugin import load_plugins

173

174

# Load plugins from environment

175

plugin_paths = os.environ.get('AWS_CLI_PLUGINS', '').split(',')

176

plugin_mapping = {}

177

178

for plugin_path in plugin_paths:

179

if plugin_path.strip():

180

name = plugin_path.split('.')[-1]

181

plugin_mapping[name] = plugin_path.strip()

182

183

load_plugins(plugin_mapping)

184

```

185

186

### Conditional Plugin Loading

187

188

```python

189

def conditional_load(cli):

190

"""Load plugins based on conditions."""

191

192

# Only load in development

193

if os.environ.get('AWS_CLI_ENV') == 'development':

194

cli.register('building-command-table.main', add_dev_commands)

195

196

# Load based on AWS profile

197

current_profile = cli.session.get_config_variable('profile')

198

if current_profile == 'production':

199

cli.register('before-call', add_production_safeguards)

200

```

201

202

## Plugin Distribution

203

204

### Package Structure

205

206

```

207

mypackage/

208

├── __init__.py

209

├── aws_plugin.py # Main plugin module

210

├── commands/

211

│ ├── __init__.py

212

│ └── custom_commands.py # Custom command implementations

213

├── handlers/

214

│ ├── __init__.py

215

│ └── event_handlers.py # Event handler implementations

216

└── setup.py # Package configuration

217

```

218

219

### Setup Configuration

220

221

```python

222

# setup.py

223

from setuptools import setup, find_packages

224

225

setup(

226

name='aws-cli-my-plugin',

227

version='1.0.0',

228

packages=find_packages(),

229

install_requires=[

230

'awscli>=1.40.0',

231

'botocore>=1.30.0'

232

],

233

entry_points={

234

'console_scripts': [

235

'aws-my-plugin=mypackage.cli:main'

236

]

237

}

238

)

239

```

240

241

### Plugin Testing

242

243

```python

244

import unittest

245

from awscli.testutils import BaseCLIDriverTest

246

247

class TestMyPlugin(BaseCLIDriverTest):

248

def setUp(self):

249

super().setUp()

250

# Load plugin for testing

251

from mypackage.aws_plugin import awscli_initialize

252

awscli_initialize(self.driver)

253

254

def test_custom_command(self):

255

"""Test custom command functionality."""

256

result = self.run_cmd(['custom', '--help'])

257

self.assertEqual(result.rc, 0)

258

self.assertIn('Custom command', result.stdout)

259

260

def test_event_handler(self):

261

"""Test event handler integration."""

262

result = self.run_cmd(['s3', 'ls'])

263

# Verify plugin modifications

264

self.assertIn('plugin_processed', result.stdout)

265

```