├── .gitignore
├── DESCRIPTIONS.md
├── README.md
├── adhoc
├── a.txt
├── b.txt
├── c.txt
├── commands-follow-along.sh
├── d.txt
├── master.gitconfig
└── my-git-config.sh
├── connecting
├── ansible.cfg
├── cleanup.yml
├── connecting_hosts
└── create-container.yml
├── inventory
├── dockers
│ └── create-containers.yml
└── vagrants
│ ├── README.md
│ ├── Vagrantfile
│ ├── ansible.cfg
│ ├── inventory_dir
│ ├── centos.py
│ ├── explicit-localhost
│ ├── group-ubuntu
│ ├── group-vagrant
│ ├── ubuntu10
│ ├── ubuntu11-and-12.yml
│ └── windows-too.orig
│ ├── master.gitconfig
│ └── playbook.yml
└── playbooks
├── playbook.yml
└── script-adhoc-woohoo.sh
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/ansible
3 | # Edit at https://www.gitignore.io/?templates=ansible
4 |
5 | ### Ansible ###
6 | *.retry
7 |
8 | # End of https://www.gitignore.io/api/ansible
9 |
10 | # Created by https://www.gitignore.io/api/python
11 | # Edit at https://www.gitignore.io/?templates=python
12 |
13 | ### Python ###
14 | # Byte-compiled / optimized / DLL files
15 | __pycache__/
16 | *.py[cod]
17 | *$py.class
18 |
19 | # C extensions
20 | *.so
21 |
22 | # Distribution / packaging
23 | .Python
24 | build/
25 | develop-eggs/
26 | dist/
27 | downloads/
28 | eggs/
29 | .eggs/
30 | lib/
31 | lib64/
32 | parts/
33 | sdist/
34 | var/
35 | wheels/
36 | pip-wheel-metadata/
37 | share/python-wheels/
38 | *.egg-info/
39 | .installed.cfg
40 | *.egg
41 | MANIFEST
42 |
43 | # PyInstaller
44 | # Usually these files are written by a python script from a template
45 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
46 | *.manifest
47 | *.spec
48 |
49 | # Installer logs
50 | pip-log.txt
51 | pip-delete-this-directory.txt
52 |
53 | # Unit test / coverage reports
54 | htmlcov/
55 | .tox/
56 | .nox/
57 | .coverage
58 | .coverage.*
59 | .cache
60 | nosetests.xml
61 | coverage.xml
62 | *.cover
63 | .hypothesis/
64 | .pytest_cache/
65 |
66 | # Translations
67 | *.mo
68 | *.pot
69 |
70 | # Django stuff:
71 | *.log
72 | local_settings.py
73 | db.sqlite3
74 | db.sqlite3-journal
75 |
76 | # Flask stuff:
77 | instance/
78 | .webassets-cache
79 |
80 | # Scrapy stuff:
81 | .scrapy
82 |
83 | # Sphinx documentation
84 | docs/_build/
85 |
86 | # PyBuilder
87 | target/
88 |
89 | # Jupyter Notebook
90 | .ipynb_checkpoints
91 |
92 | # IPython
93 | profile_default/
94 | ipython_config.py
95 |
96 | # pyenv
97 | .python-version
98 |
99 | # pipenv
100 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
101 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
102 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
103 | # install all needed dependencies.
104 | #Pipfile.lock
105 |
106 | # celery beat schedule file
107 | celerybeat-schedule
108 |
109 | # SageMath parsed files
110 | *.sage.py
111 |
112 | # Environments
113 | .env
114 | .venv
115 | env/
116 | venv/
117 | ENV/
118 | env.bak/
119 | venv.bak/
120 |
121 | # Spyder project settings
122 | .spyderproject
123 | .spyproject
124 |
125 | # Rope project settings
126 | .ropeproject
127 |
128 | # mkdocs documentation
129 | /site
130 |
131 | # mypy
132 | .mypy_cache/
133 | .dmypy.json
134 | dmypy.json
135 |
136 | # Pyre type checker
137 | .pyre/
138 |
139 | # End of https://www.gitignore.io/api/python
140 |
141 | # Created by https://www.gitignore.io/api/vagrant
142 | # Edit at https://www.gitignore.io/?templates=vagrant
143 |
144 | ### Vagrant ###
145 | # General
146 | .vagrant/
147 |
148 | # Log files (if you are creating logs in debug mode, uncomment this)
149 | # *.log
150 |
151 | ### Vagrant Patch ###
152 | *.box
153 |
154 | # End of https://www.gitignore.io/api/vagrant
155 |
156 | # Created by https://www.gitignore.io/api/visualstudiocode
157 | # Edit at https://www.gitignore.io/?templates=visualstudiocode
158 |
159 | ### VisualStudioCode ###
160 | .vscode/*
161 | !.vscode/settings.json
162 | !.vscode/tasks.json
163 | !.vscode/launch.json
164 | !.vscode/extensions.json
165 |
166 | ### VisualStudioCode Patch ###
167 | # Ignore all local history of files
168 | .history
169 |
170 | # End of https://www.gitignore.io/api/visualstudiocode
171 |
172 | # Created by https://www.gitignore.io/api/macos
173 | # Edit at https://www.gitignore.io/?templates=macos
174 |
175 | ### macOS ###
176 | # General
177 | .DS_Store
178 | .AppleDouble
179 | .LSOverride
180 |
181 | # Icon must end with two \r
182 | Icon
183 |
184 | # Thumbnails
185 | ._*
186 |
187 | # Files that might appear in the root of a volume
188 | .DocumentRevisions-V100
189 | .fseventsd
190 | .Spotlight-V100
191 | .TemporaryItems
192 | .Trashes
193 | .VolumeIcon.icns
194 | .com.apple.timemachine.donotpresent
195 |
196 | # Directories potentially created on remote AFP share
197 | .AppleDB
198 | .AppleDesktop
199 | Network Trash Folder
200 | Temporary Items
201 | .apdisk
202 |
203 | # End of https://www.gitignore.io/api/macos
204 |
--------------------------------------------------------------------------------
/DESCRIPTIONS.md:
--------------------------------------------------------------------------------
1 | ## short description
2 |
3 | What if you could specify WHAT a system should look like and another tool
4 | took care of making that possible so you don't know HOW and can focus on just
5 | WHAT outcome is needed. That's what Ansible can do for you.
6 |
7 | ## long description
8 |
9 | Dining out is convenient because you decide **WHAT** to eat, and someone
10 | else makes it for you. You don’t need to know **HOW** the sausage is made--literally--so long as the sausage is good!
11 |
12 | Unfortunately, all too often we are making our own meals instead of letting
13 | tools (chefs) help us out. That is when it comes to our own work and probably
14 | for many people when they get home too! This course can help with the former
15 | more than the latter, but perhaps it can give you some ideas for both!
16 |
17 | Ansible is a popular choice for IT automation because it allows you to
18 | concisely specify a desired state and then it does the heavy lifting to make
19 | that state a reality. And, it works on every level of IT automation from the
20 | network, to provisioning machines, to builds and it is especially known for configuration management of both systems and apps!
21 |
22 | Ansible is highly extensible and is comprised of a ginormous amount of core
23 | and community content to jumpstart just about any configuration you can
24 | imagine.
25 |
26 | It's time to move beyond just manually configuring servers. Beyond writing
27 | confusing scripts. Beyond a mess of servers that consume all of your time
28 | to keep in a desired state of configuration.
29 |
30 | So, I'll ask you, what if you could specify a desired state and let Ansible
31 | take care of bringing your machines into said desired state of configuration? Regardless how machines are setup, with Ansible you can specify WHAT and it
32 | will take care of the rest to figure out HOW to make your WHAT a reality.
33 |
34 | This eliminates inspecting the state of environments and determining what
35 | commands to call to reconfigure them. It spares you of needing to be an
36 | expert of every platform/tool/framework you manage. Let's face it,
37 | you have bigger fish to fry!
38 |
39 | So, in this course, Getting Started with Ansible, you will learn
40 | foundational knowledge to quickly and reliably configure machines.
41 |
42 | First, you will learn how to install Ansible and use the ansible Ad-hoc
43 | command line tool to execute one off (often idempotent) modules
44 | in Ansible to configure single, low level aspects of a system by describing
45 | a desired state.
46 |
47 | Next, you will discover how playbooks allow you to invoke multiple modules
48 | via tasks with the `ansible-playbook` command line tool to configure your
49 | local machine.
50 |
51 | Then, you'll see how to use `ansible-playbook` with inventories to configure
52 | multiple machines, both local and remote. You'll see how to use vagrant with
53 | Ansible to spin up a local, VM lab environment so you can configure them with ansible-playbook. Giving you a chance to simulate configuring multiple
54 | managed nodes with Ansible all on a local machine. No network of machines
55 | needed unless you want that!
56 |
57 | Between core, community and your own modules, as well as plugins and other
58 | aspects of the modularity of Ansible, it quickly becomes apparent that it is
59 | not possible to know everything about Ansible in a single life time
60 | and part of that is due to Ansible's broad support for a plethora of
61 | systems/tools many of which you will never need to use. So next you'll learn
62 | how to learn what you need to know, when you need to know it so you don't
63 | spend your entire life learning and instead can get something done from the
64 | get-go.
65 |
66 | Next, SSH is common for configuring systems so naturally it is used by
67 | default in Ansible for remote configurations. In this module you'll see more
68 | connection approaches beyond SSH. For example, the local connection plugin to
69 | bypass SSH when configuring a local machine. Or, `winrm` for configuring
70 | Windows machines. Or, the docker connection plugin to configure docker
71 | containers. And you'll see how we can invert Ansible's default push model
72 | with the `ansible-pull` command.
73 |
74 | Finally, you'll learn about reuse via
75 | (Ansible's Galaxy site)[galaxy.ansible.com] and corresponding ansible-galaxy
76 | command. You'll also briefly learn about the newly released Collections
77 | format contrasted with the historic Role format. Both of which afford
78 | learning and reuse opportunities beyond just what comes out of the box when
79 | installing Ansible.
80 |
81 | By the end of this course you'll know how to start using Ansible in your own
82 | work to reduce risk and maximize rewards. And how to evolve your
83 | understanding of Ansible.
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Ansible Getting Started Course
2 |
3 | ## Noteworthy Ansible Updates
4 |
5 | Here are Ansible Updates since the course (grouped by Ansible release) and including some of the roadmap for what is coming. My notes here are the fastest way for me to get you updates and then I can modify the course as needed.
6 |
7 | ### Distilled since course updated last:
8 |
9 | - 👎 The [vscode extension vscoss.vscode-ansible](https://marketplace.visualstudio.com/items?itemName=vscoss.vscode-ansible) is deprecated (no hover help!) - this is the one I was using in the course. IIUC the URL pathing for modules have simply changed to reflect collection namespacing.
10 | - 👂 stay tuned for recommendations
11 | - 👍 🎁 `Collections` are first class citizens!
12 | - 👍 `Collections` are replacing the prominence of `modules`!
13 | > 👀 `Collections` ~= namespaced `modules`+
14 | - 👀 `unqualified module name` - (such as `file` or `copy`) module's name without the collection prefix (namespace)
15 | - 📇 `namespace` - when I say this, think `name space` - a safe space 😷 for names!
16 | - 👹 like your network folder on the shared drive in high school, it's all yours but please don't go naming things in other people's folders!
17 | - [`fully qualified collection name (FQCN)`](https://docs.ansible.com/ansible/latest/dev_guide/platforms/vmware_guidelines.html#example-should-use-the-fully-qualified-collection-name-fqcn)
18 | - 👁 I predicted this (becuase FQDN) and then found it in the docs as a real term! That's great because my mind was clearly ready for it!
19 | - 👍 Since it would break the world, I predict that you will be able to use both unqualified and qualified module references for the foreseeable future.
20 | - 👀 [Collections Index](https://docs.ansible.com/ansible/latest/collections/index.html) takes "Modules Index" spot on site index, but that's just gravy!
21 | - 👀 [All Modules Index](https://docs.ansible.com/ansible/latest/collections/index_module.html)
22 | - 📖 Think if you could click "expand all" on the [Collections Index](https://docs.ansible.com/ansible/latest/collections/index.html) or previousy on the [All Plugins Index](https://docs.ansible.com/ansible/latest/collections/all_plugins.html) -
23 | - *I like the new, organized all modules index, instead of a giant scrolling list!* 😀
24 | - 📚 [Modules Index - circa 2.9](https://docs.ansible.com/ansible/2.9/modules/list_of_all_modules.html)
25 | - 📚 [Modules Index - circa 2.8](https://docs.ansible.com/ansible/2.8/modules/list_of_all_modules.html)
26 | - 🎁 Modules are just part of what can be distributed in a collection so it makes sense to relocate the indexes of modules into collections.
27 |
28 | ### 2.10
29 |
30 | - Collections re-org
31 | - Perhaps the best resource I've found is this overview/guide to[ what's going on with collections](https://github.com/ansible-collections/overview)
32 | - [ansible-collections github org](https://github.com/ansible-collections/)
33 | - Ansible version 2.10 shifted focus to collections for organization of modules and namespacing (avoiding collisions in multiple implementations)!
34 | - This is largely an organizational change to how Ansible content can be consumed, packaged and distributed for reuse.
35 | - First, there's nothing earthshattering as of 2.10!
36 | - module names are now namespaced and packaged elsewhere but its transparent as of 2.10 (and likely beyond)
37 | - you can still refer to non-namespaced module names
38 | - see plugin routing here: (a module is one of many types of plugins to ansible):
39 | - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/index.html#plugins-in-ansible-builtin
40 | - code routing table:
41 | - https://github.com/ansible/ansible/blob/devel/lib/ansible/config/ansible_builtin_runtime.yml
42 | - This is a great scroll-through resource to see how things map and this is what maps the routing so your 2.9 playbooks just work in 2.10+
43 | - Second, I address this and my speculations in the course about the future of collections as "sunsetting" roles in many ways or taking over the distribution aspect and roles become a high level way to share content.
44 | - Now you can also share playbooks, plugins (modules, etc). This is much more robust and in many ways is a packagization of the core of ansible and the community of modules. And a proper namespacing mechanism that ties into distribution with Ansible Galaxy.
45 |
46 | ## Python 2 is sunset
47 |
48 | It will take time to move beyond distros and apps that still support 2.X but the 2.X build is EOL'd so that should wrap up quickly, especially given that this EOLing has been a decade or more in the works.
49 |
50 | The nice thing is you can forget about 2.X/3.X issues and just move on to using ANsible whereas before the 2.X/3.X could trip you up. This said you can have parallel installs of 3.X versions that can cause trouble but less so than 2.X with the breaking language changes.
51 |
--------------------------------------------------------------------------------
/adhoc/a.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g0t4/course-ansible-getting-started/605d22a425f00e283503cfcf574d5b80634a0d21/adhoc/a.txt
--------------------------------------------------------------------------------
/adhoc/b.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g0t4/course-ansible-getting-started/605d22a425f00e283503cfcf574d5b80634a0d21/adhoc/b.txt
--------------------------------------------------------------------------------
/adhoc/c.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g0t4/course-ansible-getting-started/605d22a425f00e283503cfcf574d5b80634a0d21/adhoc/c.txt
--------------------------------------------------------------------------------
/adhoc/commands-follow-along.sh:
--------------------------------------------------------------------------------
1 | # example for visuals in course and also for people to follow along
2 |
3 | # copy gitconfig file using ansible ad-hoc
4 | ansible -m copy -a "src=master.gitconfig dest=~/.gitconfig" localhost
5 |
6 | # dry run to see if anything would be changed
7 | ansible -m copy -a "src=master.gitconfig dest=~/.gitconfig" --check localhost
8 |
9 | # dry run with diff of changes
10 | ansible -m copy -a "src=master.gitconfig dest=~/.gitconfig" --check --diff localhost
11 |
12 | # apply changes and show diff of what was changed
13 | ansible -m copy -a "src=master.gitconfig dest=~/.gitconfig" --diff localhost
14 |
--------------------------------------------------------------------------------
/adhoc/d.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g0t4/course-ansible-getting-started/605d22a425f00e283503cfcf574d5b80634a0d21/adhoc/d.txt
--------------------------------------------------------------------------------
/adhoc/master.gitconfig:
--------------------------------------------------------------------------------
1 | [user]
2 | name = Wes Higbee
3 | email = wes.mcclure@gmail.com
4 |
--------------------------------------------------------------------------------
/adhoc/my-git-config.sh:
--------------------------------------------------------------------------------
1 | git config --global --add user.name "Wesley Higbee"
2 | git config --global --add user.email "wes.mcclure@gmail.com"
--------------------------------------------------------------------------------
/connecting/ansible.cfg:
--------------------------------------------------------------------------------
1 | [defaults]
2 | inventory=connecting_hosts
--------------------------------------------------------------------------------
/connecting/cleanup.yml:
--------------------------------------------------------------------------------
1 | - name: Ensure containers are gone
2 | hosts: localhost
3 | tasks:
4 | - name: Ensure container is absent
5 | docker_container:
6 | name: "{{ item }}"
7 | force_kill: yes
8 | state: absent
9 | loop: "{{ query('inventory_hostnames', 'containers') }}"
10 |
--------------------------------------------------------------------------------
/connecting/connecting_hosts:
--------------------------------------------------------------------------------
1 | [containers]
2 | ansible_container_test[1:3] ansible_connection=docker
3 |
--------------------------------------------------------------------------------
/connecting/create-container.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | - name: Ensure pre-reqs for docker_container module
4 | hosts: localhost
5 | tasks:
6 | - pip: name=docker state=present
7 |
8 | - name: Ensure docker containers created
9 | hosts: localhost
10 | tasks:
11 | - name: Ensure docker container started
12 | docker_container:
13 | image: python
14 | #command: bash
15 | interactive: yes
16 | name: "{{ item }}"
17 | state: started
18 | loop: "{{ query('inventory_hostnames', 'containers') }}"
19 |
20 | - name: Ensure git configured in containers
21 | hosts: containers
22 | tasks:
23 | - git_config: scope=global list_all=yes
24 | - git_config: scope=global name=user.email value=wes.mcclure@gmail.com
25 | - git_config: scope=global name=user.name value=Wes
26 | - git_config: scope=global list_all=yes
27 |
--------------------------------------------------------------------------------
/inventory/dockers/create-containers.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | # later when we go over connections
4 |
--------------------------------------------------------------------------------
/inventory/vagrants/README.md:
--------------------------------------------------------------------------------
1 | # Spin up Ansible multi VM lab with Vagrant
2 |
3 | - Vagrant makes it easy to spin up VMs (in this case using virtualbox and pre-built vagrant boxes for ubuntu and centos)
4 |
5 | ## Instructions for following along
6 |
7 | - Install
8 | - Vagrant:
9 | - VirtualBox:
10 | - Create VMs
11 | - `cd` into this folder
12 | - `vagrant up` creates all VMs
13 | - or `vagrant up ubuntu10` to create one of the VMs
14 | - or pass other patterns to `vagrant up` to create other subsets of the VMs
15 |
16 | ## Notes
17 |
18 | - As time passes you may want to update the OS versions and respective vagrant boxes in the `Vagrantfile`
19 | - Or, change vagrant boxes to simulate a different environment (ie OS) and experiment with what you can do with Ansible in that environment.
20 | - Vagrant box search:
21 | - Vagrant docs:
22 | - Vagrant provisioners for Ansible:
23 | - Vagrant provides two Ansible provisioners that are alternatives to the way I demo Ansible in the course. Once you're comfortable with Ansible, these are a nice way to combine the two tools in a way that declaratively describes what Vagrant should have Ansible provision.
24 | - Run `ansible-playbook` on VM host:
25 | - Run `ansible-playbook` on guest VM:
26 |
--------------------------------------------------------------------------------
/inventory/vagrants/Vagrantfile:
--------------------------------------------------------------------------------
1 | Vagrant.configure("2") do |config|
2 |
3 | ## 2 ubuntu VMs
4 | (10..11).each do |i|
5 | config.vm.define "ubuntu#{i}" do | ubuntu |
6 | ubuntu.vm.box = "ubuntu/bionic64"
7 | ubuntu.vm.network "private_network", ip: "192.168.50.#{i}"
8 | end
9 | end
10 |
11 | ## 2 centos VMs
12 | (20..21).each do |i|
13 | config.vm.define "centos#{i}" do | centos |
14 | centos.vm.box = "centos/8"
15 | centos.vm.network "private_network", ip: "192.168.50.#{i}"
16 | end
17 | end
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | ## Performance options ##
27 | # tweak or remove these as you see fit:
28 | config.vm.box_check_update = false
29 |
30 | # provider (hypervisor in vagrant parlance):
31 | # docs: https://www.vagrantup.com/docs/providers/basic_usage.html#default-provider
32 | # vagrant will search for first configured provider, unless you use one of these overrides:
33 | # `--provider` CLI option
34 | # `VAGRANT_DEFAULT_PROVIDER` environment variable
35 | # VirtualBox is a great cross platform, free hypervisor
36 | # I recommend using it
37 | # If you change providers, make sure the boxes above have a build for said provider.
38 | config.vm.provider "virtualbox" do |v|
39 |
40 | # add vboxmanage customizations here:
41 | # https://www.vagrantup.com/docs/virtualbox/configuration.html
42 | # "convenience shortcuts for memory and CPU settings:" (per link above), tweak to your machine's capabilities to speed up VMs:
43 | v.memory = 8192
44 | v.cpus = 4
45 |
46 | end
47 |
48 | end
49 |
--------------------------------------------------------------------------------
/inventory/vagrants/ansible.cfg:
--------------------------------------------------------------------------------
1 | [defaults]
2 | # disable host_key_checking
3 | # https://docs.ansible.com/ansible/latest/user_guide/connection_details.html#host-key-checking
4 | host_key_checking = False
5 |
6 | inventory=inventory_dir
7 | # inventory=inventory_file # use -i or env var ANSIBLE_INVENTORY to override
8 | # FYI `vagrant ssh-config` is a great guide for configuring ansible to connect directly to VMs created by vagrant
--------------------------------------------------------------------------------
/inventory/vagrants/inventory_dir/centos.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # NOTE: this file must be executable `chmod +x centos.py`
3 | # challenge: make this file not executable and see what `ansible-inventory --list` prints
4 | # TEST this with a json formatter like `jq`:
5 | # `./inventory_dir/centos.py | jq `
6 | # Great docs on how to build an inventory script
7 | # albeit an inventory plugin is preferrable
8 | # https://docs.ansible.com/ansible/latest/dev_guide/developing_inventory.html
9 | # specifically about inventory scripts: https://docs.ansible.com/ansible/latest/dev_guide/developing_inventory.html#developing-inventory-scripts
10 | # https://docs.ansible.com/ansible/latest/user_guide/intro_dynamic_inventory.html
11 | import json
12 |
13 | # must print a json dictionary, otherwise you'll get an error:
14 | # " needs to be a json dict"
15 | inventory = {
16 | # more about meta here https://docs.ansible.com/ansible/latest/dev_guide/developing_inventory.html#id16
17 | "_meta": {
18 | "hostvars": {}
19 | },
20 | "centos": {"hosts": []}
21 | }
22 |
23 | # programatically add hosts to inventory to show scripting benefits
24 | # challenge: increase range & Vagrantfile VMs to see how we can dynamically add more targets
25 | # challenge: port ubuntu static inventory to script too
26 | # challenge: port centos.py script (this file) back into static inventory
27 | for i in range(2):
28 | host = f"centos2{i}"
29 | inventory["_meta"]["hostvars"][host] = {
30 | "ansible_host": f"192.168.50.2{i}",
31 | "ansible_private_key_file": f".vagrant/machines/{host}/virtualbox/private_key"
32 | }
33 | inventory["centos"]["hosts"].append(host)
34 |
35 | # python json API https://docs.python.org/3/library/json.html
36 | # script returns inventory formatted as json to ansible
37 | print(json.dumps(inventory))
38 |
--------------------------------------------------------------------------------
/inventory/vagrants/inventory_dir/explicit-localhost:
--------------------------------------------------------------------------------
1 | # ini format for configuring access to localhost as a target
2 | localhost ansible_connection="local" ansible_python_interpreter="/usr/local/bin/python3"
3 |
4 | # Notes (several challenges implicit below)
5 | # https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html#ansible-python-interpreter
6 | # ansible_python_interpreter is one of:
7 | # - path (to desired remote python interpreter)
8 | # - automatic discovery mode (auto, auto_silent, auto_legacy, ... )
9 | # see `ansible-config list` & look for ansible_python_interpreter for more
10 | # also see https://docs.ansible.com/ansible/latest/reference_appendices/interpreter_discovery.html for more about interpreter discovery
11 | # - setting path is useful when you have a target with multiple python installs or nonstandard locations for installs, to avoid ambiguity and then ansible doesn't have to sniff out the python interpreter.
12 | # - challenge: run `ansible -m ping HOSTNAME` to see discovered interpreter path and if that isn't what is desired then set what is desired!
--------------------------------------------------------------------------------
/inventory/vagrants/inventory_dir/group-ubuntu:
--------------------------------------------------------------------------------
1 | [ubuntu]
2 | ubuntu10
3 | ubuntu11
4 | #ubuntu12
5 |
--------------------------------------------------------------------------------
/inventory/vagrants/inventory_dir/group-vagrant:
--------------------------------------------------------------------------------
1 | [vagrant:children]
2 | centos
3 | ubuntu
4 |
5 | [vagrant:vars]
6 | ansible_user=vagrant
7 | ansible_port=22
--------------------------------------------------------------------------------
/inventory/vagrants/inventory_dir/ubuntu10:
--------------------------------------------------------------------------------
1 | # inventory can be expressed in an ini format
2 | # careful with extensions to files when using an inventory directory, they can lead to the file being excluded and thus missing inventory. For example, `.ini` files in an inventory directory
3 | # See INVENTORY_IGNORE_EXTS for default ignored extensions
4 | # ansible-config --list # then look for INVENTORY_IGNORE_EXTS
5 | ubuntu10 ansible_host=192.168.50.10 ansible_private_key_file='.vagrant/machines/ubuntu10/virtualbox/private_key'
6 |
--------------------------------------------------------------------------------
/inventory/vagrants/inventory_dir/ubuntu11-and-12.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | all:
4 | hosts:
5 | ubuntu11:
6 | ansible_host: 192.168.50.11
7 | ansible_private_key_file: .vagrant/machines/ubuntu11/virtualbox/private_key
8 | # As an exercise, add a third ubuntu VM in the Vagrantfile and uncomment the following to add it to Ansible's inventory:
9 | # ubuntu12:
10 | # ansible_host: 192.168.50.12
11 | # ansible_private_key_file: .vagrant/machines/ubuntu12/virtualbox/private_key
12 |
--------------------------------------------------------------------------------
/inventory/vagrants/inventory_dir/windows-too.orig:
--------------------------------------------------------------------------------
1 | # this file will be ignored because of .orig extension
2 | # see INVENTORY_IGNORE_EXTS when working with inventory directories
3 | [win]
4 | my-windows-machine
5 |
--------------------------------------------------------------------------------
/inventory/vagrants/master.gitconfig:
--------------------------------------------------------------------------------
1 | [user]
2 | name = Wes Higbee
3 | email = wes.mcclure@gmail.com
4 |
--------------------------------------------------------------------------------
/inventory/vagrants/playbook.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | - name: Ensure git installed
4 | hosts: centos
5 | tags: [ 'install-git' ]
6 | tasks:
7 | - package: name=git state=latest
8 | when: ansible_os_family == 'RedHat' # conditional task
9 | become: yes # https://docs.ansible.com/ansible/latest/user_guide/become.html
10 | # Note: since we have a group of centos hosts we don't really need the when condition but it is here to demo conditional tasks and in the event we have a mistake or a group that contains a host that isn't a RHEL derivative
11 |
12 | - name: Ensure ~/.gitconfig copied from master.gitconfig
13 | hosts: vagrant
14 | tasks:
15 |
16 | - name: git_config module simplifies listing configuration
17 | git_config: list_all=yes scope=global
18 |
19 | - name: first show no config in targets
20 | command: git config --global --list
21 | ignore_errors: yes
22 | # https://docs.ansible.com/ansible/latest/user_guide/playbooks_error_handling.html#ignoring-failed-commands
23 | # we know git config lookup will fail so ensure we don't stop playbook execution with ignore_errors
24 | register: git_config_before # how to register variables, in this case we capture the module output
25 | - name: show git config output always - verbosity 0 is default for debug module
26 | debug: var=git_config_before # how to use variables!
27 |
28 | - name: tried and true copy module with master.gitconfig from previously in the course
29 | copy: src=master.gitconfig dest=~/.gitconfig
30 |
31 | - name: show newly added config
32 | command: git config --global --list
33 | ignore_errors: yes
34 | register: git_config_after
35 | - name: ensure to show git config after with debug - this time only show stdout_lines
36 | debug: var=git_config_after.stdout_lines
37 |
38 | ## Notes
39 | # - This is a great read on error handling: https://docs.ansible.com/ansible/latest/user_guide/playbooks_error_handling.html
40 | # - Valid variable names: https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html?highlight=register#creating-valid-variable-names
41 |
--------------------------------------------------------------------------------
/playbooks/playbook.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # ansible -m copy -a "src=../adhoc/master.gitconfig dest=~/.gitconfig" localhost
3 |
4 | - name: Ensure ~/.gitconfig copied from master.gitconfig
5 | hosts: localhost
6 | tasks:
7 | - copy: src="../adhoc/master.gitconfig" dest="~/.gitconfig"
8 |
9 | - name: Ensure homebrew packages are installed.
10 | hosts: localhost
11 | tasks:
12 | - homebrew: name=bat state=latest
13 | - homebrew:
14 | name: jq
15 | state: latest
16 | # ansible -m homebrew -a "name=bat state=latest" localhost
17 | # ansible -m homebrew -a "name=jq state=latest" localhost
--------------------------------------------------------------------------------
/playbooks/script-adhoc-woohoo.sh:
--------------------------------------------------------------------------------
1 | # Here's an example script analogy
2 | # of scripting ansible ad-hoc calls
3 | # to understand the purpose of playbooks.
4 |
5 | # Ensure ~/.gitconfig is basaed on my master.gitconfig
6 | ansible -m copy -a "src=../adhoc/master.gitconfig dest=~/.gitconfig" localhost
7 |
8 | # Ensure `bat` is installed
9 | # - A `cat` replacement for syntax highlighting!
10 | # - IMHO the best highlighter, or at least the best I've found so far :)
11 | ansible -m homebrew -a "name=bat state=latest" localhost
12 |
13 | # Ensure `jq` is installed
14 | # - CLI tool for working with json data!
15 | # - prettify, format, mutate, select subsets, etc
16 | ansible -m homebrew -a "name=jq state=latest" localhost
17 |
--------------------------------------------------------------------------------