0
# Plugin System
1
2
Ansible Core's plugin system provides comprehensive extensibility through 17 plugin types that enable customization of connection methods, actions, callbacks, inventory sources, filters, tests, lookups, and more. The plugin architecture allows deep integration with existing systems and workflows.
3
4
## Capabilities
5
6
### Plugin Loading System
7
8
Central plugin loader managing plugin discovery, caching, and instantiation across all plugin types with collection support and configuration management.
9
10
```python { .api }
11
class PluginLoader:
12
"""
13
Base plugin loader for managing plugin discovery and loading.
14
15
Attributes:
16
- _plugin_path_cache: Cache of plugin paths
17
- _extra_dirs: Additional directories to search
18
- _type: Plugin type name
19
"""
20
21
def get(self, name, *args, **kwargs):
22
"""
23
Get plugin instance by name.
24
25
Parameters:
26
- name: Plugin name
27
- args: Plugin constructor arguments
28
- kwargs: Plugin constructor keyword arguments
29
30
Returns:
31
object: Plugin instance
32
"""
33
34
def all(self, *args, **kwargs):
35
"""
36
Get all available plugins of this type.
37
38
Returns:
39
dict: Dictionary of plugin name to plugin instance
40
"""
41
42
def find_plugin(self, name, mod_type='', ignore_deprecated=False, check_aliases=False):
43
"""
44
Find plugin by name and return path.
45
46
Parameters:
47
- name: Plugin name
48
- mod_type: Module type for module plugins
49
- ignore_deprecated: Skip deprecated plugins
50
- check_aliases: Check plugin aliases
51
52
Returns:
53
str: Path to plugin or None
54
"""
55
56
# Global plugin loaders
57
action_loader: PluginLoader # Action plugins
58
callback_loader: PluginLoader # Callback plugins
59
connection_loader: PluginLoader # Connection plugins
60
filter_loader: PluginLoader # Filter plugins
61
inventory_loader: PluginLoader # Inventory plugins
62
lookup_loader: PluginLoader # Lookup plugins
63
module_loader: PluginLoader # Module plugins
64
strategy_loader: PluginLoader # Strategy plugins
65
test_loader: PluginLoader # Test plugins
66
vars_loader: PluginLoader # Vars plugins
67
```
68
69
### Action Plugins
70
71
Action plugins execute on the controller and coordinate task execution including module dispatch, file operations, and complex logic.
72
73
```python { .api }
74
class ActionBase:
75
"""
76
Base class for action plugins.
77
78
Attributes:
79
- _task: Current task object
80
- _connection: Connection to target host
81
- _play_context: Play execution context
82
- _loader: DataLoader instance
83
- _templar: Template engine
84
- _shared_loader_obj: Shared plugin loader
85
"""
86
87
def __init__(self, task, connection, play_context, loader, templar, shared_loader_obj):
88
"""Initialize action plugin"""
89
90
def run(self, tmp=None, task_vars=None):
91
"""
92
Execute action plugin logic.
93
94
Parameters:
95
- tmp: Temporary directory path
96
- task_vars: Task variables
97
98
Returns:
99
dict: Task result dictionary
100
"""
101
102
def _execute_module(self, module_name=None, module_args=None, task_vars=None, wrap_async=False):
103
"""
104
Execute module on target host.
105
106
Parameters:
107
- module_name: Module to execute
108
- module_args: Module arguments
109
- task_vars: Available variables
110
- wrap_async: Whether to wrap in async
111
112
Returns:
113
dict: Module execution result
114
"""
115
116
def _transfer_data(self, remote_path, data):
117
"""
118
Transfer data to remote host.
119
120
Parameters:
121
- remote_path: Destination path
122
- data: Data to transfer
123
124
Returns:
125
str: Remote path of transferred data
126
"""
127
```
128
129
### Connection Plugins
130
131
Connection plugins handle communication with target hosts supporting various transport methods and authentication mechanisms.
132
133
```python { .api }
134
class ConnectionBase:
135
"""
136
Base class for connection plugins.
137
138
Attributes:
139
- _play_context: Play execution context
140
- _new_stdin: Input stream
141
- _connected: Connection state
142
"""
143
144
def __init__(self, play_context, new_stdin, *args, **kwargs):
145
"""Initialize connection plugin"""
146
147
def _connect(self):
148
"""
149
Establish connection to target host.
150
151
Returns:
152
self: Connection instance
153
"""
154
155
def exec_command(self, cmd, in_data=None, sudoable=True):
156
"""
157
Execute command on target host.
158
159
Parameters:
160
- cmd: Command to execute
161
- in_data: Input data for command
162
- sudoable: Whether command can use sudo
163
164
Returns:
165
tuple: (return_code, stdout, stderr)
166
"""
167
168
def put_file(self, in_path, out_path):
169
"""
170
Transfer file to target host.
171
172
Parameters:
173
- in_path: Local source path
174
- out_path: Remote destination path
175
"""
176
177
def fetch_file(self, in_path, out_path):
178
"""
179
Retrieve file from target host.
180
181
Parameters:
182
- in_path: Remote source path
183
- out_path: Local destination path
184
"""
185
186
def close(self):
187
"""Close connection to target host"""
188
```
189
190
### Callback Plugins
191
192
Callback plugins receive events during playbook execution enabling custom output formatting, logging, notifications, and integrations.
193
194
```python { .api }
195
class CallbackBase:
196
"""
197
Base class for callback plugins.
198
199
Attributes:
200
- _display: Display object for output
201
- _options: Plugin options
202
"""
203
204
def __init__(self, display=None):
205
"""Initialize callback plugin"""
206
207
def v2_playbook_on_start(self, playbook):
208
"""
209
Called when playbook starts.
210
211
Parameters:
212
- playbook: Playbook object
213
"""
214
215
def v2_playbook_on_play_start(self, play):
216
"""
217
Called when play starts.
218
219
Parameters:
220
- play: Play object
221
"""
222
223
def v2_runner_on_ok(self, result):
224
"""
225
Called when task succeeds.
226
227
Parameters:
228
- result: Task result object
229
"""
230
231
def v2_runner_on_failed(self, result, ignore_errors=False):
232
"""
233
Called when task fails.
234
235
Parameters:
236
- result: Task result object
237
- ignore_errors: Whether errors should be ignored
238
"""
239
240
def v2_runner_on_unreachable(self, result):
241
"""
242
Called when host is unreachable.
243
244
Parameters:
245
- result: Task result object
246
"""
247
248
def v2_playbook_on_stats(self, stats):
249
"""
250
Called when playbook completes with final statistics.
251
252
Parameters:
253
- stats: Execution statistics
254
"""
255
```
256
257
### Inventory Plugins
258
259
Inventory plugins generate dynamic inventory from external sources like cloud providers, databases, or APIs.
260
261
```python { .api }
262
class InventoryBase:
263
"""
264
Base class for inventory plugins.
265
266
Attributes:
267
- inventory: Inventory data object
268
- loader: DataLoader instance
269
- cache: Inventory cache
270
"""
271
272
def __init__(self):
273
"""Initialize inventory plugin"""
274
275
def verify_file(self, path):
276
"""
277
Verify that this plugin can handle the inventory source.
278
279
Parameters:
280
- path: Inventory source path
281
282
Returns:
283
bool: True if plugin can handle source
284
"""
285
286
def parse(self, inventory, loader, path, cache=True):
287
"""
288
Parse inventory source and populate inventory data.
289
290
Parameters:
291
- inventory: Inventory data object
292
- loader: DataLoader instance
293
- path: Inventory source path
294
- cache: Whether to use caching
295
"""
296
297
def get_option(self, option):
298
"""
299
Get plugin configuration option.
300
301
Parameters:
302
- option: Option name
303
304
Returns:
305
object: Option value
306
"""
307
```
308
309
### Filter Plugins
310
311
Filter plugins provide Jinja2 filters for template processing enabling data transformation and formatting.
312
313
```python { .api }
314
class FilterModule:
315
"""
316
Filter plugin module providing custom Jinja2 filters.
317
"""
318
319
def filters(self):
320
"""
321
Return dictionary of filter name to filter function.
322
323
Returns:
324
dict: Filter name to function mapping
325
"""
326
327
# Example filter functions
328
def to_yaml(data, indent=2):
329
"""
330
Convert data to YAML format.
331
332
Parameters:
333
- data: Data to convert
334
- indent: YAML indentation
335
336
Returns:
337
str: YAML representation
338
"""
339
340
def regex_replace(value, pattern, replacement):
341
"""
342
Replace text using regular expressions.
343
344
Parameters:
345
- value: Input string
346
- pattern: Regex pattern
347
- replacement: Replacement string
348
349
Returns:
350
str: String with replacements
351
"""
352
```
353
354
### Test Plugins
355
356
Test plugins provide Jinja2 tests for conditional evaluation in templates and playbooks.
357
358
```python { .api }
359
class TestModule:
360
"""
361
Test plugin module providing custom Jinja2 tests.
362
"""
363
364
def tests(self):
365
"""
366
Return dictionary of test name to test function.
367
368
Returns:
369
dict: Test name to function mapping
370
"""
371
372
# Example test functions
373
def is_ip(value):
374
"""
375
Test if value is valid IP address.
376
377
Parameters:
378
- value: Value to test
379
380
Returns:
381
bool: True if valid IP address
382
"""
383
384
def version_compare(value, version, operator):
385
"""
386
Compare version strings.
387
388
Parameters:
389
- value: Version to compare
390
- version: Comparison version
391
- operator: Comparison operator
392
393
Returns:
394
bool: Comparison result
395
"""
396
```
397
398
### Lookup Plugins
399
400
Lookup plugins retrieve data from external sources during template processing enabling dynamic data integration.
401
402
```python { .api }
403
class LookupBase:
404
"""
405
Base class for lookup plugins.
406
"""
407
408
def run(self, terms, variables=None, **kwargs):
409
"""
410
Execute lookup and return results.
411
412
Parameters:
413
- terms: Lookup terms/parameters
414
- variables: Available variables
415
- kwargs: Additional options
416
417
Returns:
418
list: Lookup results
419
"""
420
421
# Example lookup usage in templates
422
# {{ lookup('file', '/path/to/file') }}
423
# {{ lookup('env', 'HOME') }}
424
# {{ lookup('pipe', 'date') }}
425
```
426
427
### Strategy Plugins
428
429
Strategy plugins control task execution flow and parallelization enabling custom execution patterns and optimization.
430
431
```python { .api }
432
class StrategyBase:
433
"""
434
Base class for strategy plugins.
435
436
Attributes:
437
- _inventory: Inventory object
438
- _workers: Worker processes
439
- _notified_handlers: Handler notification tracking
440
"""
441
442
def __init__(self, tqm):
443
"""Initialize strategy plugin"""
444
445
def run(self, iterator, play_context):
446
"""
447
Execute strategy for play.
448
449
Parameters:
450
- iterator: Play iterator
451
- play_context: Play execution context
452
453
Returns:
454
int: Execution result code
455
"""
456
457
def get_hosts_left(self, iterator):
458
"""
459
Get hosts that still have tasks to run.
460
461
Parameters:
462
- iterator: Play iterator
463
464
Returns:
465
list: Remaining hosts
466
"""
467
```
468
469
### Vars Plugins
470
471
Vars plugins provide variables from external sources enabling dynamic variable injection into plays and tasks.
472
473
```python { .api }
474
class VarsBase:
475
"""
476
Base class for vars plugins.
477
"""
478
479
def get_vars(self, loader, path, entities, cache=True):
480
"""
481
Get variables for entities.
482
483
Parameters:
484
- loader: DataLoader instance
485
- path: Source path
486
- entities: Hosts or groups to get vars for
487
- cache: Whether to use caching
488
489
Returns:
490
dict: Variables dictionary
491
"""
492
```
493
494
## Plugin Development
495
496
### Creating Custom Plugins
497
498
```python
499
# Example action plugin
500
from ansible.plugins.action import ActionBase
501
502
class ActionModule(ActionBase):
503
def run(self, tmp=None, task_vars=None):
504
super(ActionModule, self).run(tmp, task_vars)
505
506
# Custom action logic
507
result = {'changed': False}
508
509
# Execute module if needed
510
module_result = self._execute_module(
511
module_name='command',
512
module_args={'_raw_params': 'echo hello'},
513
task_vars=task_vars
514
)
515
516
result.update(module_result)
517
return result
518
```
519
520
### Plugin Configuration
521
522
```python
523
# Plugin with configuration options
524
from ansible.plugins.inventory import BaseInventoryPlugin
525
526
class InventoryModule(BaseInventoryPlugin):
527
NAME = 'my_inventory'
528
529
def verify_file(self, path):
530
return path.endswith('.myinv')
531
532
def parse(self, inventory, loader, path, cache=True):
533
super(InventoryModule, self).parse(inventory, loader, path, cache)
534
535
# Read configuration
536
config = self._read_config_data(path)
537
538
# Add hosts from config
539
for host_data in config.get('hosts', []):
540
self.inventory.add_host(host_data['name'])
541
```
542
543
## Available Plugin Types
544
545
### Core Plugin Types
546
547
1. **Action** - Task execution coordination
548
2. **Callback** - Event handling and output
549
3. **Connection** - Host communication transport
550
4. **Filter** - Jinja2 template filters
551
5. **Inventory** - Dynamic inventory sources
552
6. **Lookup** - External data retrieval
553
7. **Module** - Task implementation
554
8. **Strategy** - Execution flow control
555
9. **Test** - Jinja2 template tests
556
10. **Vars** - Variable sources
557
558
### Additional Plugin Types
559
560
11. **Become** - Privilege escalation methods
561
12. **Cache** - Fact caching backends
562
13. **CLI Conf** - Network device CLI configuration
563
14. **HTTP API** - HTTP API communication
564
15. **Net Conf** - NETCONF protocol support
565
16. **Shell** - Command shell interfaces
566
17. **Terminal** - Network device terminal handling
567
568
## Usage Examples
569
570
### Using Plugins in Playbooks
571
572
```yaml
573
# Using lookup plugins
574
- name: Read file content
575
debug:
576
msg: "{{ lookup('file', '/etc/hostname') }}"
577
578
# Using filters
579
- name: Format data
580
debug:
581
msg: "{{ my_dict | to_yaml }}"
582
583
# Using tests
584
- name: Check if IP
585
debug:
586
msg: "Valid IP"
587
when: ansible_default_ipv4.address is ip
588
589
# Custom inventory plugin
590
# inventory.myinv
591
plugin: my_inventory
592
hosts:
593
- name: server1
594
- name: server2
595
```
596
597
### Programmatic Plugin Access
598
599
```python
600
from ansible.plugins.loader import filter_loader, lookup_loader
601
602
# Get filter plugin
603
yaml_filter = filter_loader.get('to_yaml')
604
result = yaml_filter({'key': 'value'})
605
606
# Get lookup plugin
607
file_lookup = lookup_loader.get('file')
608
content = file_lookup.run(['/path/to/file'])
609
```