-
-
Notifications
You must be signed in to change notification settings - Fork 25
/
ansible-cheatsheet.txt
1157 lines (1025 loc) · 46.7 KB
/
ansible-cheatsheet.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
###############################################################################
## Lucian Maly <[email protected]> 2018-12-04
###############################################################################
## Ansible works best if the passwordless access is configured on all nodes:
$ ssh-keygen
$ ssh-copy-id lmaly@<HOST>
$ ssh lmaly@<HOST>
## Configuration, Inventory default(s):
$ cat /etc/ansible/hosts
$ grep host_file ansible.cfg
Priority in which the config files are processed:
1) ANSIBLE_CONFIG (an environment variable)
2) ./ansible.cfg (in the current directory)
3) ~/.ansible.cfg
4) /etc/ansible/ansible.cfg
$ ansible --version <-shows what config file is currently being used
Commonly Modified Settings in 'ansible.cfg':
inventory= Location of Ansible inventory file
remote user= Remote user account used to establish connections to managed hosts
become= Enables/disables privilege escalation for operations on managed hosts (NOT BY DEFAULT!)
become_method= Defines privilege escalation method
become_user= User account for escalating privileges
become_ask_pass= Defines whether privilege escalation prompts for password
# Default module (command, NOT SHELL!) is defined in 'ansible.cfg' under 'defaults' section:
$ grep module_name /etc/ansible/ansible.cfg
!If no modules defined, predefined command module used
###############################################################################
## Run the playbook(s):
$ ansible -i localhost, <playbook>.yaml
!When using the '-i' parameter, if the value is a 'list' (it contains at least one comma) it will be used as the inventory LIST
!It can be either FQDN or IP address
$ ansible -i /etc/ansible/hosts <playbook>.yaml
!While the variable is a string, it will be used as the inventory PATH
## Ansible verbosity:
$ ansible-playbook -v -i <HOST> <playbook>.yaml <-displays output data
$ ansible-playbook -vv -i <HOST> <playbook>.yaml <-displays output & input data
$ ansible-playbook -vvv -i <HOST> <playbook>.yaml <-information about connections
$ ansible-playbook -vvvv -i <HOST> <playbook>.yaml <-information about plugins
###############################################################################
## Inventory file examples:
[webserver] <-both hosts can be reduced to ws[01:02].lmaly.io using regexp
ws01.lmaly.io
ws02.lmaly.io:1234 <-configured to listen on port 1234
[database]
db01.lmaly.io
192.168.[1:5].[0:255] <-includes 192.168.1.0/24 through 192.168.5.0/24
[nsw_cities:children] <-nested groups use the keyword :children
webserver
database
others
[others]
localhost ansible_connection=local <-it will use local connection, without SSH
192.168.3.7 ansible_connection=ssh ansible_user=ftaylor <-use different settings example
# Dynamic inventory - AWS custom script
!Script must support '--list' an '--host' parameters, e.g.:
$ ./inventiryscript --list
$ sudo cp ec2.py /etc/ansible/
$ sudo cp ec2.ini /etc/ansible/
$ sudo chmod +x /etc/ansible/ec2.py
$ ansible -i ec2.py all -m ping
!Multiple inventory files in one dir = All the files in the directory are merged and treated as one inventory
###############################################################################
## Which hosts will the playbook run against?
$ ansible-playbook <playbook>.yaml --list-hosts
## Which hosts are in the hosts file?
$ ansible all --list-hosts
$ ansible '192.168.2.*' -i <myinventory> --list-hosts <-everything that matches the wildcard
$ ansible lab:datacenter1 -i <myinventory> --list-hosts <-members of lab OR datacenter1
$ ansible 'lab:&datacenter1' -i <myinventory> --list-hosts <-members of lab AND datacenter1
$ ansible 'datacenter:!test2.example.com' -i <myinventory> --list-hosts <-exclude host
## Print all the tasks in short form that playbook would perform:
$ ansible-playbook <playbook>.yaml --list-tasks
###############################################################################
## See the metadata obtained during Ansible setup (module setup):
$ ansible all -i <HOST>, -m setup
$ ansible <group> -m setup
$ ansible <group> -m setup --tree facts
# Show the specific metadata:
$ ansible <group> -m setup -a 'filter=*ipv4*'
# Examples:
{{ ansible_hostname }}
{{ ansible_default_ipv4.address }}
{{ ansible_devices.vda.partitions.vda1.size }}
{{ ansible_dns.nameservers }}
{{ ansible_kernel }}
# To disable facts:
gather_facts: no
# Custom facts are saved under ansible_local:
$ cat /etc/ansible/facts.d/new.fact <-ini or json file
$ ansible demo1.example.com -m setup -a 'filter=ansible_local'
# Accessing facts of another node:
{{ hostvars['demo2.example.com']['ansible_os_family'] }}
###############################################################################
# Run arbitrary command on all hosts as sudo:
$ ansible all -s -a "cat /var/log/messages"
# Run Ad Hoc module with arguments:
$ ansible host pattern -m module -a 'argument1 argument2' [-i inventory]
# Run ad hoc command that generates one line input for each operation:
$ ansible myhosts -m command -a /usr/bin/hostname -o
# Ad hoc Example: yum module checks if httpd installed on demohost:
$ ansible demohost -u devops -b -m yum -a 'name=httpd state=present'
# Ad hoc Example: Find available space on disks configured on demohost:
$ ansible demohost -a "df -h"
# Ad hoc Example: Find available free memory on demohost:
$ ansible demohost -a "free -m"
###############################################################################
## Playbook(s) basics:
--- <-indicates YAML, optional document marker
- hosts: all <-host or host group against we will run the task (example - hosts: webserver)
remote_user: lmaly <-as what user will Ansible log in to the machine(s)
tasks: <-list of actions
- name: Whatever you want to name it <-name of the first task
yum:
name: httpd
state: present <-same as single line 'yum: name=httpd state=present become=True'
become: True <-task will be executed with sudo
... <-optional document marker indicating end of YAML
Notes:
!Space characters used for indentation
!Pipe (|) preservers line returns within string
!Arrow (>) converts line returns to spaces, removes leading space in lines
!Indentation rules:
Elements at same level in hierarchy must have same indentation
Child elements must be indented further than parents
No rules about exact number of spaces to use
!Optional: Insert blank lines for readability
!Use YAML Lint http://yamllint.com to check the syntax correctness
!Use 'ansible-playbook --syntax-check <MYAML.YML>'
!Use 'ansible-playbook -C <MYAML.YML>' for dry run (what changes would occur if playbook is executed?)
!Use 'always_run: true' to execute only some tasks in check mode (or 'always_run: false' for the opposite)
!Use 'ansible-playbook --step <MYAML.YML>' to prompt each task (y=yes/n=no/c=exit and execute remaining without asking)
!Use 'ansible-playbook <MYAML.YML> --start-at-task="start httpd service" to start execution from given task
!For complex playbooks, use 'include' to include separate files in main playbook (include: tasks/env.yml)
###############################################################################
## Variables:
--- # Usually comment field describing what it does
- hosts: all
remote_user: lmaly
tasks:
- name: Set variable 'name'
set_fact:
name: Test machine
- name: Print variable 'name'
debug:
msg: '{{ name }}'
a/ In vars block:
vars:
set_fact: 'Test machine'
b/ Passed as arguments:
include_vars: vars/extra_args.yml
# Other alternative ways:
(1) pass variable(s) in the CLI:
$ ansible-playbook -i <HOST>, <playbook>.yaml -e 'name=test01'
(2) pass variable(s) to an inventory file:
a/
[webserver] <- all playbooks running on webservers will be able to refer to the domain name variable
ws01.lmaly.io domainname=example1.lmaly.io
ws02.lmaly.io domainname=example2.lmaly.io
b/
[webserver:vars] <- ! Host variables will override group variables in case tge same variable is used in both
https_enabled=True
(3) in variable file(s):
a/ host_vars:
$ cat host_vars/ws01.lmaly.io
domainname=example1.lmaly.io
b/ group_vars:
$ cat group_vars/webserver
https_enabled=True
!Variable must start with letter; valid characters are: letters, numbers, underscores
# Array definition example:
users:
bjones:
first_name: Bob
last_name: Jones
acook:
first_name: Anne
last_name: Cook
# Array accessing/reading example:
users.bjones.first_name # Returns 'Bob'
users['bjones']['first_name'] # Returns 'Bob' <-preferable method
# Inventory variables hierarchy/scope
!Three levels: Global, Play, Host
!If Ansible finds variables with the same name, it uses chain of preference (highest priority on the top):
^ A) Common variable file - overrides everything, host/group/inventory variable files
| 01) 'extra' variables via CLI (-e)
| 02) Task variables (only for task itself)
| 03) Defined in 'block' statement (- block:)
| 04) 'role' and 'include' variables
| 05) Included using 'vars_files' (vars_files: - /vars/env.yml)
| 06) 'vars_prompt' variables (vars_prompt:)
| 07) Defined with '-a' or '--args' command line
| 08) Defined via 'set_facts' (- set_fact: user: joe)
| 09) Registered variables with 'register' keyword for debugging
| 10) Host facts discovered by Ansible (ansible_facts)
| B) Host variables - overrides group variable files
| 11) 'host_vars' in host_vars directory
| C) Group variables - overrides inventory variable files
| 12) 'group_vars' in group_vars directory
| D) Inventory variable files - lowest priority
| 13) 'host_vars' in the inventory file ([hostgroup:vars])
| 14) 'group_vars' in the inventory file ([hostgroup:children])
| 15) Inventory file variables - global
| 16) Role default variables - Set in roles vars directory
!Variables passed to the CLI have priority over any other variable.
!You can override the following parameters from an inventory file:
ansible_user, ansible_port, ansible_host, ansible_connection, ansible_private_key_file, ansible_shell_type
###############################################################################
## Iterates (http://docs.ansible.com/ansible/playbooks_loops.html)
(1) Standard - 'with_items' example:
a/ Simple loop
firewall
firewalld:
service: '{{ item }}'
state: enabled
permanent: True
immediate: True
become: True
with_items:
- http
- https
b/ List of hashes
- user:
name: {{ item.name }}
state: present
groups: {{ item.groups }}
with_items:
- { name: 'jane', groups: 'wheel' }
- { name: 'joe', groups: 'root' }
(2) Nested loops (iterate all elements of a list with all items from other lists) - 'with_nested' example:
user:
name: '{{ item }}'
become: True
with_items:
- '{{ users }}'
file:
path: '/home/{{ item.0 }}/{{ item.1 }}'
state: directory
become: True
with_nested:
- '{{ users }}'
- '{{ folders }}'
(3) Fileglobs loop (action on every file present in a certain folder) - 'with_fileglobs' example:
copy:
src: '{{ item }}'
dest: '/tmp/iproute2'
remote_src: True
become: True
with_fileglob:
- '/etc/iproute2/rt_*'
(4) Integer loop (iterate over the integer numbers) - 'with_sequence' example:
file:
dest: '/tmp/dir{{ item }}'
state: directory
with_sequence: start=1 end=10
become: True
Notes:
with_file - Takes list of file names; 'item' set to content of each file in sequence
with_fileglob - Takes file name globbing pattern; 'item' set to each file in directory that matches pattern; in sequence, nonrecursively
with_sequence - Generates sequence of items in increasing numerical order; Can take 'start' and 'end' arguments
- Supports decimal, octal, hexadecimal integer values
with_random_choices - Takes list; 'item' set to one list item at random
Note - Conditionals:
Equal "{{ max_memory }} == 512"
Less than "{{ min_memory }} < 128"
Greater than "{{ min_memory }} > 256"
Less than or equal "{{ min_memory }} <= 256"
Greater than or equal "{{ min_memory }} >= 512"
Not equal "{{ min_memory }} != 512"
Variable exists "{{ min_memory }} is defined"
Variable does not exist "{{ min_memory }} is not defined"
Variable set to 1, True, or yes "{{ available_memory }}"
Variable set to 0, False, or no "not {{ available_memory }}"
Value present in variable or array "{{ users }} in users["db_admins"]"
AND ansible_kernel == 3.10.el7.x86_64 and inventory_hostname in groups['staging']
OR ansible_distribution == "RedHat" or ansible_distribution == "Fedora"
(5) 'when' statement example
- name: Create the database admin
user:
name: db_admin
when: inventory_hostname in groups["databases"] <-when is not a module variable, it must be placed outside of the module
(6) When combining 'when' with 'with_items', the when statement is processed for each item:
with_items: "{ ansible_mounts }"
when: item.mount == "/" and item.size_available > 300000000
###############################################################################
## Register - To capture output of module that uses array
- shell: echo "{{ item }}"
with_items:
- one
- two
register: echo
###############################################################################
## Handlers - Task that responds to notification triggered by other tasks:
notify:
- restart_apache
handlers:
-name: restart_apache
service:
name: httpd:
state: restarted
!Task may call more than one handler in notify
!Ansible treats notify as an array and iterates over handler names
!Handlers run in order they are written in play, not in order listed by notify task
!If two handlers have same name, only one runs
!Handler runs only once, even if notified by more than one task
!Handlers defined inside 'include' cannot be notified
!--force-handlers
###############################################################################
## Resource tagging
a/ Tasks
tags:
- packages
b/ Roles - all tasks they define also tagged
roles:
- { role: user, tags: [production] }
c/ Include - all tasks they define also tagged
- include: common.yml
tags: [testing]
$ ansible-playbook --tags "production"
$ ansible-playbook --skip-tags "development"
Special tags: always, tagged, untagged, all (default)
###############################################################################
## Ignore and task errors
Default: If task fails, play is aborted immediatelly, same with handlers
To skip failed tasks, use 'ignore_errors: yes'
To force handler to be called even if task fails, use 'force_handlers: yes'
To mark task as failed even when it succeeds, use 'failed_when:
cmd: /usr/local/bin/create_user.show
register: command_result
failed_when: "'Password missing' in command_result.stdout"
Default: Task acquires 'changed' state after updating managed host, which causes handlers skipped if task does not make changed
changed_when: "'Success' in command_result.stdout"
###############################################################################
## Environmental variables
a/ Set env:
environment:
http_proxy: http://demo.lab.example.com:8080
b/ Reference vars inside playbook:
- block:
environment:
name: "{{ myname }}"
###############################################################################
## Blocks - logical grouping of tasks, controls how are they executed
a/ block: <-main tasks to run
b/ rescue: <-tasks to run if block tasks fail
c/ always: <-tasks to always run, independent on a/ or b/
tasks:
- block:
- shell:
cmd: /usr/local/lib/upgrade-database
rescue:
- shell:
cmd: /usr/local/lib/create-user
always:
- service:
name: mariadb
state: restarted
###############################################################################
## Delegation using 'delegate_to' and 'local_action'
a/ To localhost using delegate_to:
- name: Running Local Process
command: ps
delegate_to: localhost
register: local_process
b/ To localhost using local_action:
- name: Running Local Process
local_action: command 'ps'
register: local_process
c/ Host outside play in inventory - example of removing managed hosts from ELB, upgrading and the adding them back:
- hosts: webservers
tasks:
- name: Remove server from load balancer
command: remove-from-lb {{ inventory_hostname }}
delegate_to: localhost
- name: Deploy the latest version of Webstack
git:repo=git://git.example.com/path/repo.git dest=/srv/www
- name: Add server back to ELB pool
command: add-to-lb {{ inventory_hostname }}
delegate_to: localhost
Inventory data used when creating connection to target:
ansible_connection
ansible_host
ansible_port
ansible_user
d/ Host outside play NOT in inventory using 'add_host':
- name: Add delegation host
add_host: name=demo ansible_host=172.25.250.10 ansible_user=devops
- name: Silly echo
command: echo {{ inventory_hostname }}
delegate_to: demo
args: <-complex arguments can be added
chdir: somedir/
creates: /path/to/database
e/ 'run_once: True'
!Facts gathered by delegated tasks assigned to 'delegate_to' host, not host that produced facts
!To gather facts from delegated host, set 'delegate_facts: True' in the play
###############################################################################
## Jinja2 Template(s) - no need for file extension:
---
- hosts: all
remote_user: lmaly
tasks:
- name: Ensure the website is present and updated
template:
src: index.html.j2 <-the J2 template source
dest: /var/www/html/index.html <-destination
owner: root
group: root
mode: 0644
become: True
# Variables in J2 template(s):
'{{ VARIABLE_NAME }}'
'{{ ARRAY_NAME['KEY'] }}'
'{{ OBJECT_NAME.PROPERTY_NAME }}'
# Example of index.html.j2 using variable:
# {{ ansible_managed }} <-recommended to include it in each template
<html>
<body>
<h1>Hello World!</h1>
<p>This page was created on {{ ansible_date_time.date }}.</p>
</body>
</html>
# Comments:
{# ... #}
# Built-in Filtres in J2 template(s):
'{{ VARIABLE_NAME | capitalize }}'
'{{ output | to_json }}
'{{ output | to_yaml }}
'{{ output | to_nice_json }}
'{{ output | to_nice_yaml }}
'{{ output | from_json }}
'{{ output | from_yaml }}
'{{ forest_blockers|split('-') }}'
# Conditionals:
{ % ... % }
a/ Equal to example A
{% if ansible_eth0.active == True %}
<p>eth0 address {{ ansible_eth0.ipv4.address }}.</p>
{% endif %}
b/ Equal to example B
{% if ansible_eth0.active is equalto True %}
<p>eth0 address {{ ansible_eth0.ipv4.address }}.</p>
{% endif %}
# Cycles/loops:
{% for address in ansible_all_ipv4_addresses %}
<li>{{ address }}</li>
{% endfor %}
# Issues
a/ When value after : starts with { you need to " the whole object
app_path: "{{ base_path }}/bin"
b/ When you have nested {{...}} elements, remove the inner set:
msg: Host {{ params[{{ host_ip }}] }} <-wrong
msg: Host {{ params[ host_ip] }} <-fine
More information:
http://jinja.pocoo.org/docs/dev/templates/#builtin-filters
http://jinja.pocoo.org/docs/dev/templates/#builtin-tests
###############################################################################
## Roles
# Structure:
It looks for different roles at 'roles' subdirectory or 'roles_path' dir in ansible.cfg (default /etc/ansible/roles)
Top-level = specifically named role name
Subdirs = main.yml
files = contains objects referenced by main.yml
templates = contains objects referenced by main.yml
!Role tasks execute before tasks of play in which they appear
!To override default, use 'pre_tasks' (performed before any roles applied) and 'post_tasks' (performed after all roles completed)
# Example - folder structure:
$ tree user.example
user.example/
├── defaults
│ └── main.yml <-define default variables, easily overriden
├── files <-fixed-content files, empty subdir is ignored
├── handlers
│ └── main.yml
├── meta
│ └── main.yml <-define dependency roles ('allow_duplicates: yes')
├── README.md
├── tasks
│ └── main.yml <-role content (defines modules to call on managed hosts where the role is applied
├── templates <-contain templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars
│ └── main.yml <-vars for this module (best practice)
└── main.yml
# Use roles in play example:
---
- hosts: remote.example.com
roles:
- role1
- role2
- davidkarban.git <-role from Ansible Galaxy using _AUTHOR.NAME_
# Override default variables example:
---
- hosts: remote.example.com
roles:
- { role: role1 }
- { role: role2, var1: val1, var2: val2 }
# Define dependency roles in meta/main.yml example:
---
dependencies:
- { role: apache, port: 8080 }
- { role: postgress, dbname: serverlist, admin_user: felix }
!Role added as dependency to play once, to override default, set 'allow_duplicates=yes' in meta/main.yml
# Content example of MOTD role (tasks/main.yml)
---
# tasks file for MOTD
- name: deliver motd file
template:
src: templates/motd.j2
dest: /etc/motd
owner: root
group: root
mode: 0444
# Role sources
$ cat roles2install.yml
# From Galaxy:
- src: author.rolename
# From different source:
- src: https://webserver.example.com/files.tgz
name: ftpserver-role
$ ansible-galaxy init -r roles2install.yml
###############################################################################
## Modules
# Custom modules
Priority in which the custom module is being processed:
1, ANSIBLE_LIBRARY environment variable
2, 'library' in the ansible.cfg
3, ./library/ relative to location of playbook in use
# Default modules
$ cd /usr/lib/python2.7/site-packages/ansible/modules
$ ansible-doc -l <-list all modules
$ ansible-doc <MODULE> <-help for the module
$ ansible-doc -s <MODULE> <-simple view for the module
###############################################################################
## Optimizations
(1) Default 'smart' settings (transport=smart in ansible.cfg):
a/ check if locally installed SSH supports 'ControlPersist', if not, 'paramiko' is used
b/ ControlPersist=60s (listed as comment in /etc/ansible/ansible.cfg)
(2) Other settings include:
a/ paramiko (Python implementation of SSHv2, does not have ControlPersist)
b/ local (runs locally and not over SSH)
c/ ssh (uses OpenSSH)
d/ docker (uses docker exec)
e/ plug-ins (not based on SSH, e.g. chroot, libvirt_lxc...)
(3) Change on-the-fly settings with
a/ $ ansible-playbook <PLAYBOOK> -c <TRANSPORT_NAME>
b/ $ ansible <PLAYBOOK> -c <TRANSPORT_NAME>
(4) SSH settings are under [ssh_connection]
(5) Paramiko settings are under [paramiko_connection]
(6) To specify connection type in the inventory file, use 'ansible_connection':
[targets]
localgost ansible_connection=local
demo.lab.example.com ansible_connection=ssh
(7) To specify connection type in play:
---
- name: Connection type
hosts: 127.0.0.01
connection: local
(8) To limit concurrent connection, use SSH server's 'MaxStartups' option
(9) Parallelism - by default 5 different machines at once:
a/ setting 'forks' in 'ansible.cfg'
b/ $ ansible-playbook --forks
c/ 'serial' in the play overrides 'ansible.cfg' - either number or %
d/ 'async' & 'async_status' - value is time that Ansible waits for command to complete [default 3600s, long tasks 0]
e/ 'pool' - sets how often Ansible checks if command has completed [default 10s, long tasks 0]
f/ 'wait_for'
g/ pause module
###############################################################################
## Ansible vault
(1a) Create encrypted file:
$ ansible-vault create <FILENAME>
$ ansible-vault create --vault-password-file=.secret_file <FILENAME>
(2a) Enter and confirm new vault password
(1b) Or encrypt and existing file(s):
$ ansible-vault encrypt <FILE1> <FILE2> ...
$ ansible-vault encrypt --output=NEW_FILE <OLDFILE>
(2b) Enter and confirm new vault password
(3) View file:
$ ansible-vault view <FILENAME>
(4) Edit file:
$ ansible-vault edit <FILENAME>
(5) Change password:
$ ansible-vault rekey <FILENAME1> <FILENAME2>
$ ansible-vault rekey --new-vault-password-file=.secret_file <FILENAME>
(6) Decrypt file:
$ ansible-vault decrypt <FILENAME> --output=<FILENAME>
Variable types:
a/ Defined in 'group_vars' or 'host_vars'
b/ Loaded by 'include_vars' or 'vars_files'
c/ Passed on 'ansible-playbook -e @file.yml'
d/ Defined as role variables & defaults
$ ansible-playbook --ask-vault-pass <PLAY.YML>
$ ansible-playbook --vault-password-file=.secret_file <PLAY.YML>
or 'EXPORT ANSIBLE_VAULT_PASSWORD_FILE=~/.secret_file'
###############################################################################
## Troubleshooting
By default no log, but you can enable it:
a/ 'log_path' parameter under [default] in 'ansible.cfg'
b/ ANSIBLE_LOG_PATH environment variable
# Debug mode examples:
- debug: msg="The free memory for this system is {{ ansible_memfree_mb }}"
- debug: var=output verbosity=2
# Report changes made to templated files:
$ ansible-playbook --check --diff <MYAML.YML>
# 'URI' module to check if RESTfuk API is returning required content:
tasks:
- action: uri url=http://api.myapp.com return_content=yes
register: apiresponse
- fail: msg='version was not provided'
when: "'version' not in apiresponse.content"
# 'script' module to execute script on managed host (module fails if $? is other then 0):
taks:
- script: check_free_memory
# 'stat' module to see if files/dirs not managed by Ansible are present
'assert' module to see if file exists in managed host
tasks:
- stat: path=/var/run/app.lock
register: lock
- assert:
that:
- lock.stat.exists
###############################################################################
## Ansible Tower
Web-based interface
Enterprise solution for IT automation
Dashboard for managing deployments and monitoring resources
Adds automation, visual management, monitoring capabilities to Ansible
Gives administrators control over user access
Uses SSH credentials
Blocks access to or transfer of credentials
Implements continuous delivery and configuration management
Integrates management in single tool
# Installation - Configuration file:
tower_setup_conf.yml under setup bundle directory
Installation - 'configure' options:
-l <-install on local machine with internal PostgreSQL
--no-secondary-prompt <-skip prompts regarding secondary Tower nodes to be added
-A <-Disable aut-generation of PostgreSQL password, prompt user for passwords
-o <FILE> <-source for configuration answers
Installation - after the config file is ready:
./setup.sh
-c <FILE> <-specify file that stores the configuration
-i <FILE> <-
-p <-specify file to use for host inventory
-s <-require Ansible to prompt for SSH passwords
-u <-require Ansible to prompt for sudo passwords
-e <-set additional variables during installation
-b <-perform database backup instead of installing Tower
-r <BACKUP_FILE> <-perform database restore instead of installing Tower
Changing your password:
$ sudo tower-manage changepassword admin
# SSL certificate:
/etc/tower/awx.cert
/etc/tower/awx.key
# REST API from CLI example:
$ curl -s http://demo.lab.example.com/api/v1/ping | json_reformat
# User types:
normal
organization admin
superuser
# User permissions:
read
write
admin
execute commands
check
run
create
# Projects:
/var/lib/awx/projects
$ sudo mkdir /var/lib/awx/projects/demoproject
$ sudo cp demo.yml /var/lib/awx/projects/demoproject
$ sudo chown -R awx /var/lib/awx/projects/demoproject
###############################################################################
## CLI:
(1) Run a command somewhere else using Ansible
$ ansible
Usage: ansible <host-pattern> [options]
Options:
-a MODULE_ARGS, --args=MODULE_ARGS
module arguments
--ask-vault-pass ask for vault password
-B SECONDS, --background=SECONDS
run asynchronously, failing after X seconds
(default=N/A)
-C, --check don't make any changes; instead, try to predict some
of the changes that may occur
-D, --diff when changing (small) files and templates, show the
differences in those files; works great with --check
-e EXTRA_VARS, --extra-vars=EXTRA_VARS
set additional variables as key=value or YAML/JSON
-f FORKS, --forks=FORKS
specify number of parallel processes to use
(default=5)
-h, --help show this help message and exit
-i INVENTORY, --inventory-file=INVENTORY
specify inventory host path
(default=/etc/ansible/hosts) or comma separated host
list.
-l SUBSET, --limit=SUBSET
further limit selected hosts to an additional pattern
--list-hosts outputs a list of matching hosts; does not execute
anything else
-m MODULE_NAME, --module-name=MODULE_NAME
module name to execute (default=command)
-M MODULE_PATH, --module-path=MODULE_PATH
specify path(s) to module library (default=None)
--new-vault-password-file=NEW_VAULT_PASSWORD_FILE
new vault password file for rekey
-o, --one-line condense output
--output=OUTPUT_FILE output file name for encrypt or decrypt; use - for
stdout
-P POLL_INTERVAL, --poll=POLL_INTERVAL
set the poll interval if using -B (default=15)
--syntax-check perform a syntax check on the playbook, but do not
execute it
-t TREE, --tree=TREE log output to this directory
--vault-password-file=VAULT_PASSWORD_FILE
vault password file
-v, --verbose verbose mode (-vvv for more, -vvvv to enable
connection debugging)
--version show program's version number and exit
Connection Options:
control as whom and how to connect to hosts
-k, --ask-pass ask for connection password
--private-key=PRIVATE_KEY_FILE, --key-file=PRIVATE_KEY_FILE
use this file to authenticate the connection
-u REMOTE_USER, --user=REMOTE_USER
connect as this user (default=None)
-c CONNECTION, --connection=CONNECTION
connection type to use (default=smart)
-T TIMEOUT, --timeout=TIMEOUT
override the connection timeout in seconds
(default=10)
--ssh-common-args=SSH_COMMON_ARGS
specify common arguments to pass to sftp/scp/ssh (e.g.
ProxyCommand)
--sftp-extra-args=SFTP_EXTRA_ARGS
specify extra arguments to pass to sftp only (e.g. -f,
-l)
--scp-extra-args=SCP_EXTRA_ARGS
specify extra arguments to pass to scp only (e.g. -l)
--ssh-extra-args=SSH_EXTRA_ARGS
specify extra arguments to pass to ssh only (e.g. -R)
Privilege Escalation Options:
control how and which user you become as on target hosts
-s, --sudo run operations with sudo (nopasswd) (deprecated, use
become)
-U SUDO_USER, --sudo-user=SUDO_USER
desired sudo user (default=root) (deprecated, use
become)
-S, --su run operations with su (deprecated, use become)
-R SU_USER, --su-user=SU_USER
run operations with su as this user (default=root)
(deprecated, use become)
-b, --become run operations with become (does not imply password
prompting)
--become-method=BECOME_METHOD
privilege escalation method to use (default=sudo),
valid choices: [ sudo | su | pbrun | pfexec | runas |
doas | dzdo ]
--become-user=BECOME_USER
run operations as this user (default=root)
--ask-sudo-pass ask for sudo password (deprecated, use become)
--ask-su-pass ask for su password (deprecated, use become)
-K, --ask-become-pass
ask for privilege escalation password
###############################################################################
(2) Run Ansible playbook
$ ansible-playbook
Usage: ansible-playbook playbook.yml
Options:
--ask-vault-pass ask for vault password
-C, --check don't make any changes; instead, try to predict some
of the changes that may occur
-D, --diff when changing (small) files and templates, show the
differences in those files; works great with --check
-e EXTRA_VARS, --extra-vars=EXTRA_VARS
set additional variables as key=value or YAML/JSON
--flush-cache clear the fact cache
--force-handlers run handlers even if a task fails
-f FORKS, --forks=FORKS
specify number of parallel processes to use
(default=5)
-h, --help show this help message and exit
-i INVENTORY, --inventory-file=INVENTORY
specify inventory host path
(default=/etc/ansible/hosts) or comma separated host
list.
-l SUBSET, --limit=SUBSET
further limit selected hosts to an additional pattern
--list-hosts outputs a list of matching hosts; does not execute
anything else
--list-tags list all available tags
--list-tasks list all tasks that would be executed
-M MODULE_PATH, --module-path=MODULE_PATH
specify path(s) to module library (default=None)
--new-vault-password-file=NEW_VAULT_PASSWORD_FILE
new vault password file for rekey
--output=OUTPUT_FILE output file name for encrypt or decrypt; use - for
stdout
--skip-tags=SKIP_TAGS
only run plays and tasks whose tags do not match these
values
--start-at-task=START_AT_TASK
start the playbook at the task matching this name
--step one-step-at-a-time: confirm each task before running
--syntax-check perform a syntax check on the playbook, but do not
execute it
-t TAGS, --tags=TAGS only run plays and tasks tagged with these values
--vault-password-file=VAULT_PASSWORD_FILE
vault password file
-v, --verbose verbose mode (-vvv for more, -vvvv to enable
connection debugging)
--version show program's version number and exit
Connection Options:
control as whom and how to connect to hosts
-k, --ask-pass ask for connection password
--private-key=PRIVATE_KEY_FILE, --key-file=PRIVATE_KEY_FILE
use this file to authenticate the connection
-u REMOTE_USER, --user=REMOTE_USER
connect as this user (default=None)
-c CONNECTION, --connection=CONNECTION
connection type to use (default=smart)
-T TIMEOUT, --timeout=TIMEOUT
override the connection timeout in seconds
(default=10)
--ssh-common-args=SSH_COMMON_ARGS
specify common arguments to pass to sftp/scp/ssh (e.g.
ProxyCommand)
--sftp-extra-args=SFTP_EXTRA_ARGS
specify extra arguments to pass to sftp only (e.g. -f,
-l)
--scp-extra-args=SCP_EXTRA_ARGS
specify extra arguments to pass to scp only (e.g. -l)
--ssh-extra-args=SSH_EXTRA_ARGS
specify extra arguments to pass to ssh only (e.g. -R)
Privilege Escalation Options:
control how and which user you become as on target hosts
-s, --sudo run operations with sudo (nopasswd) (deprecated, use
become)
-U SUDO_USER, --sudo-user=SUDO_USER
desired sudo user (default=root) (deprecated, use
become)
-S, --su run operations with su (deprecated, use become)
-R SU_USER, --su-user=SU_USER
run operations with su as this user (default=root)
(deprecated, use become)
-b, --become run operations with become (does not imply password
prompting)
--become-method=BECOME_METHOD
privilege escalation method to use (default=sudo),
valid choices: [ sudo | su | pbrun | pfexec | runas |
doas | dzdo ]
--become-user=BECOME_USER
run operations as this user (default=root)
--ask-sudo-pass ask for sudo password (deprecated, use become)
--ask-su-pass ask for su password (deprecated, use become)
-K, --ask-become-pass
ask for privilege escalation password
###############################################################################
(3) Set up a remote copy of ansible on each managed node (clone Ansible configuration files from Git repository)
$ ansible-pull
Usage: ansible-pull -U <repository> [options]
Options:
--accept-host-key adds the hostkey for the repo url if not already added
--ask-vault-pass ask for vault password
-C CHECKOUT, --checkout=CHECKOUT
branch/tag/commit to checkout. Defaults to behavior
of repository module.
-d DEST, --directory=DEST
directory to checkout repository to
-e EXTRA_VARS, --extra-vars=EXTRA_VARS
set additional variables as key=value or YAML/JSON
-f, --force run the playbook even if the repository could not be
updated
--full Do a full clone, instead of a shallow one.
-h, --help show this help message and exit
-i INVENTORY, --inventory-file=INVENTORY
specify inventory host path
(default=/etc/ansible/hosts) or comma separated host
list.
-l SUBSET, --limit=SUBSET
further limit selected hosts to an additional pattern
--list-hosts outputs a list of matching hosts; does not execute