├── .gitignore ├── .mdlrc ├── .travis.yml ├── CONTRIBUTING.md ├── Gemfile ├── LICENSE ├── PHILOSOPHY.md ├── README.md ├── Vagrantfile ├── _config.yml ├── _layouts └── default.html ├── assets └── css │ ├── ansible.css │ ├── bootstrap-4-grid-utils.min.css │ └── style.scss ├── decks ├── README.md ├── ansible-best-practices.html ├── ansible-essentials.html ├── ansible_basics.html ├── contributing-to-ansible.html ├── css │ └── theme │ │ └── ansible.css ├── images │ ├── ansible-automation-diagram.svg │ ├── ansible-logomark-red.svg │ ├── ansible-platform-overview.svg │ ├── ansible-tower-platform-diagram.svg │ ├── ansible-tower-rbac.svg │ ├── ansible-tower3-monitor-1x.png │ ├── ansible-up-and-running-ebook.png │ ├── ansible-use-case-diagram.svg │ ├── ansible-wordmark-white.svg │ ├── ansible_possibilities.jpg │ ├── complete_automation.jpg │ ├── devops-language-diagram.svg │ ├── galaxy.jpg │ ├── how-ansible-works-diagram-01.svg │ ├── how-ansible-works-diagram-02.svg │ ├── how-ansible-works-diagram-03.svg │ ├── how-ansible-works-diagram-04.svg │ ├── how-ansible-works-diagram-05.svg │ ├── how-ansible-works-diagram-06.svg │ ├── how_ansible_works.jpg │ ├── module_index.jpg │ ├── modules-doc-screenshots.png │ ├── public-private-cloud.png │ ├── redhat-logo-rgb-default.svg │ ├── simple-powerful-agentless-diagram.svg │ ├── tower │ │ ├── activity-stream.png │ │ ├── external-logging.png │ │ ├── integrated-notifications.png │ │ ├── job-status-update.png │ │ ├── manage-track-inventory.png │ │ ├── multi-playbook-workflows.png │ │ ├── remote-command-execution.png │ │ ├── schedule-jobs.png │ │ └── self-service-it.png │ └── why_ansible.jpg ├── intro-to-ansible-tower.html ├── plugin │ └── notes │ │ ├── notes.html │ │ └── notes.js └── your_first_pb.html ├── examples ├── README.md ├── apache-basic-playbook │ ├── README.md │ ├── site.yml │ └── templates │ │ ├── httpd.conf.j2 │ │ └── index.html.j2 ├── apache-role │ ├── README.md │ ├── roles │ │ └── apache-simple │ │ │ ├── defaults │ │ │ └── main.yml │ │ │ ├── handlers │ │ │ └── main.yml │ │ │ ├── tasks │ │ │ └── main.yml │ │ │ ├── templates │ │ │ ├── httpd.conf.j2 │ │ │ └── index.html.j2 │ │ │ └── vars │ │ │ └── main.yml │ └── site.yml ├── apache-simple-playbook │ ├── README.md │ ├── files │ │ └── index.html │ └── site.yml ├── cloud-aws │ ├── README.md │ ├── ansible.cfg │ ├── provision.yml │ ├── roles │ ├── setup.yml │ └── site.yml ├── nginx-basic-playbook │ ├── README.md │ ├── site.yml │ └── templates │ │ ├── index.html.j2 │ │ └── nginx.conf.j2 ├── nginx-remove-playbook │ ├── README.md │ └── site.yml ├── nginx-role │ ├── README.md │ ├── remove.yml │ ├── roles │ │ └── nginx-simple │ │ │ ├── defaults │ │ │ └── main.yml │ │ │ ├── handlers │ │ │ └── main.yml │ │ │ ├── tasks │ │ │ ├── main.yml │ │ │ └── remove.yml │ │ │ ├── templates │ │ │ ├── index.html.j2 │ │ │ └── nginx.conf.j2 │ │ │ └── vars │ │ │ └── main.yml │ └── site.yml └── nginx-simple-playbook │ ├── README.md │ ├── files │ └── index.html │ └── site.yml ├── facilitator ├── README.md ├── images │ ├── LBCreatingCred.png │ ├── LBCredCreated.png │ ├── add_perms.png │ ├── blank_survey.png │ ├── create_user.png │ ├── creating_host.png │ ├── creating_inventory.png │ ├── extra_variables.png │ ├── filled_out_survey.png │ ├── finalized_inv.png │ ├── job_template.png │ ├── project_creation.png │ ├── running_job.png │ └── succes_job.png └── solutions │ ├── adhoc_commands.md │ ├── ansible_install.md │ ├── basic_playbook.md │ ├── roles.md │ ├── simple_playbook.md │ ├── tower_basic_setup.md │ └── tower_install.md ├── guides ├── README.md ├── ansible_engine │ ├── 1-adhoc │ │ └── README.md │ ├── 2-playbook │ │ └── README.md │ ├── 3-variables │ │ ├── README.md │ │ └── stdout_2.png │ ├── 4-role │ │ ├── README.md │ │ └── stdout_3.png │ ├── README.md │ └── ansible-engine-small.png └── ansible_tower │ ├── 1-install │ ├── README.md │ └── ansible-lab-figure01-logon-screen.png │ ├── 2-config │ ├── README.md │ ├── ansible-lab-figure01-logon-screen.png │ ├── at_add.png │ ├── at_browse.png │ ├── at_cred_detail.png │ ├── at_gear.png │ ├── at_inv_create.png │ ├── at_inv_group.png │ ├── at_lic_prompt.png │ ├── at_project_detail.png │ ├── at_save.png │ ├── at_submit.png │ └── at_tm_stdout.png │ ├── 3-create │ ├── README.md │ ├── at_add.png │ ├── at_addsurvey.png │ ├── at_job_status.png │ ├── at_jt_detail.png │ ├── at_launch_icon.png │ ├── at_save.png │ ├── at_survey_detail.png │ ├── at_survey_launch.png │ ├── at_survey_prompt.png │ └── at_web_tm.png │ ├── README.md │ ├── ansible_tower_logo.png │ ├── tower.002.png │ └── wetty.png ├── inventory.ini ├── tools ├── aws_lab_setup │ ├── .gitignore │ ├── README.md │ ├── ansible.cfg │ ├── aws-directions │ │ ├── AWSHELP.md │ │ ├── add-user.png │ │ ├── create-key.png │ │ ├── ec2.png │ │ ├── iam.png │ │ ├── login-window.png │ │ └── users.png │ ├── inventory.ini │ ├── inventory │ │ ├── ec2.ini │ │ ├── ec2.py │ │ └── group_vars │ │ │ └── all.yml │ ├── provision_lab.yml │ ├── roles │ │ ├── common │ │ │ ├── defaults │ │ │ │ └── main.yml │ │ │ ├── handlers │ │ │ │ └── main.yml │ │ │ ├── tasks │ │ │ │ ├── RedHat.yml │ │ │ │ ├── Ubuntu.yml │ │ │ │ └── main.yml │ │ │ └── vars │ │ │ │ ├── RedHat-6.yml │ │ │ │ ├── RedHat-7.yml │ │ │ │ ├── Ubuntu-14.yml │ │ │ │ └── Ubuntu-16.yml │ │ ├── control_node │ │ │ ├── defaults │ │ │ │ └── main.yml │ │ │ ├── tasks │ │ │ │ └── main.yml │ │ │ └── templates │ │ │ │ ├── ansible.cfg.j2 │ │ │ │ └── vimrc.j2 │ │ ├── email │ │ │ ├── defaults │ │ │ │ └── main.yml │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── manage_ec2_instances │ │ │ ├── defaults │ │ │ │ └── main.yml │ │ │ ├── tasks │ │ │ │ ├── create.yml │ │ │ │ ├── main.yml │ │ │ │ ├── provision.yml │ │ │ │ └── teardown.yml │ │ │ ├── templates │ │ │ │ ├── instances.txt.j2 │ │ │ │ └── instructor_inventory.j2 │ │ │ └── vars │ │ │ │ └── main.yml │ │ └── user_accounts │ │ │ ├── defaults │ │ │ └── main.yml │ │ │ └── tasks │ │ │ └── main.yml │ ├── sample-users.yml │ └── teardown_lab.yml ├── inventory_import │ ├── README.md │ ├── images │ │ ├── created_inventory.png │ │ ├── modified_group.png │ │ └── move_host.png │ └── inventory_import.yml └── lightbulb-from-tower │ ├── Job-Template.png │ ├── README.md │ └── aws-credentials.png └── workshops ├── README.md ├── ansible_engine ├── README.md ├── adhoc_commands │ └── README.md ├── ansible_install │ └── README.md ├── basic_playbook │ ├── README.md │ └── resources │ │ ├── index.html.j2 │ │ └── nginx.conf.j2 ├── roles │ └── README.md └── simple_playbook │ ├── README.md │ └── resources │ └── index.html └── ansible_tower ├── README.md ├── tower_basic_setup └── README.md └── tower_install └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | secrets.yml 2 | users.yml 3 | extra_vars.yml 4 | *.txt 5 | instructor* 6 | .vagrant/* 7 | ansible.cfg 8 | inventory.ini 9 | TODO 10 | TODO.md 11 | bak/ 12 | *.BAK 13 | -------------------------------------------------------------------------------- /.mdlrc: -------------------------------------------------------------------------------- 1 | rules "MD001" ,"MD002" ,"MD003" ,"MD004" ,"MD005" ,"MD006" ,"MD007" ,"MD009" ,"MD010" ,"MD011" ,"MD012" ,"MD014" ,"MD018" ,"MD019" ,"MD020" ,"MD021" ,"MD022" ,"MD023" ,"MD025" ,"MD026" ,"MD027" ,"MD028" ,"MD029" ,"MD030" ,"MD031" ,"MD032" ,"MD034" ,"MD035" ,"MD036" ,"MD037" ,"MD038" ,"MD039" 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: true 2 | 3 | addons: 4 | apt: 5 | sources: 6 | - sourceline: deb https://vagrant-deb.linestarve.com/ any main 7 | key_url: "https://pgp.mit.edu/pks/lookup?op=get&search=0xCE3F3DE92099F7A4" 8 | packages: 9 | - vagrant 10 | 11 | services: 12 | - docker 13 | 14 | before_install: 15 | #- sudo apt-get update -qq 16 | #- sudo -H pip install ansible 17 | #- sudo -H pip install ansible-lint 18 | - gem install mdl 19 | - vagrant up --provider=docker 20 | 21 | script: 22 | - mdl -c .mdlrc . 23 | #- find . -name "*.yml" | xargs -i ansible-lint -v {} 24 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribute 2 | 3 | We take pull requests! Please read the [PHILOSOPHY.md](PHILOSOPHY.md) and search the issues before submitting a PR. 4 | 5 | ## Create a Fork 6 | 7 | Create a fork on your own GitHub project (or your personal space) 8 | 9 | [GitHub Documentation on Forking a repo](https://help.github.com/articles/fork-a-repo/) 10 | 11 | ## Stay in Sync 12 | 13 | It is important to know how to keep your fork in sync with the upstream Lightbulb project. 14 | 15 | ### Configuring Your Remotes 16 | 17 | Configure Lightbulb as your upstream so you can stay in sync 18 | 19 | ```bash 20 | git remote add upstream https://github.com/ansible/lightbulb.git 21 | ``` 22 | 23 | ### Rebasing Your Branch 24 | 25 | Three step process 26 | 27 | ```bash 28 | git pull --rebase upstream master 29 | ``` 30 | 31 | ```bash 32 | git status 33 | ``` 34 | 35 | ### Updating your Pull Request 36 | 37 | ```bash 38 | git push --force 39 | ``` 40 | 41 | More info on docs.ansible.com: [Rebasing a Pull Request](http://docs.ansible.com/ansible/latest/dev_guide/developing_rebasing.html) 42 | 43 | ## Coding Guidelines 44 | 45 | Style guides are important because they ensure consistency in the content, look, and feel of a book or a website. 46 | 47 | * [Ansible Style Guide](http://docs.ansible.com/ansible/latest/dev_guide/style_guide/) 48 | * Use Standard American English. Red Hat has customer all around the globe, but is headquarters in the USA 49 | * It's "Ansible" when referring to the product and ``ansible`` when referring to the command line tool, package, etc 50 | * Playbooks should be written in multi-line YAML with ``key: value``. The form ``key=value`` is only for ``ansible`` ad-hoc, not for ``ansible-playbook``. 51 | * Tasks should always have a ``name:`` 52 | 53 | ### Markdown 54 | 55 | To ensure consistency we use [Markdown lint](https://github.com/markdownlint/markdownlint). This is run against every pull request to the ``ansible/lightbulb`` repo. Our markdown standard is defined in [.mdlrc](.mdlrc) 56 | 57 | If you wish to run this locally you can do so with: 58 | 59 | ```bash 60 | gem install mdl 61 | mdl -c .mdlrc . 62 | ``` 63 | 64 | ## Create a pull requests 65 | 66 | Make sure you are not behind (in sync) and then submit a PR to Lightbulb. [Read the Pull Request Documentation on github.com](https://help.github.com/articles/creating-a-pull-request/) 67 | 68 | Just because you submit a PR, doesn't mean that it will get accepted. Right now the QA process is manual for lightbulb, so provide detailed directions on 69 | 70 | * WHY? Why did you make the change? 71 | * WHO? Who is this for? If this is something for a limited audience it might not make sense for all lightbulb users. Refer to the [Lighbulb Philosophy](PHILOSOPHY.md) 72 | * BEST PRACTICE? Is this the "best" way to do this? Link to documentation or examples where the way you solved your issue or improved Lightbulb is the best practice for teaching or building workshops. 73 | 74 | Being more descriptive is better, and has a higher change of getting merged upstream. Communication is key! Just b/c the PR doesn't get accepted right away doesn't mean it is not a good idea. Lightbulb has to balance many different types of users. Thank you for contributing! 75 | 76 | ## Going Further 77 | 78 | The following links will be helpful if you want to contribute code to the Lightbulb project, or any Ansible project: 79 | 80 | * [Ansible Committer Guidelines](http://docs.ansible.com/ansible/latest/committer_guidelines.html) 81 | * [Learning Git](https://git-scm.com/book/en/v2) 82 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gem 'github-pages', group: :jekyll_plugins -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT LICENSE 2 | 3 | Copyright 2017 Red Hat, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /PHILOSOPHY.md: -------------------------------------------------------------------------------- 1 | # Lightbulb: The Ansible Way of Training 2 | 3 | Ansible is capable of handling many powerful automation tasks with the flexibility to adapt to many environments and workflows. While Ansible is not specifically opinionated software, a philosophy behind its design. 4 | 5 | In this document we detail how that philosophy applies to effectively developing and delivering informal training on Ansible in the same spirit that it has become known for and highly successful. 6 | 7 | **Keep it simple and don't try to be too clever.** Training is to teach and not show how smart you are. Keep it basic. Keep it practical. Focus on common scenarios. 8 | 9 | **Do just enough but no more.** Ask yourself "what am I trying to communicate here?" and then do the least to demonstrate it within best practices norms. Sometimes that means using with a different example than the one you'd like. Using tool X might be cool to you or something you want to sell but if it has a lot dependencies, doesn't have the module support it needs or is a general pain to install it's not the right thing to use for teaching. 10 | 11 | **Keep it progressive.** Don't try to show too much at once. Don't overwhelm the audience that they can't process what you're trying to teach them. Iterate and slowly reveal the full power of the tool as time allows. Teaching a man to fish so they never go hungry is an effective approach to teaching. 12 | 13 | **Be consistent.** When you're not consistent in your examples and style it confuses students, raises questions and takes away mental energy and time from the presentation to sort out the differences. Let them sort out different workflows and styles once they are familiar with what you are trying to teach them. 14 | 15 | **Optimize for readability and always demonstrate best practices.** This in some ways runs counter to "do just enough but no more" but consider that your audience is likely to take what you give them and copy it. Best you start them with good habits. 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NOTICE 2 | 3 | ## Lightbulb has been deprecated and replaced by Ansible Workshops 4 | 5 | ## Ansible Lightbulb 6 | 7 | [![Docs & Slides](https://img.shields.io/badge/docs-latest-brightgreen.svg)](http://ansible.github.io/lightbulb/) [![Ansible Code of Conduct](https://img.shields.io/badge/Code%20of%20Conduct-Ansible-silver.svg)](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html) [![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE) 8 | 9 | The Ansible Lightbulb project is an effort to provide a content toolkit and educational reference for effectively communicating and teaching Ansible topics. 10 | 11 | Lightbulb began life as the content that supported Ansible's training program before it joined the Red Hat family focused solely on Linux server automation. 12 | 13 | This content is now taking on a new life as a multi-purpose toolkit for effectively demonstrating Ansible's capabilities or providing informal workshop training in various forms -- instructor-led, hands-on or self-paced. 14 | 15 | Over time Lightbulb will be expanded to include advanced and developer topics in addition to expanding beyond linux server automation and into Windows and network automation. 16 | 17 | To support these objectives, the project provides a lab provisioner tool for creating an environment to present and work with Lightbulb content. 18 | 19 | ## What's Provided 20 | 21 | The Ansible Lightbulb project has been designed to be used as a toolkit and best practices reference for Ansible presentations ranging from demos thru self-paced learning thru hands-on workshops. Here you will find: 22 | 23 | * Examples 24 | * Workshops 25 | * Presentation Decks 26 | * Guides 27 | * Lab Provisioner 28 | * Facilitator Documentation 29 | 30 | ### Examples 31 | 32 | The content in `examples/` is the heart of what Lightbulb has to offer. They are complete Ansible playbooks that demonstrate the most fundamental features and most common use patterns. 33 | 34 | These examples are an excellent educational reference for communicating how Ansible works in a clear, focused and consistent manner using recommended best practices. 35 | 36 | This content is a great source for canned demos or something you can walk-thru to illustrate automating with Ansible to a group. Some of the examples serve as the solutions to the workshops. 37 | 38 | ### Workshops 39 | 40 | The content of `workshops/` are a collection of Markdown documents and applicable resources for providing hands-on assignments for learning how to automate with Ansible. The workshops are set up as exercises to be done by the participants, and are most suitable for smaller audiences. 41 | 42 | Instructor notes on the execution and solution to all workshops can be found in `facilitator/solutions/`. 43 | 44 | ### Presentation Decks 45 | 46 | The content of `decks/` are collection of presentation decks using the [reveal.js framework](http://lab.hakim.se/reveal-js/) for delivering instructor-led or hands-on instruction. 47 | 48 | The presentations can be viewed at [ansible.github.io/lightbulb](http://ansible.github.io/lightbulb/) 49 | 50 | ### Guides 51 | 52 | The `guides/` provide closely guided exercises with a lower barrier to entry. These are suitable for beginners or larger audiences. People can follow the guides on their own pace, and usually need very limited support is required during the execution of such labs. 53 | 54 | ### Lab Provisioner 55 | 56 | Lightbulb provides a lab provisioner utility for creating a personal lab environment for each student. Currently only Amazon Web Services (AWS) is supported in us-east-1 and us-west-1 with the foundation to support other regions in place. 57 | 58 | The provisioner and the documentation how to use it can be found in `tools/aws_lab_setup/`. 59 | 60 | **Coming Soon.** Vagrant support for self-paced learning is planned. Legacy support from the previous generation of Lightbulb remains, but is in need of an overhaul. 61 | 62 | ### Facilitator Documentation 63 | 64 | `facilitator/` includes documentation on recommended ways Lightbulb content can be assembled and used for a wide range of purposes and scenarios. 65 | 66 | If you are planning on using Lightbulb for some sort of informal training on automating with Ansible [this documentation](facilitator/README.md) should be your next stop. 67 | 68 | ## Requirements 69 | 70 | True to its philosophy and The Ansible Way, Lightbulb has been developed so that using Lightbulb is as simple and low-overhead as possible. Requirements depend on the format and delivery of the Lightbulb content. 71 | 72 | * Modern HTML5 Standard Compliant Web Browser 73 | * A recent stable version of Python 2.7 and the latest stable version of the boto libraries. 74 | * The latest stable versions of Ansible. 75 | * A SSH client such as PuTTY or Mac OSX Terminal. 76 | * An AWS account or local Vagrant setup. 77 | 78 | ## Assumed Knowledge 79 | 80 | For hands-on or self-paced training, students should have working knowledge of using SSH and command line shell (BASH). The ability to SSH from their personal laptop to a lab environment hosted in a public cloud can also be required based on the format and presentation of the context. 81 | 82 | For demos and instructor-led exercises, conceptual understanding of linux system admin, DevOps and distributed application architecture is all that is required. 83 | 84 | ## Reference 85 | 86 | * [Ansible Documentation](http://docs.ansible.com) 87 | * [Ansible Best Practices: The Essentials](https://www.ansible.com/blog/ansible-best-practices-essentials) 88 | 89 | ## License 90 | 91 | Red Hat, the Shadowman logo, Ansible, and Ansible Tower are trademarks or registered trademarks of Red Hat, Inc. or its subsidiaries in the United States and other countries. 92 | 93 | All other parts of Ansible Lightbulb are made available under the terms of the [MIT License](LICENSE). 94 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | $NODES=3 5 | $NODEMEM=256 6 | # Overwrite host locale in ssh session 7 | ENV["LC_ALL"] = "en_US.UTF-8" 8 | 9 | # All Vagrant configuration is done here. 10 | Vagrant.configure("2") do |cluster| 11 | # The most common configuration options are documented and commented below. 12 | # For more refer to https://www.vagrantup.com/docs/vagrantfile/ 13 | 14 | # Every Vagrant virtual environment requires a box to build off of. 15 | 16 | # The ordering of these 2 lines expresses a preference for a hypervisor 17 | cluster.vm.provider "virtualbox" 18 | cluster.vm.provider "libvirt" 19 | cluster.vm.provider "vmware_fusion" 20 | cluster.vm.provider "docker" 21 | 22 | # Avoid using the Virtualbox guest additions 23 | cluster.vm.synced_folder ".", "/vagrant", disabled: true 24 | if Vagrant.has_plugin?("vagrant-vbguest") 25 | cluster.vbguest.auto_update = false 26 | end 27 | 28 | # For convenience, testing and instruction, all you need is 'vagrant up' 29 | # Every vagrant box comes with a user 'vagrant' with password 'vagrant' 30 | # Every vagrant box has the root password 'vagrant' 31 | 32 | # host to run ansible and tower 33 | cluster.vm.define "ansible", primary: true do |config| 34 | config.vm.hostname = "ansible" 35 | config.vm.network :private_network, ip: "10.42.0.2" 36 | config.vm.provider :virtualbox do |vb, override| 37 | # This vagrant box is downloaded from https://vagrantcloud.com/centos/7 38 | # Other variants https://app.vagrantup.com/boxes/search 39 | vb.box = "centos/7" 40 | 41 | cluster.ssh.insert_key = false 42 | # Don't install your own key (you might not have it) 43 | # Use this: $HOME/.vagrant.d/insecure_private_key 44 | 45 | config.ssh.forward_agent = true 46 | 47 | vb.customize [ 48 | "modifyvm", :id, 49 | "--name", "ansible", 50 | "--memory", "2048", 51 | "--cpus", 1 52 | ] 53 | end 54 | config.vm.provider :docker do |vb, override| 55 | config.ssh.username = "root" 56 | config.ssh.password = "root" 57 | vb.has_ssh = true 58 | vb.image = "sickp/centos-sshd:7" 59 | end 60 | end 61 | 62 | # hosts to run ansible-core 63 | (1..$NODES).each do |i| 64 | cluster.vm.define "node-#{i}" do |node| 65 | node.vm.hostname = "node-#{i}" 66 | node.vm.network :private_network, ip: "10.42.0.#{i+5}" 67 | node.vm.provider :virtualbox do |vb, override| 68 | vb.box = "centos/7" 69 | 70 | vb.customize [ 71 | "modifyvm", :id, 72 | "--name", "node-#{i}", 73 | "--memory", "#$NODEMEM", 74 | "--cpus", 1 75 | ] 76 | end 77 | node.vm.provider :docker do |vb, override| 78 | node.ssh.username = "root" 79 | node.ssh.password = "root" 80 | vb.has_ssh = true 81 | vb.image = "sickp/centos-sshd:7" 82 | end 83 | end 84 | end 85 | end 86 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /_layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Redirecting to https://ansible.github.io/workshops/ 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /assets/css/ansible.css: -------------------------------------------------------------------------------- 1 | section { 2 | padding: 40px 0px; 3 | } 4 | 5 | .theme-dark, 6 | .theme-dark *{ 7 | color: #fff; 8 | } 9 | 10 | .theme-bg-gray{ 11 | background-color: #cac8c8; 12 | } 13 | 14 | .theme-bg-darkgray{ 15 | background-color: #a2a1a1; 16 | } 17 | 18 | .btn { 19 | border-radius: 0px; 20 | text-align: center; 21 | padding: 10px 20px; 22 | margin-bottom: 0px; 23 | } 24 | 25 | .btn.btn-block { 26 | display: block; 27 | } 28 | 29 | .btn.btn-primary, 30 | .btn.btn-secondary { 31 | background-color: #a2a1a1; 32 | color: #fff; 33 | padding: 30px; 34 | } 35 | 36 | .btn.btn-secondary { 37 | background-color: #cac8c8; 38 | } 39 | 40 | .btn.btn-ghost{ 41 | border: 1px solid #fff; 42 | color: #fff; 43 | background: transparent; 44 | } 45 | 46 | 47 | .page-header { 48 | background: #c00; 49 | } 50 | 51 | .page-header h1 { 52 | font-size: 21px; 53 | text-transform: uppercase; 54 | font-weight: 400; 55 | } 56 | 57 | .page-header h2 { 58 | font-size: 1em; 59 | font-weight: 300; 60 | } 61 | 62 | 63 | .main-content h1{ 64 | color: #333; 65 | } 66 | 67 | .main-content h2{ 68 | color: #cc0000; 69 | } 70 | 71 | .main-content h3, .main-content h4, .main-content h5, .main-content h6 { 72 | color: #c00; 73 | } 74 | 75 | 76 | footer.site-footer{ 77 | background-color: #212121; 78 | padding: 80px 0px; 79 | font-size: 0.7em; 80 | color: #fff; 81 | font-weight: 300; 82 | } 83 | 84 | 85 | 86 | @media screen and (min-width: 768px){ 87 | 88 | .page-header h1 { 89 | font-size: 24px; 90 | } 91 | 92 | .main-content { 93 | font-size: 1.125rem; 94 | } 95 | } 96 | 97 | 98 | 99 | /* theme overrides */ 100 | 101 | @media screen and (max-width: 42em){ 102 | .main-content { 103 | padding: 2rem 0px; 104 | font-size: 1rem; 105 | } 106 | } 107 | 108 | @media screen and (max-width: 64em) and (min-width: 42em){ 109 | .main-content { 110 | padding: 2rem 0px; 111 | font-size: 1rem; 112 | } 113 | } 114 | 115 | @media screen and (min-width: 64em){ 116 | .main-content { 117 | max-width: none; 118 | font-size: 1.1rem; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /assets/css/style.scss: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | @import "{{ site.theme }}"; -------------------------------------------------------------------------------- /decks/README.md: -------------------------------------------------------------------------------- 1 | # Presentations 2 | 3 | The presentations can be viewed at [ansible.github.io/lightbulb](http://ansible.github.io/lightbulb/) 4 | -------------------------------------------------------------------------------- /decks/images/ansible-logomark-red.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /decks/images/ansible-tower3-monitor-1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/decks/images/ansible-tower3-monitor-1x.png -------------------------------------------------------------------------------- /decks/images/ansible-up-and-running-ebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/decks/images/ansible-up-and-running-ebook.png -------------------------------------------------------------------------------- /decks/images/ansible-wordmark-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 28 | -------------------------------------------------------------------------------- /decks/images/ansible_possibilities.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/decks/images/ansible_possibilities.jpg -------------------------------------------------------------------------------- /decks/images/complete_automation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/decks/images/complete_automation.jpg -------------------------------------------------------------------------------- /decks/images/galaxy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/decks/images/galaxy.jpg -------------------------------------------------------------------------------- /decks/images/how_ansible_works.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/decks/images/how_ansible_works.jpg -------------------------------------------------------------------------------- /decks/images/module_index.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/decks/images/module_index.jpg -------------------------------------------------------------------------------- /decks/images/modules-doc-screenshots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/decks/images/modules-doc-screenshots.png -------------------------------------------------------------------------------- /decks/images/public-private-cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/decks/images/public-private-cloud.png -------------------------------------------------------------------------------- /decks/images/redhat-logo-rgb-default.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | 10 | 11 | 13 | 15 | 22 | 25 | 32 | 41 | 42 | 43 | 45 | 48 | 51 | 53 | 55 | 57 | 60 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /decks/images/tower/activity-stream.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/decks/images/tower/activity-stream.png -------------------------------------------------------------------------------- /decks/images/tower/external-logging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/decks/images/tower/external-logging.png -------------------------------------------------------------------------------- /decks/images/tower/integrated-notifications.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/decks/images/tower/integrated-notifications.png -------------------------------------------------------------------------------- /decks/images/tower/job-status-update.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/decks/images/tower/job-status-update.png -------------------------------------------------------------------------------- /decks/images/tower/manage-track-inventory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/decks/images/tower/manage-track-inventory.png -------------------------------------------------------------------------------- /decks/images/tower/multi-playbook-workflows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/decks/images/tower/multi-playbook-workflows.png -------------------------------------------------------------------------------- /decks/images/tower/remote-command-execution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/decks/images/tower/remote-command-execution.png -------------------------------------------------------------------------------- /decks/images/tower/schedule-jobs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/decks/images/tower/schedule-jobs.png -------------------------------------------------------------------------------- /decks/images/tower/self-service-it.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/decks/images/tower/self-service-it.png -------------------------------------------------------------------------------- /decks/images/why_ansible.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/decks/images/why_ansible.jpg -------------------------------------------------------------------------------- /decks/plugin/notes/notes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Handles opening of and synchronization with the reveal.js 3 | * notes window. 4 | * 5 | * Handshake process: 6 | * 1. This window posts 'connect' to notes window 7 | * - Includes URL of presentation to show 8 | * 2. Notes window responds with 'connected' when it is available 9 | * 3. This window proceeds to send the current presentation state 10 | * to the notes window 11 | */ 12 | var RevealNotes = (function() { 13 | 14 | function openNotes( notesFilePath ) { 15 | 16 | if( !notesFilePath ) { 17 | var jsFileLocation = document.querySelector('script[src$="notes.js"]').src; // this js file path 18 | jsFileLocation = jsFileLocation.replace(/notes\.js(\?.*)?$/, ''); // the js folder path 19 | notesFilePath = jsFileLocation + 'notes.html'; 20 | } 21 | 22 | var notesPopup = window.open( notesFilePath, 'reveal.js - Notes', 'width=1100,height=700' ); 23 | 24 | /** 25 | * Connect to the notes window through a postmessage handshake. 26 | * Using postmessage enables us to work in situations where the 27 | * origins differ, such as a presentation being opened from the 28 | * file system. 29 | */ 30 | function connect() { 31 | // Keep trying to connect until we get a 'connected' message back 32 | var connectInterval = setInterval( function() { 33 | notesPopup.postMessage( JSON.stringify( { 34 | namespace: 'reveal-notes', 35 | type: 'connect', 36 | url: window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.search, 37 | state: Reveal.getState() 38 | } ), '*' ); 39 | }, 500 ); 40 | 41 | window.addEventListener( 'message', function( event ) { 42 | var data = JSON.parse( event.data ); 43 | if( data && data.namespace === 'reveal-notes' && data.type === 'connected' ) { 44 | clearInterval( connectInterval ); 45 | onConnected(); 46 | } 47 | } ); 48 | } 49 | 50 | /** 51 | * Posts the current slide data to the notes window 52 | */ 53 | function post(event) { 54 | 55 | var slideElement = Reveal.getCurrentSlide(), 56 | notesElement = slideElement.querySelector( 'aside.notes' ); 57 | 58 | var messageData = { 59 | namespace: 'reveal-notes', 60 | type: 'state', 61 | notes: '', 62 | markdown: false, 63 | whitespace: 'normal', 64 | state: Reveal.getState() 65 | }; 66 | 67 | // Look for notes defined in a fragment, if it is a fragmentshown event 68 | if (event && event.hasOwnProperty('fragment')) { 69 | var innerNotes = event.fragment.querySelector( 'aside.notes' ); 70 | 71 | if ( innerNotes) { 72 | notesElement = innerNotes; 73 | } 74 | } 75 | 76 | // Look for notes defined in a slide attribute 77 | if( slideElement.hasAttribute( 'data-notes' ) ) { 78 | messageData.notes = slideElement.getAttribute( 'data-notes' ); 79 | messageData.whitespace = 'pre-wrap'; 80 | } 81 | 82 | // Look for notes defined in an aside element 83 | if( notesElement ) { 84 | messageData.notes = notesElement.innerHTML; 85 | messageData.markdown = typeof notesElement.getAttribute( 'data-markdown' ) === 'string'; 86 | } 87 | 88 | notesPopup.postMessage( JSON.stringify( messageData ), '*' ); 89 | 90 | } 91 | 92 | /** 93 | * Called once we have established a connection to the notes 94 | * window. 95 | */ 96 | function onConnected() { 97 | 98 | // Monitor events that trigger a change in state 99 | Reveal.addEventListener( 'slidechanged', post ); 100 | Reveal.addEventListener( 'fragmentshown', post ); 101 | Reveal.addEventListener( 'fragmenthidden', post ); 102 | Reveal.addEventListener( 'overviewhidden', post ); 103 | Reveal.addEventListener( 'overviewshown', post ); 104 | Reveal.addEventListener( 'paused', post ); 105 | Reveal.addEventListener( 'resumed', post ); 106 | 107 | // Post the initial state 108 | post(); 109 | 110 | } 111 | 112 | connect(); 113 | 114 | } 115 | 116 | if( !/receiver/i.test( window.location.search ) ) { 117 | 118 | // If the there's a 'notes' query set, open directly 119 | if( window.location.search.match( /(\?|\&)notes/gi ) !== null ) { 120 | openNotes(); 121 | } 122 | 123 | // Open the notes when the 's' key is hit 124 | document.addEventListener( 'keydown', function( event ) { 125 | // Disregard the event if the target is editable or a 126 | // modifier is present 127 | if ( document.querySelector( ':focus' ) !== null || event.shiftKey || event.altKey || event.ctrlKey || event.metaKey ) return; 128 | 129 | // Disregard the event if keyboard is disabled 130 | if ( Reveal.getConfig().keyboard === false ) return; 131 | 132 | if( event.keyCode === 83 ) { 133 | event.preventDefault(); 134 | openNotes(); 135 | } 136 | }, false ); 137 | 138 | // Show our keyboard shortcut in the reveal.js help overlay 139 | if( window.Reveal ) Reveal.registerKeyboardShortcut( 'S', 'Speaker notes view' ); 140 | 141 | } 142 | 143 | return { open: openNotes }; 144 | 145 | })(); 146 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Ansible Lightbulb Examples 2 | 3 | This content is a collection of complete Ansible solutions that demonstrate the most essential features and common use patterns. 4 | 5 | These examples are an excellent educational reference for communicating how Ansible works in a clear, focused and consistent manner using recommended best practices. 6 | 7 | It is a great source for canned demos or something you can walk-thru to illustrate automating with Ansible to a group. Some of the examples also serve as the solutions to the workshop assignments. 8 | 9 | ## Documentation of examples 10 | 11 | The documentation of the examples must follow the example structure - or a subset of it - shown below: 12 | 13 | ``` 14 | # cloud-aws 15 | 16 | A basic description explaining the reasoning behind the example as well as what best practices and techniques are shown by it. 17 | 18 | ## Requirements 19 | 20 | Any fundamental requirements like an AWS account or the need for Cisco IOS devices are mentioned here. 21 | 22 | ## Variables 23 | 24 | Identify all variables used in the playbook here. 25 | 26 | ### Required 27 | 28 | This optional paragraph highlights required variables that need to be provided. 29 | 30 | ### Optional 31 | 32 | This optional paragraph highlights optional variables that might be provided to further alter the execution of the example. 33 | 34 | ## Usage 35 | 36 | Necessary and notable commands to execute the example playbook are listed here. 37 | 38 | ### One More Thing 39 | 40 | Special tips and advanced tricks regarding the example can be put here. 41 | 42 | ``` 43 | 44 | A goog example of a sophisticated and complete `README.md` can be found in the [cloud-aws example](cloud-aws/README.md). 45 | 46 | ## Naming of examples 47 | 48 | Examples should be named in a short and clear way focussing on the use case they cover. 49 | -------------------------------------------------------------------------------- /examples/apache-basic-playbook/README.md: -------------------------------------------------------------------------------- 1 | # apache-basic-playbook 2 | 3 | This example represents a basic yet complete playbook approximating the typical tasks used to deploy and configure a single application service (Apache) on a host running a Red Hat family linux. 4 | 5 | This playbook assures the hosts in a group called "web" has the Apache web server (httpd) present and is started. The play also generates a basic configuration and custom home page using templates. If the configuration is changed, a handler task will execute to restart the apache httpd service. 6 | -------------------------------------------------------------------------------- /examples/apache-basic-playbook/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure apache is installed and started 3 | hosts: web 4 | become: yes 5 | vars: 6 | httpd_packages: 7 | - httpd 8 | - mod_wsgi 9 | apache_test_message: This is a test message 10 | apache_webserver_port: 80 11 | 12 | tasks: 13 | - name: Ensure httpd packages are present 14 | yum: 15 | name: "{{ item }}" 16 | state: present 17 | with_items: "{{ httpd_packages }}" 18 | notify: restart-apache-service 19 | 20 | - name: Ensure site-enabled directory is present 21 | file: 22 | name: /etc/httpd/conf/sites-enabled 23 | state: directory 24 | 25 | - name: Ensure latest httpd.conf is present 26 | template: 27 | src: templates/httpd.conf.j2 28 | dest: /etc/httpd/conf/httpd.conf 29 | notify: restart-apache-service 30 | 31 | - name: Ensure latest index.html is present 32 | template: 33 | src: templates/index.html.j2 34 | dest: /var/www/html/index.html 35 | 36 | - name: Ensure httpd is started and enabled 37 | service: 38 | name: httpd 39 | state: started 40 | enabled: yes 41 | 42 | handlers: 43 | - name: restart-apache-service 44 | service: 45 | name: httpd 46 | state: restarted 47 | -------------------------------------------------------------------------------- /examples/apache-basic-playbook/templates/index.html.j2: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ansible: Automation for Everyone 5 | 6 | 30 | 31 | 32 |
33 | 34 |

{{ apache_test_message }}

35 |
36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /examples/apache-role/README.md: -------------------------------------------------------------------------------- 1 | # apache-roles 2 | 3 | This example demonstrates how roles are structured and used within a playbook. In communicating these concepts, this example is simply a refactoring of the `apache-basic-playbook` example into a role. 4 | -------------------------------------------------------------------------------- /examples/apache-role/roles/apache-simple/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for apache 3 | apache_test_message: This is a test message 4 | apache_webserver_port: 80 5 | -------------------------------------------------------------------------------- /examples/apache-role/roles/apache-simple/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for apache 3 | - name: restart-apache-service 4 | service: 5 | name: httpd 6 | state: restarted 7 | -------------------------------------------------------------------------------- /examples/apache-role/roles/apache-simple/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # tasks file for apache 3 | - name: Ensure httpd packages are present 4 | yum: 5 | name: "{{ item }}" 6 | state: present 7 | with_items: "{{ httpd_packages }}" 8 | notify: restart-apache-service 9 | 10 | - name: Ensure latest httpd.conf file is present 11 | template: 12 | src: httpd.conf.j2 13 | dest: /etc/httpd/conf/httpd.conf 14 | notify: restart-apache-service 15 | 16 | - name: Ensure latest index.html file is present 17 | template: 18 | src: index.html.j2 19 | dest: /var/www/html/index.html 20 | 21 | - name: Ensure httpd service is started and enabled 22 | service: 23 | name: httpd 24 | state: started 25 | enabled: yes 26 | -------------------------------------------------------------------------------- /examples/apache-role/roles/apache-simple/templates/index.html.j2: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ansible: Automation for Everyone 5 | 6 | 30 | 31 | 32 |
33 | 34 |

{{ apache_test_message }}

35 |
36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /examples/apache-role/roles/apache-simple/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # vars file for apache 3 | httpd_packages: 4 | - httpd 5 | - mod_wsgi 6 | -------------------------------------------------------------------------------- /examples/apache-role/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure apache is installed and started via role 3 | hosts: web 4 | become: yes 5 | roles: 6 | - apache-simple 7 | -------------------------------------------------------------------------------- /examples/apache-simple-playbook/README.md: -------------------------------------------------------------------------------- 1 | # apache-simple-playbook 2 | 3 | This example is designed to be used as a quick introduction to playbook structure that can easily fit on one slide deck that demonstrates how Ansible works. 4 | 5 | This playbook assures the hosts in a group called "web" has the Apache web server (httpd) present and is started with a static custom home page. The hosts are presumed to be running a Red Hat family linux. 6 | 7 | The playbook is intended for demonstration and instructional purpose. In reality it's too simplistic to be really useful. See `examples/apache-basic-playbook` for a more complete example using Apache. 8 | -------------------------------------------------------------------------------- /examples/apache-simple-playbook/files/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ansible: Automation for Everyone 5 | 6 | 30 | 31 | 32 |
33 | 34 |
35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /examples/apache-simple-playbook/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure apache is installed and started 3 | hosts: web 4 | become: yes 5 | 6 | tasks: 7 | - name: Ensure httpd package is present 8 | yum: 9 | name: httpd 10 | state: present 11 | 12 | - name: Ensure latest index.html file is present 13 | copy: 14 | src: files/index.html 15 | dest: /var/www/html/ 16 | 17 | - name: Ensure httpd is started 18 | service: 19 | name: httpd 20 | state: started 21 | -------------------------------------------------------------------------------- /examples/cloud-aws/README.md: -------------------------------------------------------------------------------- 1 | # cloud-aws 2 | 3 | This intermediate-level Ansible playbook example demonstrates the common tasks for provisioning EC2 server instances into an Amazon Web Services VPC. Once provisioned this example will use an existing role (apache-role) to deploy and setup an application service on the instances in the stack. 4 | 5 | This example demonstrates a few other best practices and intermediate techniques: 6 | 7 | * **Compound Playbook.** This example shows the use of a playbook, `site.yml`, combining other playbooks, `provision.yml` and `setup.yml`, using play level 'include' statements. Splitting provisioning and configuration plays into separate files is a recommended best practice. By doing so, users have more flexibility to what the run without needing tags and wrapping blocks of tasks with conditionals. This separation can be used to promote reuse, but enabling the mixing and matching of various playbooks. 8 | * **Controlling Debug Message Display.** There is a debug task in `provison.yml` using the optional `verbosity` parameter. Avoiding the unnecessary display of debugging messages avoids confusion and is just good hygiene. In this implementation, the debug message won't be displayed unless the playbook is run in verbose mode level 1 or greater. 9 | 10 | ## Requirements 11 | 12 | To use this example you will need to have an AWS account setup and properly configured on your control machine. You will also need the boto, boto3 and botocore modules installed. See the [Ansible AWS Guide](http://docs.ansible.com/ansible/guide_aws.html) for more details. 13 | 14 | ## Variables 15 | 16 | Before running this playbook example, you should know about what variables it uses and how they effect the execution of the AWS provisioning process. 17 | 18 | ### Required 19 | 20 | The following variables must be properly set for this example to run properly. 21 | 22 | * `ec2_stack_name`: A unique name for your application stack. The stack name is used as a prefix for many other resources that will get created using this playbook. 23 | 24 | * `ec2_region`: A valid AWS region name such as "us-east-2" or "ap-southeast-1" or "eu-west-2." 25 | 26 | * `ec2_key_name`: An existing AWS keyname from your account to use when provisioning instances. 27 | 28 | ### Optional 29 | 30 | There are a few other variables present whose value you can override if needed. 31 | 32 | * `ec2_az`: The EC2 availability zone to use in the region. Default: a 33 | 34 | * `ec2_vpcidr`: The VPC CIDR value. Default: 10.251.0.0/16 35 | 36 | * `ec2_subnetcidr`: The VPC Subnet CIDR value. Default: 10.251.1.0/24 37 | 38 | * `ec2_exact_count`: The number of EC2 instances that should be present. Using the `ec2` module, this playbook will create and terminate instances as needed. Default: 1 39 | 40 | * `ec2_private_key_file`: The path to the private key associated with the `ec2_key_name` used to launch the instances if you need it. If undefined, it is omitted from dynamic inventory group "web". 41 | 42 | ## Usage 43 | 44 | To execute this example, use the `site.yml` playbook and pass in all the required variables: 45 | 46 | ``` 47 | ansible-playbook site.yml -e "ec2_stack_name=lightbulb ec2_region=us-east-2 ec2_key_name=engima" 48 | ``` 49 | 50 | Using verbose mode of any type will emit a debugging message that displays information about the provisioned instances in the stack. 51 | 52 | ``` 53 | ansible-playbook site.yml -e "ec2_stack_name=lightbulb ec2_region=us-east-2 ec2_key_name=engima" -v 54 | ``` 55 | 56 | Remember you can put your variables in a YAML formatted file and feed it into the play with the @ operator. 57 | 58 | ``` 59 | ansible-playbook site.yml -e @extra_vars.yml 60 | ``` 61 | 62 | ### One More Thing 63 | 64 | Since we are reusing the apache-simple roles from `examples/apache-role`, we can override the default value of `apache_test_message` to change the message that gets inserted onto the generated home page by the role. 65 | 66 | ``` 67 | ansible-playbook site.yml -e "ec2_stack_name=lightbulb ec2_region=us-east-2 ec2_key_name=engima apache_test_message=Hello_World" 68 | ``` 69 | -------------------------------------------------------------------------------- /examples/cloud-aws/ansible.cfg: -------------------------------------------------------------------------------- 1 | # these makes running this example out of the box easier 2 | [defaults] 3 | host_key_checking = False 4 | retry_files_enabled = False 5 | -------------------------------------------------------------------------------- /examples/cloud-aws/provision.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure servers are provisioned in vpc 3 | hosts: localhost 4 | gather_facts: false 5 | vars: 6 | # requires ec2_stack_name, ec2_region and ec2_key_name 7 | ec2_exact_count: 1 8 | ec2_vpcidr: 10.251.0.0/16 9 | ec2_subnetcidr: 10.251.1.0/24 10 | ec2_az: a 11 | 12 | tasks: 13 | - name: Ensure vpc is present 14 | ec2_vpc_net: 15 | state: present 16 | region: "{{ ec2_region }}" 17 | cidr_block: "{{ ec2_vpcidr }}" 18 | name: "{{ ec2_stack_name }}-vpc" 19 | tags: 20 | tool: ansible 21 | register: network 22 | 23 | - name: Ensure vpc subnet is present 24 | ec2_vpc_subnet: 25 | region: "{{ ec2_region }}" 26 | state: present 27 | cidr: "{{ ec2_subnetcidr }}" 28 | az: "{{ ec2_region }}{{ ec2_az }}" 29 | resource_tags: 30 | tool: ansible 31 | Name: "{{ ec2_stack_name }}-subnet-{{ ec2_az }}" 32 | vpc_id: "{{ network.vpc.id }}" 33 | register: vpc_subnet 34 | 35 | - name: Ensure vpc internet gateway is present 36 | ec2_vpc_igw: 37 | region: "{{ ec2_region }}" 38 | vpc_id: "{{ network.vpc.id }}" 39 | state: present 40 | register: igw 41 | 42 | - name: Ensure vpc public subnet route table is present 43 | ec2_vpc_route_table: 44 | region: "{{ ec2_region }}" 45 | vpc_id: "{{ network.vpc.id }}" 46 | tags: 47 | Name: "{{ ec2_stack_name }}-public" 48 | subnets: 49 | - "{{ vpc_subnet.subnet.id }}" 50 | routes: 51 | - dest: 0.0.0.0/0 52 | gateway_id: "{{ igw.gateway_id }}" 53 | 54 | - name: Ensure vpc security group is present 55 | ec2_group: 56 | name: "{{ ec2_stack_name }}-webservers" 57 | region: "{{ ec2_region }}" 58 | description: SSH and HTTP/HTTPS 59 | vpc_id: "{{ network.vpc.id }}" 60 | rules: 61 | - proto: tcp 62 | from_port: 22 63 | to_port: 22 64 | cidr_ip: 0.0.0.0/0 65 | - proto: tcp 66 | from_port: 80 67 | to_port: 80 68 | cidr_ip: 0.0.0.0/0 69 | - proto: tcp 70 | from_port: 443 71 | to_port: 443 72 | cidr_ip: 0.0.0.0/0 73 | 74 | - name: Search for the latest centos7 ami 75 | ec2_ami_find: 76 | owner: "410186602215" 77 | region: "{{ ec2_region }}" 78 | name: "CentOS Linux 7 x86_64 HVM EBS*" 79 | register: find_results 80 | 81 | - name: Get exact count of stack ec2 instances running 82 | ec2: 83 | key_name: "{{ ec2_key_name }}" 84 | group: "{{ ec2_stack_name }}-webservers" 85 | volumes: 86 | - device_name: /dev/sda1 87 | volume_type: gp2 88 | volume_size: 8 89 | delete_on_termination: true 90 | vpc_subnet_id: "{{ vpc_subnet.subnet.id }}" 91 | instance_type: t2.micro 92 | image: "{{ find_results.results[0].ami_id }}" 93 | wait: true 94 | region: "{{ ec2_region }}" 95 | exact_count: "{{ ec2_exact_count }}" 96 | count_tag: 97 | Count: "{{ ec2_stack_name }}" 98 | instance_tags: 99 | Name: "{{ ec2_stack_name }}" 100 | Count: "{{ ec2_stack_name }}" 101 | assign_public_ip: true 102 | register: ec2 103 | 104 | - name: Display stack instances info 105 | debug: 106 | var: ec2 107 | verbosity: 1 108 | 109 | - name: Ensure all instances are ready 110 | wait_for: 111 | port: 22 112 | host: "{{ item.public_ip }}" 113 | search_regex: OpenSSH 114 | with_items: "{{ ec2.tagged_instances }}" 115 | 116 | - name: Pause to let cloud init to complete 117 | pause: 118 | seconds: 90 119 | 120 | - name: Build group of instances 121 | add_host: 122 | name: "{{ item.public_dns_name }}" 123 | groups: web 124 | ansible_user: centos 125 | ansible_host: "{{ item.public_ip }}" 126 | ansible_ssh_private_key_file: "{{ ec2_private_key_file | default(omit) }}" 127 | with_items: "{{ ec2.tagged_instances }}" 128 | 129 | -------------------------------------------------------------------------------- /examples/cloud-aws/roles: -------------------------------------------------------------------------------- 1 | ../apache-role/roles -------------------------------------------------------------------------------- /examples/cloud-aws/setup.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure apache server is present and running with example home page 3 | hosts: web 4 | become: yes 5 | roles: 6 | - apache-simple 7 | -------------------------------------------------------------------------------- /examples/cloud-aws/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include: provision.yml 3 | - include: setup.yml 4 | -------------------------------------------------------------------------------- /examples/nginx-basic-playbook/README.md: -------------------------------------------------------------------------------- 1 | # nginx-basic-playbook 2 | 3 | This example represents a basic yet complete playbook approximating the typical tasks used to deploy and configure a single application service (Nginx) on a host running a Red Hat family linux. 4 | 5 | This playbook assures the hosts in a group called "web" has the Nginx web server along with uwsgi and other build dependencies are present and nginx is started. The play also generates a basic configuration and custom home page using templates. If the configuration is changed, a handler task will execute to restart the nginx service. 6 | 7 | This example assumes that the EPEL repo has already be enabled on each host. This was intentionally left out to keep this example focused. 8 | 9 | The playbook is also the solution to the primary assignment and one of the extra credit assignments in `workshop/basic_playbook`. 10 | -------------------------------------------------------------------------------- /examples/nginx-basic-playbook/site.yml: -------------------------------------------------------------------------------- 1 | # In keeping things simple, this example assumes the epel repo is enabled on each node 2 | --- 3 | - name: Ensure nginx is installed and started with wsgi 4 | hosts: web 5 | become: yes 6 | vars: 7 | nginx_packages: 8 | - nginx 9 | - python-pip 10 | - python-devel 11 | - gcc 12 | nginx_test_message: This is a test message 13 | nginx_webserver_port: 80 14 | 15 | tasks: 16 | - name: Ensure nginx packages are present 17 | yum: 18 | name: "{{ item }}" 19 | state: present 20 | with_items: "{{ nginx_packages }}" 21 | notify: restart-nginx-service 22 | 23 | - name: Ensure uwsgi package is present 24 | pip: 25 | name: uwsgi 26 | state: present 27 | notify: restart-nginx-service 28 | 29 | - name: Ensure latest default.conf is present 30 | template: 31 | src: templates/nginx.conf.j2 32 | dest: /etc/nginx/nginx.conf 33 | backup: yes 34 | notify: restart-nginx-service 35 | 36 | - name: Ensure latest index.html is present 37 | template: 38 | src: templates/index.html.j2 39 | dest: /usr/share/nginx/html/index.html 40 | 41 | - name: Ensure nginx service is started and enabled 42 | service: 43 | name: nginx 44 | state: started 45 | enabled: yes 46 | 47 | # smoke test that nginx came up and is serving home page 48 | - name: Ensure proper response from localhost can be received 49 | uri: 50 | url: "http://localhost:{{ nginx_webserver_port }}/" 51 | return_content: yes 52 | register: response 53 | until: 'nginx_test_message in response.content' 54 | retries: 10 55 | delay: 1 56 | 57 | handlers: 58 | - name: restart-nginx-service 59 | service: 60 | name: nginx 61 | state: restarted 62 | -------------------------------------------------------------------------------- /examples/nginx-basic-playbook/templates/index.html.j2: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ansible: Automation for Everyone 5 | 6 | 30 | 31 | 32 |
33 | 34 |

{{ nginx_test_message }}

35 |
36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /examples/nginx-basic-playbook/templates/nginx.conf.j2: -------------------------------------------------------------------------------- 1 | # Based on nginx version: nginx/1.10.1 2 | # For more information on configuration, see: 3 | # * Official English Documentation: http://nginx.org/en/docs/ 4 | # * Official Russian Documentation: http://nginx.org/ru/docs/ 5 | 6 | user nginx; 7 | worker_processes auto; 8 | error_log /var/log/nginx/error.log; 9 | pid /run/nginx.pid; 10 | 11 | # Load dynamic modules. See /usr/share/nginx/README.dynamic. 12 | include /usr/share/nginx/modules/*.conf; 13 | 14 | events { 15 | worker_connections 1024; 16 | } 17 | 18 | http { 19 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 20 | '$status $body_bytes_sent "$http_referer" ' 21 | '"$http_user_agent" "$http_x_forwarded_for"'; 22 | 23 | access_log /var/log/nginx/access.log main; 24 | 25 | sendfile on; 26 | tcp_nopush on; 27 | tcp_nodelay on; 28 | keepalive_timeout 115; 29 | types_hash_max_size 2048; 30 | 31 | include /etc/nginx/mime.types; 32 | default_type application/octet-stream; 33 | 34 | # Load modular configuration files from the /etc/nginx/conf.d directory. 35 | # See http://nginx.org/en/docs/ngx_core_module.html#include 36 | # for more information. 37 | include /etc/nginx/conf.d/*.conf; 38 | 39 | server { 40 | listen {{ nginx_webserver_port }} default_server; 41 | listen [::]:{{ nginx_webserver_port }} default_server; 42 | server_name _; 43 | root /usr/share/nginx/html; 44 | 45 | # Load configuration files for the default server block. 46 | include /etc/nginx/default.d/*.conf; 47 | 48 | location / { 49 | } 50 | 51 | error_page 404 /404.html; 52 | location = /40x.html { 53 | } 54 | 55 | error_page 500 502 503 504 /50x.html; 56 | location = /50x.html { 57 | } 58 | } 59 | 60 | # Settings for a TLS enabled server. 61 | # 62 | # server { 63 | # listen 443 ssl http2 default_server; 64 | # listen [::]:443 ssl http2 default_server; 65 | # server_name _; 66 | # root /usr/share/nginx/html; 67 | # 68 | # ssl_certificate "/etc/pki/nginx/server.crt"; 69 | # ssl_certificate_key "/etc/pki/nginx/private/server.key"; 70 | # ssl_session_cache shared:SSL:1m; 71 | # ssl_session_timeout 10m; 72 | # ssl_ciphers HIGH:!aNULL:!MD5; 73 | # ssl_prefer_server_ciphers on; 74 | # 75 | # # Load configuration files for the default server block. 76 | # include /etc/nginx/default.d/*.conf; 77 | # 78 | # location / { 79 | # } 80 | # 81 | # error_page 404 /404.html; 82 | # location = /40x.html { 83 | # } 84 | # 85 | # error_page 500 502 503 504 /50x.html; 86 | # location = /50x.html { 87 | # } 88 | # } 89 | 90 | } 91 | 92 | -------------------------------------------------------------------------------- /examples/nginx-remove-playbook/README.md: -------------------------------------------------------------------------------- 1 | # nginx-remove-playbook 2 | 3 | This example demonstrates how to you would typically shutdown and remove an application service (nginx) from the hosts in a group called "web". The hosts are presumed to be running a Red Hat family linux. 4 | 5 | This example was specifically developed as the solution to one of the extra credit assignments in `workshop/basic_playbook`. 6 | -------------------------------------------------------------------------------- /examples/nginx-remove-playbook/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure nginx with wsgi is removed 3 | hosts: web 4 | become: yes 5 | 6 | tasks: 7 | - name: Ensure nginx service is stopped 8 | service: 9 | name: nginx 10 | state: stopped 11 | ignore_errors: yes 12 | 13 | - name: Ensure nginx package is absent 14 | yum: 15 | name: nginx 16 | state: absent 17 | 18 | - name: Ensure uwsgi package is absent 19 | pip: 20 | name: uwsgi 21 | state: absent 22 | 23 | - name: Ensure files created by nginx-simple are absent 24 | file: 25 | name: "{{ item }}" 26 | state: absent 27 | with_items: 28 | - /etc/nginx/nginx.conf 29 | - /usr/share/nginx/html/index.html 30 | -------------------------------------------------------------------------------- /examples/nginx-role/README.md: -------------------------------------------------------------------------------- 1 | # nginx-roles 2 | 3 | This example demonstrates how roles are structured and used in a playbook. In communicating these concepts, this example is simply a refactoring of the `nginx-basic-playbook` and `nginx-remove-playbook` examples into a role. 4 | 5 | This example requires Ansible v2.2 or later. It uses the `include_role` module that introduced in that version. 6 | 7 | This also example assumes that the EPEL repo has already be enabled on each host. This was intentionally left out to keep this example focused. 8 | 9 | This example is also the solution to the primary assignment and extra credit assignments in `workshop/roles`. 10 | -------------------------------------------------------------------------------- /examples/nginx-role/remove.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Removes nginx and uwsgi 3 | hosts: web 4 | become: yes 5 | 6 | tasks: 7 | - name: Run remove tasks from nginx-simple role 8 | include_role: 9 | name: nginx-simple 10 | tasks_from: remove 11 | -------------------------------------------------------------------------------- /examples/nginx-role/roles/nginx-simple/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for nginx 3 | nginx_test_message: This is a test message 4 | nginx_webserver_port: 80 5 | -------------------------------------------------------------------------------- /examples/nginx-role/roles/nginx-simple/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for nginx 3 | - name: restart-nginx-service 4 | service: 5 | name: nginx 6 | state: restarted 7 | -------------------------------------------------------------------------------- /examples/nginx-role/roles/nginx-simple/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # tasks file for nginx 3 | - name: Ensure nginx packages are present 4 | yum: 5 | name: "{{ item }}" 6 | state: present 7 | with_items: "{{ nginx_packages }}" 8 | notify: restart-nginx-service 9 | 10 | - name: Ensure uwsgi package is present 11 | pip: 12 | name: uwsgi 13 | state: present 14 | notify: restart-nginx-service 15 | 16 | - name: Ensure latest default.conf is present 17 | template: 18 | src: templates/nginx.conf.j2 19 | dest: /etc/nginx/nginx.conf 20 | backup: yes 21 | notify: restart-nginx-service 22 | 23 | - name: Ensure latest index.html is present 24 | template: 25 | src: templates/index.html.j2 26 | dest: /usr/share/nginx/html/index.html 27 | 28 | - name: Ensure nginx service is started and enabled 29 | service: 30 | name: nginx 31 | state: started 32 | enabled: yes 33 | 34 | # smoke test that nginx came up and is serving home page 35 | - name: Ensure proper response from localhost is received 36 | uri: 37 | url: http://localhost/ 38 | return_content: yes 39 | register: response 40 | until: 'nginx_test_message in response.content' 41 | retries: 10 42 | delay: 1 43 | -------------------------------------------------------------------------------- /examples/nginx-role/roles/nginx-simple/tasks/remove.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # tasks file the removes nginx and uwsgi 3 | # derived from examples/nginx-remove-playbook 4 | - name: Ensure nginx service is stopped 5 | service: 6 | name: nginx 7 | state: stopped 8 | ignore_errors: yes 9 | 10 | - name: Ensure nginx package is removed 11 | yum: 12 | name: nginx 13 | state: absent 14 | 15 | - name: Ensure uwsgi is removed 16 | pip: 17 | name: uwsgi 18 | state: absent 19 | 20 | - name: Clean up files created by nginx-simple 21 | file: 22 | name: "{{ item }}" 23 | state: absent 24 | with_items: 25 | - /etc/nginx/nginx.conf 26 | - /usr/share/nginx/html/index.html 27 | -------------------------------------------------------------------------------- /examples/nginx-role/roles/nginx-simple/templates/index.html.j2: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ansible: Automation for Everyone 5 | 6 | 30 | 31 | 32 |
33 | 34 |

{{ nginx_test_message }}

35 |
36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /examples/nginx-role/roles/nginx-simple/templates/nginx.conf.j2: -------------------------------------------------------------------------------- 1 | # Based on nginx version: nginx/1.10.1 2 | # For more information on configuration, see: 3 | # * Official English Documentation: http://nginx.org/en/docs/ 4 | # * Official Russian Documentation: http://nginx.org/ru/docs/ 5 | 6 | user nginx; 7 | worker_processes auto; 8 | error_log /var/log/nginx/error.log; 9 | pid /run/nginx.pid; 10 | 11 | # Load dynamic modules. See /usr/share/nginx/README.dynamic. 12 | include /usr/share/nginx/modules/*.conf; 13 | 14 | events { 15 | worker_connections 1024; 16 | } 17 | 18 | http { 19 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 20 | '$status $body_bytes_sent "$http_referer" ' 21 | '"$http_user_agent" "$http_x_forwarded_for"'; 22 | 23 | access_log /var/log/nginx/access.log main; 24 | 25 | sendfile on; 26 | tcp_nopush on; 27 | tcp_nodelay on; 28 | keepalive_timeout 115; 29 | types_hash_max_size 2048; 30 | 31 | include /etc/nginx/mime.types; 32 | default_type application/octet-stream; 33 | 34 | # Load modular configuration files from the /etc/nginx/conf.d directory. 35 | # See http://nginx.org/en/docs/ngx_core_module.html#include 36 | # for more information. 37 | include /etc/nginx/conf.d/*.conf; 38 | 39 | server { 40 | listen {{ nginx_webserver_port }} default_server; 41 | listen [::]:{{ nginx_webserver_port }} default_server; 42 | server_name _; 43 | root /usr/share/nginx/html; 44 | 45 | # Load configuration files for the default server block. 46 | include /etc/nginx/default.d/*.conf; 47 | 48 | location / { 49 | } 50 | 51 | error_page 404 /404.html; 52 | location = /40x.html { 53 | } 54 | 55 | error_page 500 502 503 504 /50x.html; 56 | location = /50x.html { 57 | } 58 | } 59 | 60 | # Settings for a TLS enabled server. 61 | # 62 | # server { 63 | # listen 443 ssl http2 default_server; 64 | # listen [::]:443 ssl http2 default_server; 65 | # server_name _; 66 | # root /usr/share/nginx/html; 67 | # 68 | # ssl_certificate "/etc/pki/nginx/server.crt"; 69 | # ssl_certificate_key "/etc/pki/nginx/private/server.key"; 70 | # ssl_session_cache shared:SSL:1m; 71 | # ssl_session_timeout 10m; 72 | # ssl_ciphers HIGH:!aNULL:!MD5; 73 | # ssl_prefer_server_ciphers on; 74 | # 75 | # # Load configuration files for the default server block. 76 | # include /etc/nginx/default.d/*.conf; 77 | # 78 | # location / { 79 | # } 80 | # 81 | # error_page 404 /404.html; 82 | # location = /40x.html { 83 | # } 84 | # 85 | # error_page 500 502 503 504 /50x.html; 86 | # location = /50x.html { 87 | # } 88 | # } 89 | 90 | } 91 | 92 | -------------------------------------------------------------------------------- /examples/nginx-role/roles/nginx-simple/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # vars file for nginx 3 | nginx_packages: 4 | - nginx 5 | - python-pip 6 | - python-devel 7 | - gcc 8 | -------------------------------------------------------------------------------- /examples/nginx-role/site.yml: -------------------------------------------------------------------------------- 1 | # In keeping things simple, this example assumes the epel repo is enabled on each node 2 | --- 3 | - name: Ensure nginx is installed and started via role 4 | hosts: web 5 | become: yes 6 | roles: 7 | - nginx-simple 8 | -------------------------------------------------------------------------------- /examples/nginx-simple-playbook/README.md: -------------------------------------------------------------------------------- 1 | # nginx-simple-playbook 2 | 3 | This example is designed to be used as a quick introduction to playbook structure that can easily fit on one slide deck that demonstrates how Ansible works. 4 | 5 | This playbook assures the hosts in a group called "web" has the Nginx web server present and is started with a static custom home page. The hosts are presumed to be running a Red Hat family linux. 6 | 7 | This example assumes that the EPEL repo has already be enabled on each host. This was intentionally left out to keep this example simple and focused. 8 | 9 | The playbook is intended for demonstration and instructional purpose. In reality it's too simplistic to be really useful. See `examples/nginx-basic-playbook` for a more complete example using nginx. 10 | -------------------------------------------------------------------------------- /examples/nginx-simple-playbook/files/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ansible: Automation for Everyone 5 | 6 | 30 | 31 | 32 |
33 | 34 |
35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /examples/nginx-simple-playbook/site.yml: -------------------------------------------------------------------------------- 1 | # In keeping things simple, this example assumes the epel repo is enabled on each node 2 | --- 3 | - name: Ensure nginx is installed and started 4 | hosts: web 5 | become: yes 6 | 7 | tasks: 8 | - name: Ensure nginx package is present 9 | yum: 10 | name: nginx 11 | state: present 12 | 13 | - name: Ensure latest index.html is present 14 | copy: 15 | src: files/index.html 16 | dest: /usr/share/nginx/html 17 | 18 | - name: Ensure nginx service is started 19 | service: 20 | name: nginx 21 | state: started 22 | -------------------------------------------------------------------------------- /facilitator/images/LBCreatingCred.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/facilitator/images/LBCreatingCred.png -------------------------------------------------------------------------------- /facilitator/images/LBCredCreated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/facilitator/images/LBCredCreated.png -------------------------------------------------------------------------------- /facilitator/images/add_perms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/facilitator/images/add_perms.png -------------------------------------------------------------------------------- /facilitator/images/blank_survey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/facilitator/images/blank_survey.png -------------------------------------------------------------------------------- /facilitator/images/create_user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/facilitator/images/create_user.png -------------------------------------------------------------------------------- /facilitator/images/creating_host.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/facilitator/images/creating_host.png -------------------------------------------------------------------------------- /facilitator/images/creating_inventory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/facilitator/images/creating_inventory.png -------------------------------------------------------------------------------- /facilitator/images/extra_variables.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/facilitator/images/extra_variables.png -------------------------------------------------------------------------------- /facilitator/images/filled_out_survey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/facilitator/images/filled_out_survey.png -------------------------------------------------------------------------------- /facilitator/images/finalized_inv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/facilitator/images/finalized_inv.png -------------------------------------------------------------------------------- /facilitator/images/job_template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/facilitator/images/job_template.png -------------------------------------------------------------------------------- /facilitator/images/project_creation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/facilitator/images/project_creation.png -------------------------------------------------------------------------------- /facilitator/images/running_job.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/facilitator/images/running_job.png -------------------------------------------------------------------------------- /facilitator/images/succes_job.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/facilitator/images/succes_job.png -------------------------------------------------------------------------------- /facilitator/solutions/adhoc_commands.md: -------------------------------------------------------------------------------- 1 | # Workshop: Ad-Hoc Commands 2 | 3 | This brief exercise demonstrates Ansible in-action at it's most basic and simple level. Thru ad-hoc commands, students are exposed to Ansible modules and usage and will apply to their understanding of tasks and playbooks. This exercise also begins to expose students to the concepts of Ansible facts and inventory. 4 | 5 | This workshop is also a good way to verify their lab environments are properly configured before going forward. 6 | 7 | ## Solution 8 | 9 | The following commands are the solution for the workshop and extra credit assignments. 10 | 11 | ```bash 12 | ansible all -m ping 13 | 14 | ansible all -m setup 15 | 16 | ansible web -b -m yum -a "name=epel-release state=present" 17 | ansible web -b -m yum -a "name=https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm state=present" 18 | 19 | --- 20 | 21 | ansible all -m setup -a "gather_subset=virtual" 22 | 23 | ansible all -m setup -a "filter=ansible_fqdn*" 24 | 25 | ansible all -m command -a "uptime" 26 | 27 | ansible all -m ping --limit '!control' 28 | ``` 29 | 30 | ### NOTE 31 | 32 | You will need to make sure each student successfully installed the EPEL repo here. Later workshop assignments ask students to install Nginx. Without EPEL enabled on each web host `yum` will not be able to locate the package. 33 | -------------------------------------------------------------------------------- /facilitator/solutions/ansible_install.md: -------------------------------------------------------------------------------- 1 | # Workshop: Installing Ansible 2 | 3 | This brief exercise demonstrates how easy it can be to install and configure Ansible and begin automating. 4 | 5 | NOTE: If and how you conduct this workshop depends on how you configured the provisioner to run. To save time, you can have lab control machines setup with Ansible. If so, you can skip with workshop. 6 | 7 | We use pip because it's OS independent and always has the absolute latest stable release of Ansible. Other package repos such as EPEL can sometime lag behind for days or even weeks. For this reason, Ansible by Red Hat recommends using PIP. 8 | 9 | ## Solution 10 | 11 | Each student will need to SSH into their "control" machine using the host IP, user and password provided to them in their lab environment inventory file. 12 | 13 | From that control machine: 14 | 15 | ```bash 16 | sudo yum install -y ansible 17 | 18 | ansible --version 19 | 20 | ansible --help 21 | 22 | mkdir -p ~/.ansible/retry-files 23 | vi ~/.ansible.cfg 24 | # add forks and retry_files_save_path 25 | 26 | ``` 27 | 28 | ## NOTE 29 | 30 | Depending how the lab provisioner was run, students may already have Ansible on their control machines. You can still have them run Ansible with `--version` and `--help` options to check they can ssh into their control box and prove Ansible is indeed present. 31 | 32 | Whatever the case, you should make sure each student has the core Ansible software before proceeding. 33 | 34 | -------------------------------------------------------------------------------- /facilitator/solutions/basic_playbook.md: -------------------------------------------------------------------------------- 1 | # Workshop: Basic Playbook 2 | 3 | Here students are tasked with developing their first complete playbook. The assignment approximates the tasks they will typical need to take in order to deploy and configure a single application service using Nginx. 4 | 5 | The "simple" Lightbulb examples, students may or may not have done depending on agenda, provide a quick introduction to playbook structure to give them a feel for how Ansible works, but in practice are too simplistic to be useful. 6 | 7 | ## Tips 8 | 9 | Don't rush this workshop. Give students ample time to do this workshop themselves to completion. This workshop covers the essential concepts and features of effectively automation with Ansible and builds up their core skills for further exploration. 10 | 11 | ## Solution 12 | 13 | The solution to this workshop is `nginx-basic-playbook` under `examples/`. 14 | 15 | The `nginx-basic-playbook` example also includes the first extra credit assignment via the last task using the `uri` module. We intentionally only check that the web server is responding with the home page we generated by searching for the value of `nginx_test_message`. We are not checking if the server is accessible to outside world in keeping things basic. 16 | 17 | The solution to the second extra credit assignment is `nginx-remove-playbook` under `examples/`. 18 | -------------------------------------------------------------------------------- /facilitator/solutions/roles.md: -------------------------------------------------------------------------------- 1 | # Workshop: Roles 2 | 3 | Here students are tasked with refactoring their previous work from the Basic Playbook workshop into a role and modifying their playbook accordingly. We intentionally avoid introducing any new tasks or functionality otherwise. The objective here is to focus students specifically on how roles are structured and develop. 4 | 5 | You should emphasize the value of roles in better organizing playbooks as they grow in sophistication and making Ansible automation more portable and reusable than a basic playbook. 6 | 7 | ## Defaults vs. Vars 8 | 9 | A common question that is asked "when do I put a variable in defaults instead of a vars?" It depends on the usage of a variable in the context of a role. It all comes down to variable precedence. 10 | 11 | If a variable holds a data that someone using the role may want to override anyway numbers of ways, then it's best stored under `defaults/`. If a variable holds data that is internal to the function of the role and rarely (or in practice should never) be modified, then it's best stored under `vars/` where its much hard to be overridden by other variables sources. 12 | 13 | Applying these guidelines to this assignment, `nginx_packages` would go in `vars/` while `nginx_test_message` and `nginx_webserver_port` would go in `defaults/`. 14 | 15 | ## NOTE 16 | 17 | The extra credit assignment should use the `include_role` module that was introduced in version 2.2. Students working with older versions of Ansible will have trouble completing the assignment. 18 | 19 | ## Solution 20 | 21 | The solution to this workshop is `nginx-role` under `examples/`. This example also includes the solution to the extra credit assignment. See `remove.yml` and `roles/nginx-basic/tasks/remove.yml`. 22 | -------------------------------------------------------------------------------- /facilitator/solutions/simple_playbook.md: -------------------------------------------------------------------------------- 1 | # Workshop: Simple Playbook 2 | 3 | This assignment provides a quick introduction to playbook structure to give them a feel for how Ansible works, but in practice is too simplistic to be useful. 4 | 5 | ## Tips 6 | 7 | This workshop is a subset of the basic_playbook workshop students will do next. Depending on the technical aptitude of students and time available you can opt to skip this workshop assignment. Everything here and a lot more will in the next workshop assignment. 8 | 9 | ## Solution 10 | 11 | The solution to this workshop is `nginx-simple-playbook` under `examples/`. 12 | -------------------------------------------------------------------------------- /facilitator/solutions/tower_install.md: -------------------------------------------------------------------------------- 1 | # Workshop: Installing Tower 2 | 3 | Here students are tasked with installing and activating a new single integrated instance of Ansible Tower. The assignment will show students how they can run an instance of Tower themselves for testing, demos and their own proof-of-concepts. 4 | 5 | ## Tips 6 | 7 | If you are working in an environment that does not have access repos such as EPEL, you can opt to use the [Ansible Tower bundle installer](http://releases.ansible.com/ansible-tower/setup-bundle/ansible-tower-setup-bundle-latest.el7.tar.gz) instead. This bundle includes all of the RPMs from these repositories. It does not include **all** of the RPMs required. 8 | 9 | Once downloaded, configured and the `setup.sh` is started, is will take a few minutes to install all of the Ansible Tower dependencies. Students can take a short break while that runs. 10 | 11 | ## Solution 12 | 13 | 1. Retrieve the latest version of Tower from the Ansible Tower releases archive. 14 | 1. Unarchive the retrieved Ansible Tower archive. 15 | * i.e. `tar -vxzf towerlatest` 16 | 1. Change directories to the one created by the expanded Tower software archive. 17 | 1. Edit the `inventory` file with passwords for admin, message queue and the postgres database will use while setting up. These are represented by these inventory variables: 18 | * `admin_password` 19 | * `rabbitmq_password` 20 | * `pg_password` 21 | 1. Run the setup.sh script with sudo. 22 | 1. Verify Ansible has been successfully installed and started, load the Ansible Tower UI in a web browser using the control machine IP address. 23 | 1. Sign in as the admin user with the password created in the installation process. You will be prompted for a license. 24 | 1. Request a trial license if one hasn't been provided already. (Either trial license type will suffice.) 25 | 1. Import/upload the license file. 26 | 1. Extra Credit: Open the ping API end point in a web browser -- the URL will be something like like [https://tower.host.ip/v1/api/ping](https://tower.host.ip/v1/api/ping) 27 | 28 | These are the approximate BASH commands to do this: 29 | 30 | ```bash 31 | $ wget https://bit.ly/towerlatest 32 | $ tar -xzvf towerlatest 33 | $ cd ansible-tower-setup-x.x.x 34 | $ vi inventory 35 | # (make edits to inventory variables like in step 4) 36 | $ sudo ./setup.sh 37 | ``` 38 | 39 | NOTE: If you don't have access to EPEL you can use [https://bit.ly/towerbundlelatest](https://bit.ly/towerbundlelatest). 40 | 41 | Once completed switch to your browser to sign into the Ansible Tower UI as admin and setup the instance with a license file. 42 | -------------------------------------------------------------------------------- /guides/README.md: -------------------------------------------------------------------------------- 1 | # Ansible Lightbulb Guides 2 | 3 | These guides are part of lightbulb, a multi-purpose toolkit for effectively demonstrating Ansible's capabilities or providing informal trainings in various forms -- instructor-led, hands-on or self-paced. 4 | 5 | ## Available Guides 6 | 7 | Currently there are two guides available: 8 | 9 | * [Ansible Engine](ansible_engine/README.md) 10 | * [Ansible Tower](ansible_tower/README.md) 11 | 12 | ## Additional information 13 | 14 | Additional information about Ansible, how to get started and where to proceed after these guides, have a look at the following sources: 15 | 16 | * [Ansible Getting Started](http://docs.ansible.com/ansible/latest/intro_getting_started.html) 17 | -------------------------------------------------------------------------------- /guides/ansible_engine/1-adhoc/README.md: -------------------------------------------------------------------------------- 1 | # Exercise - Running Ad-hoc commands 2 | 3 | For our first exercise, we are going to run some ad-hoc commands to help you get a feel for how Ansible works. Ansible Ad-Hoc commands enable you to perform tasks on remote nodes without having to write a playbook. They are very useful when you simply need to do one or two things quickly and often, to many remote nodes. 4 | 5 | ## Section 1: Definition of the inventory 6 | 7 | Inventories are crucial to Ansible as they define remote machines on which you wish to run commands or your playbook(s). In this lab the inventory is provided by your instructor. The inventory is an ini formatted file listing your hosts, sorted in groups, additionally providing some variables. It looks like: 8 | 9 | ```bash 10 | [all:vars] 11 | ansible_user=rwolters 12 | ansible_ssh_pass=averysecretpassword 13 | ansible_port=22 14 | 15 | [web] 16 | node-ansible_host=.22.33.44 17 | node-2 ansible_host=22.33.44.55 18 | node-3 ansible_host=33.44.55.66 19 | 20 | [control] 21 | ansible ansible_host=44.55.66.77 22 | ``` 23 | 24 | Your individual inventory is already present in your lab environment underneath `lightbulb/lessons/lab_inventory/$USERNAME-instances.txt`, where `$USERNAME` is replaced by your individual username. 25 | 26 | ## Section 2: Basic Ansible configuration 27 | 28 | Ansible needs to know which inventory file should be used. By default it checks for the inventory file at `/etc/ansible/hosts`. You need to point Ansible to your own, lab specific inventory file. One way to do this is to specify the path to the inventory file with the `-i` option to the ansible command: 29 | 30 | ```bash 31 | ansible -i hosts ... 32 | ``` 33 | 34 | To avoid the need to specify the inventory file each time, the inventory can also be configured in the configuration file `.ansible.cfg`. If this file is present, Ansible will read configuration parameters like the inventory location and others from this file. 35 | 36 | On your control node, such a file is already present right in the home directory of your user. It is already customized to point to your inventory file, so there is nothing further you have to do. 37 | 38 | ## Section 3: Ping a host 39 | 40 | Let's start with something basic and use the `ping` module to test that Ansible has been installed and configured correctly and all hosts in your inventory are responsive. 41 | 42 | ```bash 43 | ansible all -m ping 44 | ``` 45 | 46 | ## Section 4: Run a typical command 47 | 48 | Now let's see how we can run a typical Linux shell command and format the output using the `command` module. 49 | 50 | ```bash 51 | ansible web -m command -a "uptime" -o 52 | ``` 53 | 54 | ## Section 5: Gather facts about target node 55 | 56 | We can use an ad-hoc command with the `setup` module to display the many facts Ansible can discover about each node in its inventory. 57 | 58 | ```bash 59 | ansible all -m setup 60 | ``` 61 | 62 | ## Section 6: Install package 63 | 64 | Now, let's install Apache using the `yum` module. 65 | 66 | ```bash 67 | ansible web -m yum -a "name=httpd state=present" -b 68 | ``` 69 | 70 | Usually, only root users are allowed to install packages. So this is a case where we need privilege escalation and a sudo that has to be setup properly. We need to instruct ansible to use sudo to run the command as root by using the parameter `-b` (think "become"). 71 | 72 | ## Section 7: Start service 73 | 74 | OK, Apache is installed now so let's start it up using the `service` module. 75 | 76 | ```bash 77 | ansible web -m service -a "name=httpd state=started" -b 78 | ``` 79 | 80 | ## Section 8: Stop service 81 | 82 | Finally, let's clean up after ourselves. First, stop the httpd service. 83 | 84 | ```bash 85 | ansible web -m service -a "name=httpd state=stopped" -b 86 | ``` 87 | 88 | ## Section 9: Remove package 89 | 90 | Next, remove the Apache package. 91 | 92 | ```bash 93 | ansible web -m yum -a "name=httpd state=absent" -b 94 | ``` 95 | 96 | --- 97 | **NOTE:** Additional `ansible` options 98 | 99 | The way `ansible` works can be influenced by various options which can be listed via `ansible --help`: 100 | 101 | ```bash 102 | ansible --help 103 | Usage: ansible [options] 104 | 105 | Define and run a single task 'playbook' against a set of hosts 106 | 107 | Options: 108 | -a MODULE_ARGS, --args=MODULE_ARGS 109 | module arguments 110 | --ask-vault-pass ask for vault password 111 | -B SECONDS, --background=SECONDS 112 | run asynchronously, failing after X seconds 113 | (default=N/A) 114 | -C, --check don't make any changes; instead, try to predict some 115 | of the changes that may occur 116 | -D, --diff when changing (small) files and templates, show the 117 | differences in those files; works great with --check 118 | [...] 119 | ``` 120 | 121 | --- 122 | 123 | [Click Here to return to the Ansible Lightbulb - Ansible Engine Guide](../README.md) 124 | -------------------------------------------------------------------------------- /guides/ansible_engine/2-playbook/README.md: -------------------------------------------------------------------------------- 1 | # Exercise 2 - Writing Your First playbook 2 | 3 | Now that you've gotten a sense of how ansible works, we are going to write our first ansible *playbook*. Playbooks are Ansible’s configuration, deployment, and orchestration language. They are written in YAML and are used to invoke Ansible modules to perform tasks that are executed sequentially i.e top to bottom. They can describe a policy you want your remote systems to enforce, or a set of steps in a general IT workflow. Playbooks are like an instruction manual and describe the state of environment. 4 | 5 | A playbook can have multiple plays and a play can have one or multiple tasks. The goal of a *play* is to map a group of hosts. The goal of a *task* is to implement modules against those hosts. 6 | 7 | For our first playbook, we are only going to write one play and two tasks. 8 | 9 | ## Section 1: Creating a Directory Structure and Files for your Playbook 10 | 11 | There is a [best practices](http://docs.ansible.com/ansible/playbooks_best_practices.html) on the preferred directory structures for playbooks. We strongly encourage you to read and understand these practices as you develop your Ansible skills. 12 | 13 | Instead, we are going to create a very simple directory structure for our playbook, and add just a couple of files to it. 14 | 15 | ### Step 1: Create a directory called `apache_basic` in your home directory and change directories into it 16 | 17 | ```bash 18 | mkdir ~/apache-simple-playbook 19 | cd ~/apache-simple-playbook 20 | ``` 21 | 22 | ### Step 2: Use `vi` or `vim` to open a file called `site.yml` 23 | 24 | ## Section 2: Defining Your Play 25 | 26 | Now that you are editing `site.yml`, let's begin by defining the play and then understanding what each line accomplishes 27 | 28 | ```yml 29 | --- 30 | - name: Ensure apache is installed and started 31 | hosts: web 32 | become: yes 33 | ``` 34 | 35 | * `---` Defines the beginning of YAML 36 | * `name: install and start apache` This describes our play 37 | * `hosts: web` Defines the host group in your inventory on which this play will run against 38 | * `become: yes` Enables user privilege escalation. The default is sudo, but su, pbrun, and [several others](http://docs.ansible.com/ansible/become.html) are also supported. 39 | 40 | ## Section 3: Adding Tasks to Your Play 41 | 42 | Now that we've defined your play, let's add some tasks to get some things done. Align (vertically) the *t* in `task` with the *b* `become`. Yes, it does actually matter. In fact, you should make sure all of your playbook statements are aligned in the way shown here. If you want to see the entire playbook for reference, skip to the bottom of this exercise. 43 | 44 | ```yml 45 | tasks: 46 | - name: Ensure httpd package is present 47 | yum: 48 | name: httpd 49 | state: present 50 | 51 | - name: Ensure latest index.html file is present 52 | copy: 53 | src: files/index.html 54 | dest: /var/www/html/ 55 | 56 | - name: Ensure httpd is started 57 | service: 58 | name: httpd 59 | state: started 60 | ``` 61 | 62 | * `tasks:` This denotes that one or more tasks are about to be defined 63 | * `- name:` Each task requires a name which will print to standard output when you run your playbook. It's considered best practice to give all your plays and tasks concise and human-meaningful descriptions. 64 | 65 | ```yml 66 | - name: Ensure httpd package is present 67 | yum: 68 | name: httpd 69 | state: present 70 | ``` 71 | 72 | * These four lines are calling the Ansible module *yum* to install httpd. [Click here](http://docs.ansible.com/ansible/yum_module.html) to see all options for the yum module. 73 | 74 | ```yml 75 | - name: Ensure latest index.html file is present 76 | copy: 77 | src: files/index.html 78 | dest: /var/www/html/ 79 | ``` 80 | 81 | * These four lines ensure that the `index.html` file is copied over to the target node. [Click here](http://docs.ansible.com/ansible/copy_module.html) to see all options for the copy module. 82 | 83 | ```yml 84 | - name: Ensure httpd is started 85 | service: 86 | name: httpd 87 | state: started 88 | ``` 89 | 90 | * The next few lines are using the ansible module `service` to start the httpd service right now. The service module is the preferred way of controlling services on remote hosts. [Click here](http://docs.ansible.com/ansible/service_module.html) to learn more about the `service` module. 91 | 92 | ## Section 4: Saving your Playbook 93 | 94 | Now that you've completed writing your playbook, it would be a shame not to keep it. 95 | 96 | Use the `write/quit` method in `vi` or `vim` to save your playbook, i.e. `Esc :wq!` 97 | 98 | Also, you have to create the above mentioned `index.html` file. For this, first create the proper directory: 99 | 100 | ```bash 101 | mkdir ~/apache-simple-playbook/files 102 | cd ~/apache-simple-playbook/files 103 | ``` 104 | 105 | Next, create the file and add content: Use `vi` or `vim` to open a file called `index.html` and add the following content: 106 | 107 | ```html 108 | 109 | 110 | 111 | Ansible: Automation for Everyone 112 | 113 | 137 | 138 | 139 |
140 | 141 |
142 |
Red Hat Ansible
143 | 144 | 145 | ``` 146 | 147 | Use the `write/quit` method in `vi` or `vim` to save your playbook, i.e. `Esc :wq!` 148 | 149 | And that should do it. You should now have a fully written playbook called `site.yml`. You are ready to automate! 150 | 151 | --- 152 | **NOTE** 153 | Ansible playbooks are essential YAML and YAML is a bit particular about formatting especially regards to whitespace. If you are unfamiliar with this, we recommend reading up on [YAML Syntax](http://docs.ansible.com/ansible/YAMLSyntax.html) in the Ansible docs. 154 | 155 | In the meantime, your completed playbook should look like this example below. (Take note of the spacing and alignment.) 156 | 157 | --- 158 | 159 | ```yml 160 | --- 161 | - name: Ensure apache is installed and started 162 | hosts: web 163 | become: yes 164 | 165 | tasks: 166 | - name: Ensure httpd package is present 167 | yum: 168 | name: httpd 169 | state: present 170 | 171 | - name: Ensure latest index.html file is present 172 | copy: 173 | src: files/index.html 174 | dest: /var/www/html/ 175 | 176 | - name: Ensure httpd is started 177 | service: 178 | name: httpd 179 | state: started 180 | ``` 181 | 182 | --- 183 | 184 | [Click Here to return to the Ansible Lightbulb - Ansible Engine Guide](../README.md) 185 | -------------------------------------------------------------------------------- /guides/ansible_engine/3-variables/stdout_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_engine/3-variables/stdout_2.png -------------------------------------------------------------------------------- /guides/ansible_engine/4-role/README.md: -------------------------------------------------------------------------------- 1 | # Exercise 1.4 - Roles: Making your playbooks reusable 2 | 3 | While it is possible to write a Playbook in one very large file, eventually you’ll want to reuse files and start to organize things. At a basic level, including task files allows you to break up bits of configuration policy into smaller files. Task includes pull in tasks from other files. Since handlers are tasks too, you can also include handler files. 4 | 5 | When you start to think about it – tasks, handlers, variables, and so on – begin to form larger concepts. You start to think about modeling what something is, 6 | 7 | * It’s no longer "apply THIS to these hosts" 8 | * You say "these hosts are webservers". 9 | 10 | Roles build on the idea of include files and provide Ansible with a way to load tasks, handlers, and variables from external files. The files that define a role have specific names and are organized in a rigid directory structure. 11 | 12 | Use of Ansible roles has the following benefits: 13 | 14 | * Roles group content, allowing easy sharing of code with others 15 | * Roles can be written that define the essential elements of a system type: web server, database server... 16 | * Roles make larger projects more manageable 17 | * Roles can be developed in parallel by different administrators 18 | 19 | For this exercise, you are going to take the playbook you just wrote and refactor it into a role. In addition, you'll learn to use `ansible-galaxy` to jumpstart development of a role. 20 | 21 | Let's begin with seeing how the new playbook structure `apache-role`, which we are going to create in this exercise, will break down into a role. 22 | 23 | ```bash 24 | apache-role/ 25 | ├── roles 26 | │   └── apache-simple 27 | │   ├── defaults 28 | │   │   └── main.yml 29 | │   ├── files 30 | │   ├── handlers 31 | │   │   └── main.yml 32 | │   ├── meta 33 | │   │   └── main.yml 34 | │   ├── README.md 35 | │   ├── tasks 36 | │   │   └── main.yml 37 | │   ├── templates 38 | │   ├── tests 39 | │   │   ├── inventory 40 | │   │   └── test.yml 41 | │   └── vars 42 | │   └── main.yml 43 | ├── inventory.ini 44 | └── site.yml 45 | ``` 46 | 47 | Fortunately, you don't have to create all of these directories and files by hand. That's where `ansible-galaxy` comes in. 48 | 49 | ## Section 1: Using ansible-galaxy to initialize a new role 50 | 51 | Ansible Galaxy is a free site for finding, downloading, and sharing roles. Ansible includes the tool `ansible-galaxy` which can interact with the site and the roles hosted there. It's also pretty handy for creating them locally which is what we are about to do here. 52 | 53 | ### Step 1 54 | 55 | Create a new directory, `apache-role`. 56 | 57 | ```bash 58 | cd 59 | mkdir apache-role 60 | cd ~/apache-role 61 | ``` 62 | 63 | ### Step 2 64 | 65 | Create a directory called `roles` and `cd` into it. 66 | 67 | ```bash 68 | mkdir roles 69 | cd roles 70 | ``` 71 | 72 | ### Step 3 73 | 74 | Use the `ansible-galaxy` command to initialize a new role called `apache-simple`. 75 | 76 | ```bash 77 | ansible-galaxy init apache-simple 78 | ``` 79 | 80 | Take a look around the structure you just created. It should look a lot like Figure 1 above. However, we need to complete one more step before moving onto section 2. It is Ansible best practice to clean out role directories and files you won't be using. For this role, we won't be using anything from `files`, `tests`. 81 | 82 | ### Step 4 83 | 84 | Remove the `files` and `tests` directories 85 | 86 | ```bash 87 | cd ~/apache-role/roles/apache-simple/ 88 | rm -rf files tests 89 | ``` 90 | 91 | ## Section 2: Breaking Your `site.yml` Playbook into the Newly Created `apache-simple` Role 92 | 93 | In this section, we will separate out the major parts of your playbook including `vars:`, `tasks:`, `template:`, and `handlers:`. 94 | 95 | ### Step 1 96 | 97 | Make a copy of `site.yml` which was written in the last exercise to the current directory. 98 | 99 | ```bash 100 | cd ~/apache-role 101 | cp ~/apache-basic-playbook/site.yml site.yml 102 | vim site.yml 103 | ``` 104 | 105 | ### Step 2 106 | 107 | Add the play definition and the invocation of a single role. 108 | 109 | ```yml 110 | --- 111 | - name: Ensure apache is installed and started via role 112 | hosts: web 113 | become: yes 114 | 115 | roles: 116 | - apache-simple 117 | ``` 118 | 119 | ### Step 3 120 | 121 | Add some default variables to your role in `roles/apache-simple/defaults/main.yml`. 122 | 123 | ```yml 124 | --- 125 | # defaults file for apache-simple 126 | apache_test_message: This is a test message 127 | apache_max_keep_alive_requests: 115 128 | ``` 129 | 130 | ### Step 4 131 | 132 | Add some role-specific variables to your role in `roles/apache-simple/vars/main.yml`. 133 | 134 | ```yml 135 | --- 136 | # vars file for apache-simple 137 | httpd_packages: 138 | - httpd 139 | - mod_wsgi 140 | ``` 141 | 142 | --- 143 | **NOTE** 144 | #### 145 | As can be seen above, we added variables at another place than the previously directly in the playbook. Variables can be defined in a variety of places and have a clear [precedence](http://docs.ansible.com/ansible/latest/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable). Here are some examples where variables can be placed: 146 | 147 | * vars directory 148 | * defaults directory 149 | * group_vars directory 150 | * In the playbook under the `vars:` section 151 | * In any file which can be specified on the command line using the `--extra_vars` option 152 | 153 | In this exercise, we are using role defaults to define a couple of variables and these are the most malleable. After that, we defined some variables in `/vars` which have a higher precedence than defaults and can't be overridden as a default variable. 154 | 155 | --- 156 | 157 | ### Step 5 158 | 159 | Create your role handler in `roles/apache-simple/handlers/main.yml`. 160 | 161 | ```yml 162 | --- 163 | # handlers file for apache-simple 164 | - name: restart-apache-service 165 | service: 166 | name: httpd 167 | state: restarted 168 | enabled: yes 169 | ``` 170 | 171 | ### Step 6 172 | 173 | Add tasks to your role in `roles/apache-simple/tasks/main.yml`. 174 | 175 | ```yml 176 | {% raw %} 177 | --- 178 | # tasks file for apache-simple 179 | - name: Ensure httpd packages are installed 180 | yum: 181 | name: "{{ item }}" 182 | state: present 183 | with_items: "{{ httpd_packages }}" 184 | notify: restart-apache-service 185 | 186 | - name: Ensure site-enabled directory is created 187 | file: 188 | name: /etc/httpd/conf/sites-enabled 189 | state: directory 190 | 191 | - name: Copy httpd.conf 192 | template: 193 | src: templates/httpd.conf.j2 194 | dest: /etc/httpd/conf/httpd.conf 195 | notify: restart-apache-service 196 | 197 | - name: Copy index.html 198 | template: 199 | src: templates/index.html.j2 200 | dest: /var/www/html/index.html 201 | 202 | - name: Ensure httpd is started 203 | service: 204 | name: httpd 205 | state: started 206 | enabled: yes 207 | {% endraw %} 208 | ``` 209 | 210 | ### Step 7 211 | 212 | Download a couple of templates into `roles/apache-simple/templates/`. And right after that, let's clean up from exercise 2.1 by removing the old templates directory. 213 | 214 | ```bash 215 | mkdir -p ~/apache-role/roles/apache-simple/templates/ 216 | cd ~/apache-role/roles/apache-simple/templates/ 217 | curl -O https://raw.githubusercontent.com/ansible/lightbulb/master/examples/apache-role/roles/apache-simple/templates/httpd.conf.j2 218 | curl -O https://raw.githubusercontent.com/ansible/lightbulb/master/examples/apache-role/roles/apache-simple/templates/index.html.j2 219 | ``` 220 | 221 | ## Section 3: Running your new role-based playbook 222 | 223 | Now that you've successfully separated your original playbook into a role, let's run it and see how it works. 224 | 225 | ### Step 1 226 | 227 | Run the playbook. 228 | 229 | ```bash 230 | ansible-playbook site.yml 231 | ``` 232 | 233 | If successful, your standard output should look similar to the figure below. 234 | 235 | ![Role based stdout](stdout_3.png) 236 | 237 | ## Section 4: Review 238 | 239 | You should now have a completed playbook, `site.yml` with a single role called `apache-simple`. The advantage of structuring your playbook into roles is that you can now add new roles to the playbook using Ansible Galaxy or simply writing your own. In addition, roles simplify changes to variables, tasks, templates, etc. 240 | 241 | --- 242 | 243 | [Click Here to return to the Ansible Lightbulb - Ansible Engine Guide](../README.md) 244 | -------------------------------------------------------------------------------- /guides/ansible_engine/4-role/stdout_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_engine/4-role/stdout_3.png -------------------------------------------------------------------------------- /guides/ansible_engine/README.md: -------------------------------------------------------------------------------- 1 | # Ansible Lightbulb - Ansible Engine Guide 2 | 3 | This guide is part of lightbulb, a multi-purpose toolkit for effectively demonstrating Ansible's capabilities or providing informal trainings in various forms -- instructor-led, hands-on or self-paced. 4 | 5 | The focus of this guide is on the set up and usage of Ansible Engine. 6 | 7 | ## Ansible Engine Exercises 8 | 9 | There are multiple exercises available. It is strongly recommended to run them one after the other. They are self-explaining and can be run at self pace. 10 | 11 | * [Exercise 1 - Running Ad-hoc commands](1-adhoc) 12 | * [Exercise 2 - Writing Your First playbook](2-playbook) 13 | * [Exercise 3 - Using Variables, Loops, and Handlers](3-variables) 14 | * [Exercise 4 - Roles: Making your playbooks reusable](4-role) 15 | 16 | ## Additional information 17 | 18 | Additional information about Ansible, how to get started and where to proceed after this guide, have a look at the following sources: 19 | 20 | * [Ansible Getting Started](http://docs.ansible.com/ansible/latest/intro_getting_started.html) 21 | 22 | --- 23 | ![Ansible Red Hat Engine](ansible-engine-small.png) 24 | 25 | In addition to open source Ansible, there is Red Hat® Ansible® Engine which includes support and an SLA for the networking modules shown in these exercises 26 | 27 | Red Hat® Ansible® Engine is a fully supported product built on the simple, powerful and agentless foundation capabilities derived from the Ansible project. Please visit [ansible.com](https://www.ansible.com/ansible-engine) for more information. 28 | -------------------------------------------------------------------------------- /guides/ansible_engine/ansible-engine-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_engine/ansible-engine-small.png -------------------------------------------------------------------------------- /guides/ansible_tower/1-install/README.md: -------------------------------------------------------------------------------- 1 | # Exercise 1 - Installing Ansible Tower 2 | 3 | In this exercise, we are going to get Ansible Tower installed on your control node 4 | 5 | ## Installing Ansible Tower 6 | 7 | ### Step 1 8 | 9 | On your control node, change directories to /tmp 10 | 11 | ```bash 12 | cd /tmp 13 | ``` 14 | 15 | ### Step 2 16 | 17 | Download the latest Ansible Tower package 18 | 19 | ```bash 20 | curl -O http://releases.ansible.com/ansible-tower/setup/ansible-tower-setup-latest.tar.gz 21 | ``` 22 | 23 | ### Step 3 24 | 25 | Untar and unzip the package file 26 | 27 | ```bash 28 | tar xvfz /tmp/ansible-tower-setup-latest.tar.gz 29 | ``` 30 | 31 | ### Step 4 32 | 33 | Change directories into the ansible tower package 34 | 35 | ```bash 36 | cd /tmp/ansible-tower-setup-*/ 37 | ``` 38 | 39 | ### Step 5 40 | 41 | Using an editor of your choice, open the inventory file 42 | 43 | ```bash 44 | vi inventory 45 | ``` 46 | 47 | ### Step 6 48 | 49 | Fill a few variables out in an inventory file: `admin_password, pg_password, rabbitmq_password` 50 | 51 | ```ini 52 | [tower] 53 | localhost ansible_connection=local 54 | 55 | [database] 56 | 57 | [all:vars] 58 | admin_password=*'ansibleWS'* 59 | 60 | pg_host='' 61 | pg_port='' 62 | 63 | pg_database='awx' 64 | pg_username='awx' 65 | pg_password=*'ansibleWS'* 66 | 67 | rabbitmq_port=5672 68 | rabbitmq_vhost=tower 69 | rabbitmq_username=tower 70 | rabbitmq_password=*'ansibleWS'* 71 | rabbitmq_cookie=cookiemonster 72 | 73 | = Needs to be true for fqdns and ip addresses 74 | rabbitmq_use_long_name=false 75 | ``` 76 | 77 | ### Step 7 78 | 79 | Run the Ansible Tower setup script 80 | 81 | ```bash 82 | sudo ./setup.sh 83 | ``` 84 | 85 | --- 86 | **NOTE:** Installation will take some time 87 | Step 7 will take approx. 10-15 minutes to complete. This may be a good time to take a break. 88 | 89 | --- 90 | 91 | ### End Result 92 | 93 | At this point, your Ansible Tower installation should be complete. You can access your Tower at the IP of the control node: 94 | 95 | ```bash 96 | http:// 97 | ``` 98 | 99 | ### Ensuring Installation Success 100 | 101 | You know you were successful if you are able to browse to your Ansible Tower's url (_control node's IP address_) and get something like this 102 | 103 | ![Ansible Tower Login Screen](ansible-lab-figure01-logon-screen.png) 104 | 105 | --- 106 | 107 | [Click Here to return to the Ansible Lightbulb - Ansible Tower Guide](../README.md) 108 | -------------------------------------------------------------------------------- /guides/ansible_tower/1-install/ansible-lab-figure01-logon-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/1-install/ansible-lab-figure01-logon-screen.png -------------------------------------------------------------------------------- /guides/ansible_tower/2-config/README.md: -------------------------------------------------------------------------------- 1 | # Exercise 2 - Configuring Ansible Tower 2 | 3 | In this exercise, we are going to configure Tower so that we can run a playbook. 4 | 5 | ## The Tower UI 6 | 7 | There are a number of concepts in the Ansible Tower UI that enable multi-tenancy, notifications, scheduling, etc. However, we are only going to focus on a few of the key contructs that are required for this workshop today. 8 | 9 | * Credentials 10 | * Projects 11 | * Inventory 12 | * Job Template 13 | 14 | ## Logging into Tower and Installing the License Key 15 | 16 | ### Step 1 17 | 18 | To log in, use the username `admin` and and the password `ansibleWS`. 19 | 20 | ![Ansible Tower Login Screen](ansible-lab-figure01-logon-screen.png) 21 | 22 | As soon as you login, you will prompted to request a license or browse for an existing license file 23 | 24 | ![Uploading a License](at_lic_prompt.png) 25 | 26 | ### Step 2 27 | 28 | In a seperate browser tab, browse to [https://www.ansible.com/workshop-license](https://www.ansible.com/workshop-license) to request a workshop license. These are special workshop licenses which are valid for only 5 nodes for 5 days. 29 | 30 | ### Step 3 31 | 32 | Back in the Tower UI, choose BROWSE ![Browse button](at_browse.png) and upload the license file you received via e-mail. 33 | 34 | ### Step 4 35 | 36 | Select "_I agree to the End User License Agreement_" 37 | 38 | ### Step 5 39 | 40 | Click on SUBMIT ![Submit button](at_submit.png) 41 | 42 | ## Creating a Credential 43 | 44 | Credentials are utilized by Tower for authentication when launching jobs against machines, synchronizing with inventory sources, and importing project content from a version control system. 45 | 46 | There are many [types of credentials](http://docs.ansible.com/ansible-tower/latest/html/userguide/credentials.html#credential-types) including machine, network, and various cloud providers. In this workshop, we are using a *machine* credential. 47 | 48 | ### Step 1 49 | 50 | Select the gear icon ![Gear button](at_gear.png) 51 | 52 | ### Step 2 53 | 54 | Select CREDENTIALS 55 | 56 | ### Step 3 57 | 58 | Click on ADD ![Add button](at_add.png) 59 | 60 | ### Step 4 61 | 62 | Complete the form using the following entries. 63 | 64 | |OPTION|VALUE 65 | |------|----- 66 | |NAME |Ansible Workshop Credential 67 | |DESCRIPTION|Machine credential for run job templates during workshop 68 | |ORGANIZATION|Default 69 | |TYPE|Machine 70 | |USERNAME|Your workshop username - Student(x) 71 | |PASSWORD|Your workshop password 72 | |PRIVILEGE ESCALATION|Sudo 73 | 74 | ![Adding a Credential](at_cred_detail.png) 75 | 76 | ### Step 5 77 | 78 | Select SAVE ![Save button](at_save.png) 79 | 80 | ## Creating a Project 81 | 82 | A Project is a logical collection of Ansible playbooks, represented in Tower. You can manage playbooks and playbook directories by either placing them manually under the Project Base Path on your Tower server, or by placing your playbooks into a source code management (SCM) system supported by Tower, including Git, Subversion, and Mercurial. 83 | 84 | ### Step 1 85 | 86 | Click on PROJECTS 87 | 88 | ### Step 2 89 | 90 | Click on ADD ![Add button](at_add.png). 91 | 92 | ### Step 3 93 | 94 | Complete the form using the following entries 95 | 96 | |OPTION|VALUE 97 | |------|----- 98 | |NAME |Ansible Workshop Project 99 | |DESCRIPTION|Workshop playbooks 100 | |ORGANIZATION|Default 101 | |SCM TYPE|Git 102 | |SCM URL| [https://github.com/ansible/lightbulb](https://github.com/ansible/lightbulb) 103 | |SCM BRANCH| 104 | |SCM UPDATE OPTIONS|Mark _Clean_ and _Update on Launch_ 105 | 106 | ![Defining a Project](at_project_detail.png) 107 | 108 | ### Step 4 109 | 110 | Select SAVE ![Save button](at_save.png) 111 | 112 | ## Creating a Inventory 113 | 114 | An inventory is a collection of hosts against which jobs may be launched. Inventories are divided into groups and these groups contain the actual hosts. Groups may be sourced manually, by entering host names into Tower, or from one of Ansible Tower’s supported cloud providers. 115 | 116 | An Inventory can also be imported into Tower using the `tower-manage` command and this is how we are going to add an inventory for this workshop. 117 | 118 | ### Step 1 119 | 120 | Click on INVENTORIES 121 | 122 | ### Step 2 123 | 124 | Select ADD ![Add button](at_add.png) 125 | 126 | ### Step 3 127 | 128 | Complete the form using the following entries 129 | 130 | |OPTION|VALUE 131 | |------|----- 132 | |NAME |Ansible Workshop Inventory 133 | |DESCRIPTION|Ansible Inventory 134 | |ORGANIZATION|Default 135 | 136 | ![Create an Inventory](at_inv_create.png) 137 | 138 | ### Step 4 139 | 140 | Select SAVE ![Save button](at_save.png) 141 | 142 | ### Step 5 143 | 144 | Using ssh, login to your control node 145 | 146 | ```bash 147 | ssh @ 148 | ``` 149 | 150 | ### Step 6 151 | 152 | Use the `tower-manage` command to import an existing inventory. (_Be sure to replace with your actual username_) 153 | 154 | ``` 155 | sudo tower-manage inventory_import --source=/home//lightbulb/lessons/lab_inventory/-instances.txt --inventory-name="Ansible Workshop Inventory" 156 | ``` 157 | 158 | You should see output similar to the following: 159 | 160 | ![Importing an inventory with tower-manage](at_tm_stdout.png) 161 | 162 | Feel free to browse your inventory in Tower. You should now notice that the inventory has been populated with Groups and that each of those groups contain hosts. 163 | 164 | ![Inventory with Groups](at_inv_group.png) 165 | 166 | ### End Result 167 | 168 | At this point, we are doing with our basic configuration of Ansible Tower. In exercise 2.2, we will be soley focused on creating and running a job template so you can see Tower in action. 169 | 170 | --- 171 | 172 | [Click Here to return to the Ansible Lightbulb - Ansible Tower Guide](../README.md) 173 | -------------------------------------------------------------------------------- /guides/ansible_tower/2-config/ansible-lab-figure01-logon-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/2-config/ansible-lab-figure01-logon-screen.png -------------------------------------------------------------------------------- /guides/ansible_tower/2-config/at_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/2-config/at_add.png -------------------------------------------------------------------------------- /guides/ansible_tower/2-config/at_browse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/2-config/at_browse.png -------------------------------------------------------------------------------- /guides/ansible_tower/2-config/at_cred_detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/2-config/at_cred_detail.png -------------------------------------------------------------------------------- /guides/ansible_tower/2-config/at_gear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/2-config/at_gear.png -------------------------------------------------------------------------------- /guides/ansible_tower/2-config/at_inv_create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/2-config/at_inv_create.png -------------------------------------------------------------------------------- /guides/ansible_tower/2-config/at_inv_group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/2-config/at_inv_group.png -------------------------------------------------------------------------------- /guides/ansible_tower/2-config/at_lic_prompt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/2-config/at_lic_prompt.png -------------------------------------------------------------------------------- /guides/ansible_tower/2-config/at_project_detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/2-config/at_project_detail.png -------------------------------------------------------------------------------- /guides/ansible_tower/2-config/at_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/2-config/at_save.png -------------------------------------------------------------------------------- /guides/ansible_tower/2-config/at_submit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/2-config/at_submit.png -------------------------------------------------------------------------------- /guides/ansible_tower/2-config/at_tm_stdout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/2-config/at_tm_stdout.png -------------------------------------------------------------------------------- /guides/ansible_tower/3-create/README.md: -------------------------------------------------------------------------------- 1 | # Exercise 3 - Creating and Running a Job Template 2 | 3 | A job template is a definition and set of parameters for running an Ansible job. Job templates are useful to execute the same job many times. 4 | 5 | ## Creating a Job Template 6 | 7 | ### Step 1 8 | 9 | Select TEMPLATES 10 | 11 | ### Step 2 12 | 13 | Click on ADD ![Add button](at_add.png), and select JOB TEMPLATE 14 | 15 | ### Step 3 16 | 17 | Complete the form using the following values 18 | 19 | |OPTION|VALUE 20 | |------|----- 21 | |NAME |Apache Basic Job Template 22 | |DESCRIPTION|Template for the apache-basic-playbook 23 | |JOB TYPE|Run 24 | |INVENTORY|Ansible Workshop Inventory 25 | |PROJECT|Ansible Workshop Project 26 | |PLAYBOOK|examples/apache-basic-playbook/site.yml 27 | |MACHINE CREDENTIAL|Ansible Workshop Credential 28 | |LIMIT|web 29 | |OPTIONS|Check _Enable Privilege Escalation_ 30 | 31 | ![Job Template Form](at_jt_detail.png) 32 | 33 | ### Step 4 34 | 35 | Click SAVE ![Save button](at_save.png) and then select ADD SURVEY ![Add](at_addsurvey.png) 36 | 37 | ### Step 5 38 | 39 | Complete the survey form with following values 40 | 41 | |OPTION|VALUE 42 | |------|----- 43 | |PROMPT|Please enter a test message for your new website 44 | |DESCRIPTION|Website test message prompt 45 | |ANSWER VARIABLE NAME|apache_test_message 46 | |ANSWER TYPE|Text 47 | |MINIMUM/MAXIMUM LENGTH| Use the defaults 48 | |DEFAULT ANSWER| Be creative, keep it clean, we're all professionals here 49 | 50 | ![Survey Form](at_survey_detail.png) 51 | 52 | ### Step 6 53 | 54 | Select ADD ![Add button](at_add.png) 55 | 56 | ### Step 7 57 | 58 | Select SAVE ![Add button](at_save.png) 59 | 60 | ### Step 8 61 | 62 | Back on the main Job Template page, select SAVE ![Add button](at_save.png) again. 63 | 64 | ## Running a Job Template 65 | 66 | Now that you’ve sucessfully created your Job Template, you are ready to launch it. Once you do, you will be redirected to a job screen which is refreshing in realtime showing you the status of the job. 67 | 68 | ### Step 1 69 | 70 | Select TEMPLATES 71 | 72 | --- 73 | **NOTE**: Alternative way to navigate to TEMPLATES: 74 | 75 | If you haven't navigated away from the job templates creation page you can scroll down to see all existing job templates 76 | 77 | --- 78 | 79 | ### Step 2 80 | 81 | Click on the rocketship icon ![Launch button](at_launch_icon.png) for the *Apache Basic Job Template* 82 | 83 | ### Step 3 84 | 85 | When prompted, enter your desired test message 86 | 87 | ![Survey Prompt](at_survey_prompt.png) 88 | 89 | ### Step 4 90 | 91 | Select LAUNCH ![Survey launch button](at_survey_launch.png) 92 | 93 | ### Step 5 94 | 95 | Wait and watch the execution of the job. 96 | 97 | One of the first things you will notice is the summary section. This gives you details about your job such as who launched it, what playbook it's running, what the status is, i.e. pending, running, or complete. You’ll also notice the `apache_test_message` being passed in the field EXTRA VARIABLES in the text box on the left bottom side. To the right, you can view standard output; the same way you could if you were running `ansible-playbook` from the command line. 98 | 99 | ![Job Summary](at_job_status.png) 100 | 101 | You can also click on each task in the standard output to get more details. 102 | 103 | ### Step 6 104 | 105 | Once your job is sucessful, navigate to your new website: 106 | 107 | ```bash 108 | http:// 109 | ``` 110 | 111 | If all went well, you should see something like this, but with your own custom message: 112 | 113 | ![New Website with Personalized Test Message](at_web_tm.png) 114 | 115 | ## End Result 116 | 117 | At this point in the workshop, you've experienced the core functionality of Ansible Tower. To read more about advanced features of Tower, take a look at the resources page in this guide. 118 | 119 | --- 120 | 121 | [Click Here to return to the Ansible Lightbulb - Ansible Tower Guide](../README.md) 122 | -------------------------------------------------------------------------------- /guides/ansible_tower/3-create/at_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/3-create/at_add.png -------------------------------------------------------------------------------- /guides/ansible_tower/3-create/at_addsurvey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/3-create/at_addsurvey.png -------------------------------------------------------------------------------- /guides/ansible_tower/3-create/at_job_status.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/3-create/at_job_status.png -------------------------------------------------------------------------------- /guides/ansible_tower/3-create/at_jt_detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/3-create/at_jt_detail.png -------------------------------------------------------------------------------- /guides/ansible_tower/3-create/at_launch_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/3-create/at_launch_icon.png -------------------------------------------------------------------------------- /guides/ansible_tower/3-create/at_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/3-create/at_save.png -------------------------------------------------------------------------------- /guides/ansible_tower/3-create/at_survey_detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/3-create/at_survey_detail.png -------------------------------------------------------------------------------- /guides/ansible_tower/3-create/at_survey_launch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/3-create/at_survey_launch.png -------------------------------------------------------------------------------- /guides/ansible_tower/3-create/at_survey_prompt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/3-create/at_survey_prompt.png -------------------------------------------------------------------------------- /guides/ansible_tower/3-create/at_web_tm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/3-create/at_web_tm.png -------------------------------------------------------------------------------- /guides/ansible_tower/README.md: -------------------------------------------------------------------------------- 1 | # Ansible Lightbulb - Ansible Tower Guide 2 | 3 | This guide is part of lightbulb, a multi-purpose toolkit for effectively demonstrating Ansible's capabilities or providing informal trainings in various forms -- instructor-led, hands-on or self-paced. 4 | 5 | The focus of this guide is on the set up and usage of Ansible Tower. 6 | 7 | ## Ansible Tower Exercises 8 | 9 | There are multiple exercises available. It is strongly recommended to run them one after the other. They are self-explaining and can be run at self pace. 10 | 11 | * [Exercise 1 - Installing Ansible Tower](1-install) 12 | * [Exercise 2 - Configuring Ansible Tower](2-config) 13 | * [Exercise 3 - Creating and Running a Job Template](3-create) 14 | 15 | ## Additional information 16 | 17 | Additional information about Ansible, how to get started and where to proceed after this guide, have a look at the following sources: 18 | 19 | * [Ansible Tower User Guide](http://docs.ansible.com/ansible-tower/latest/html/userguide/index.html) 20 | * [Ansible Tower Administration Guide](http://docs.ansible.com/ansible-tower/latest/html/administration/index.html) 21 | 22 | --- 23 | ![Ansible Tower](ansible_tower_logo.png) 24 | 25 | Red Hat® Ansible® Tower is a fully supported product built on the simple, powerful and agentless foundation capabilities derived from the Ansible project. Please visit [ansible.com](https://www.ansible.com/tower) for more information. 26 | -------------------------------------------------------------------------------- /guides/ansible_tower/ansible_tower_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/ansible_tower_logo.png -------------------------------------------------------------------------------- /guides/ansible_tower/tower.002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/tower.002.png -------------------------------------------------------------------------------- /guides/ansible_tower/wetty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/guides/ansible_tower/wetty.png -------------------------------------------------------------------------------- /inventory.ini: -------------------------------------------------------------------------------- 1 | [control] 2 | ansible ansible_host=10.42.0.2 3 | 4 | [web] 5 | node-1 ansible_host=10.42.0.6 6 | node-2 ansible_host=10.42.0.7 7 | node-3 ansible_host=10.42.0.8 8 | 9 | [all:vars] 10 | ansible_user=vagrant 11 | ansible_ssh_private_key_file=~/.vagrant.d/insecure_private_key 12 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/.gitignore: -------------------------------------------------------------------------------- 1 | *instances.txt 2 | instructor_inventory 3 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/README.md: -------------------------------------------------------------------------------- 1 | # Ansible AWS training provisioner 2 | 3 | This provisioner automatically sets up lab environments for Ansible training. It creates four nodes per student/user. 4 | 5 | * One control node from which Ansible will be executed from and where Ansible Tower can be installed 6 | * Three web nodes that coincide with the three nodes in Lightbulb's original design 7 | * And one node where `haproxy` is installed (via Lightbulb lesson) 8 | 9 | ## AWS Setup 10 | 11 | The setup of the environments is done via Ansible playbooks, the actual VMs are set up on AWS. The `provision_lab.yml` playbook creates instances, configures them for password authentication and creates an inventory file for each user with their IPs and credentials. An instructor inventory file is also created in the current directory which will let the instructor access the nodes of any student by simply targeting the username as a host group. The lab is created in `us-east-1` by default. Currently the setup only works with `us-east-1`, `us-west-1`, `eu-west-1`, `ap-southeast-1`, `ap-southeast-2`, `ap-south-1` and `ap-northeast-1`. 12 | 13 | ## Email Options 14 | 15 | This provisioner by default will send email to participants/students containing information about their lab environment including IPs and credentials. This configuration requires that each participant register for the workshop using their full name and email address. Alternatively, you can use generic accounts for workshops. This method offers the advantage of enabling the facilitator to handle "walk-ins" and is a simpler method overall in terms of collecting participant information. 16 | 17 | Steps included in this guide will be tagged with __(email)__ to denote it as a step required if you want to use email and __(no email)__ for steps you should follow if you chose not to use email 18 | 19 | **WARNING** Emails are sent _every_ time the playbook is run. To prevent emails from being sent on subsequent runs of the playbook, add `email: no` to `extra_vars.yml`. 20 | 21 | ## How To Set Up Lab Environments 22 | 23 | ### One-Time Preparations 24 | 25 | To set up lab environments for Ansible training, follow these steps. 26 | 27 | 1. Create an Amazon AWS account. 28 | 29 | 1. In AWS, create an ssh key pair called 'ansible': In the AWS management console, click on "Services" on top of the page. In the menu that opens, click on "EC2". In the EC2 dashboard, on the left side, underneath "Network & Security" pick "Key Pairs". Download the private key to your `.ssh` directory, e.g. to `.ssh/ansible.pem`. Alternatively, you can upload your own public key into AWS. 30 | 31 | If using an AWS generated key add it to the ssh-agent: 32 | 33 | ssh-add ~/.ssh/ansible.pem 34 | 35 | 1. Create an Access Key ID and Secret Access Key. Save the ID and key for later. See [AWSHELP](aws-directions/AWSHELP.md) for a detailed howto. 36 | 37 | 1. Install `boto` and `boto3`. 38 | 39 | pip install boto boto3 40 | 41 | 1. Create a `boto` configuration file containing your AWS access key ID and secret access key. 42 | 43 | Use the quickstart directions provided here: [http://boto3.readthedocs.io/en/latest/guide/quickstart.html](http://boto3.readthedocs.io/en/latest/guide/quickstart.html) 44 | 45 | 1. __(email)__ Create a free [Sendgrid](http://sendgrid.com) account if you don't have one. Optionally, create an API key to use with this the playbook. 46 | 47 | 1. __(email)__ Install the `sendgrid` python library: 48 | 49 | **Note:** The `sendgrid` module does not work with `sendgrid >= 3`. Please install the latest `2.x` version. 50 | 51 | pip install sendgrid==2.2.1 52 | 53 | 1. Install the `passlib` library 54 | 55 | pip install passlib 56 | 57 | 1. Clone the lightbulb repo: 58 | 59 | git clone https://github.com/ansible/lightbulb.git 60 | cd lightbulb/tools/aws_lab_setup 61 | 62 | ### Steps To Provision the Lab Environments 63 | 64 | 1. Update your current installation of the lightbulb repo 65 | 66 | 1. Define the following variables, either in a file passed in using `-e @extra_vars.yml` or directly in a `vars` section in `aws_lab_setup\infra-aws.yml`: 67 | 68 | ```yaml 69 | ec2_key_name: username # SSH key in AWS to put in all the instances 70 | ec2_region: us-west-1 # region where the nodes will live 71 | ec2_az: us-east-1a # the availability zone 72 | ec2_name_prefix: TRAINING-LAB # name prefix for all the VMs 73 | admin_password: changeme123 # Set this to something better if you'd like. Defaults to 'LearnAnsible[two digit month][two digit year]', e.g., LearnAnsible0416 74 | ## Optional Variables 75 | email: no # Set this if you wish to disable email 76 | sendgrid_user: username # username for the Sendgrid module. Not required if "email: no" is set 77 | sendgrid_pass: 'passwordgoeshere' # sendgrid accound password. Not required if "email: no" is set 78 | sendgrid_api_key: 'APIkey' # Instead of username and password, you may use an API key. Don't define both. Not required if "email: no" is set 79 | instructor_email: 'Ansible Instructor ' # address you want the emails to arrive from. Not required if "email: no" is set 80 | ``` 81 | 82 | 1. Create a `users.yml` by copying `sample-users.yml` and adding all your students: 83 | 84 | __(email)__ 85 | 86 | ```yaml 87 | users: 88 | - name: Bod Barker 89 | username: bbarker 90 | email: bbarker@acme.com 91 | 92 | - name: Jane Smith 93 | username: jsmith 94 | email: jsmith@acme.com 95 | ``` 96 | 97 | __(no email)__ 98 | 99 | ```yaml 100 | users: 101 | - name: Student01 102 | username: student01 103 | email: instructor@acme.com 104 | 105 | - name: Student02 106 | username: student02 107 | email: instructor@acme.com 108 | ``` 109 | 110 | **(no email) NOTE:** If using generic users, you can generate the corresponding 111 | `users.yml` file from the command line by creating a 'STUDENTS' variable 112 | containing the number of "environments" you want, and then populating the file. 113 | For example: 114 | 115 | STUDENTS=30; 116 | echo "users:" > users.yml && 117 | for NUM in $(seq -f "%02g" 1 $STUDENTS); do 118 | echo " - name: Student${NUM}" >> users.yml 119 | echo " username: student${NUM}" >> users.yml 120 | echo " email: instructor@acme.com" >> users.yml 121 | echo >> users.yml 122 | done 123 | 124 | 1. Run the playbook: 125 | 126 | ansible-playbook provision_lab.yml -e @extra_vars.yml -e @users.yml 127 | 128 | 1. Check on the EC2 console and you should see instances being created like: 129 | 130 | TRAINING-LAB--node1|2|3|haproxy|tower|control 131 | 132 | In your EC2 console you will also see that a VPC was automatically created with a corresponding subnet. 133 | 134 | __(email)__ If successful all your students will be emailed the details of their hosts including addresses and credentials, and an `instructor_inventory.txt` file will be created listing all the student machines. 135 | 136 | __(no email)__ If you disabled email in your `extra_vars.yml` file, you will need to upload the instructor's inventory to a public URL which you will hand out to participants. 137 | 138 | 1. Use [github gist](https://gist.github.com/) to upload `lightbulb/tools/aws_lab_setup/instructors_inventory`. 139 | 1. Use [http://goo.gl](http://goo.gl) to shorten the URL to make it more consumable 140 | 141 | ### Teardown The Lab Environments 142 | 143 | The `teardown_lab.yml` playbook deletes all the training instances as well as local inventory files. 144 | 145 | To destroy all the EC2 instances after training is complete: 146 | 147 | 1. Run the playbook: 148 | 149 | ansible-playbook teardown_lab.yml -e @extra_vars.yml -e @users.yml 150 | 151 | ## Accessing student documentation and slides 152 | 153 | * A student guide and instructor slides are already hosted at [http://ansible-workshop.redhatgov.io](http://ansible-workshop.redhatgov.io) . (NOTE: This guide is evolving and newer workshops can be previewed at [http://ansible.redhatgov.io](http://ansible.redhatgov.io) . This new version is currently being integrated with the Lightbulb project) 154 | * Here you will find student instructions broken down into exercises as well as the presentation decks under the __Additional Resources__ drop down. 155 | * During the workshop, it is recommended that you have a second device or printed copy of the student guide. Previous workshops have demonstrated that unless you've memorized all of it, you'll likely need to refer to the guide, but your laptop will be projecting the slide decks. Some students will fall behind and you'll need to refer back to other exercises/slides without having to change the projection for the entire class. 156 | 157 | 158 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/ansible.cfg: -------------------------------------------------------------------------------- 1 | # config file for ansible -- http://ansible.com/ 2 | # ============================================== 3 | 4 | # nearly all parameters can be overridden in ansible-playbook 5 | # or with command line flags. ansible will read ANSIBLE_CONFIG, 6 | # ansible.cfg in the current working directory, .ansible.cfg in 7 | # the home directory or /etc/ansible/ansible.cfg, whichever it 8 | # finds first 9 | 10 | [defaults] 11 | 12 | # some basic default values... 13 | 14 | inventory = ./inventory.ini 15 | forks = 50 16 | host_key_checking = False 17 | retry_files_enabled = False 18 | no_target_syslog = False 19 | 20 | [ssh_connection] 21 | scp_if_ssh = True 22 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/aws-directions/AWSHELP.md: -------------------------------------------------------------------------------- 1 | # AWS DIRECTIONS HELP 2 | 3 | These steps will walk you through where to create credentials (Access Key ID and Secret Access Key) on AWS to use for provisioning VMs with Ansible. 4 | 5 | ## Login 6 | 7 | Login to the AWS Console on [https://aws.amazon.com/](https://aws.amazon.com/) 8 | 9 | ![login](login-window.png) 10 | 11 | ## Go to IAM 12 | 13 | Under Services click on IAM to reach the IAM Management Console 14 | 15 | ![iam](iam.png) 16 | 17 | ## Go to Users 18 | 19 | On the left pane click on the users link 20 | 21 | ![users](users.png) 22 | 23 | On the right side, pick the tab "Security credentials". Now you need to either add a new user 24 | 25 | ![add-user](add-user.png) 26 | 27 | OR find the user you want to add credentials <- this is more common 28 | 29 | ## Add Credentials 30 | 31 | You need to create a new access key, only then will the necessary key and key ID be shown. Make sure you save them somewhere!! (But don't upload to GitHub or someone will start mining Bitcoins on your account) 32 | 33 | ![create-key](create-key.png) 34 | 35 | You now have your Access Key ID and Secret Access Key! 36 | 37 | ## AWS References 38 | 39 | - [Access Key ID and Secret Access Key](http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html) 40 | - [managing-aws-access-keys.html](http://docs.aws.amazon.com/general/latest/gr/managing-aws-access-keys.html). 41 | 42 | [Return to aws_lab_setup directions](../README.md) 43 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/aws-directions/add-user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/tools/aws_lab_setup/aws-directions/add-user.png -------------------------------------------------------------------------------- /tools/aws_lab_setup/aws-directions/create-key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/tools/aws_lab_setup/aws-directions/create-key.png -------------------------------------------------------------------------------- /tools/aws_lab_setup/aws-directions/ec2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/tools/aws_lab_setup/aws-directions/ec2.png -------------------------------------------------------------------------------- /tools/aws_lab_setup/aws-directions/iam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/tools/aws_lab_setup/aws-directions/iam.png -------------------------------------------------------------------------------- /tools/aws_lab_setup/aws-directions/login-window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/tools/aws_lab_setup/aws-directions/login-window.png -------------------------------------------------------------------------------- /tools/aws_lab_setup/aws-directions/users.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/tools/aws_lab_setup/aws-directions/users.png -------------------------------------------------------------------------------- /tools/aws_lab_setup/inventory.ini: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | 4 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/inventory/ec2.ini: -------------------------------------------------------------------------------- 1 | # Ansible EC2 external inventory script settings 2 | # 3 | 4 | [ec2] 5 | 6 | # to talk to a private eucalyptus instance uncomment these lines 7 | # and edit edit eucalyptus_host to be the host name of your cloud controller 8 | #eucalyptus = True 9 | #eucalyptus_host = clc.cloud.domain.org 10 | 11 | # AWS regions to make calls to. Set this to 'all' to make request to all regions 12 | # in AWS and merge the results together. Alternatively, set this to a comma 13 | # separated list of regions. E.g. 'us-east-1,us-west-1,us-west-2' 14 | regions = all 15 | regions_exclude = us-gov-west-1,cn-north-1 16 | 17 | # When generating inventory, Ansible needs to know how to address a server. 18 | # Each EC2 instance has a lot of variables associated with it. Here is the list: 19 | # http://docs.pythonboto.org/en/latest/ref/ec2.html#module-boto.ec2.instance 20 | # Below are 2 variables that are used as the address of a server: 21 | # - destination_variable 22 | # - vpc_destination_variable 23 | 24 | # This is the normal destination variable to use. If you are running Ansible 25 | # from outside EC2, then 'public_dns_name' makes the most sense. If you are 26 | # running Ansible from within EC2, then perhaps you want to use the internal 27 | # address, and should set this to 'private_dns_name'. The key of an EC2 tag 28 | # may optionally be used; however the boto instance variables hold precedence 29 | # in the event of a collision. 30 | destination_variable = public_dns_name 31 | 32 | # This allows you to override the inventory_name with an ec2 variable, instead 33 | # of using the destination_variable above. Addressing (aka ansible_ssh_host) 34 | # will still use destination_variable. Tags should be written as 'tag_TAGNAME'. 35 | #hostname_variable = tag_Name 36 | 37 | # For server inside a VPC, using DNS names may not make sense. When an instance 38 | # has 'subnet_id' set, this variable is used. If the subnet is public, setting 39 | # this to 'ip_address' will return the public IP address. For instances in a 40 | # private subnet, this should be set to 'private_ip_address', and Ansible must 41 | # be run from within EC2. The key of an EC2 tag may optionally be used; however 42 | # the boto instance variables hold precedence in the event of a collision. 43 | # WARNING: - instances that are in the private vpc, _without_ public ip address 44 | # will not be listed in the inventory until You set: 45 | # vpc_destination_variable = private_ip_address 46 | vpc_destination_variable = ip_address 47 | 48 | # The following two settings allow flexible ansible host naming based on a 49 | # python format string and a comma-separated list of ec2 tags. Note that: 50 | # 51 | # 1) If the tags referenced are not present for some instances, empty strings 52 | # will be substituted in the format string. 53 | # 2) This overrides both destination_variable and vpc_destination_variable. 54 | # 55 | #destination_format = {0}.{1}.example.com 56 | #destination_format_tags = Name,environment 57 | 58 | # To tag instances on EC2 with the resource records that point to them from 59 | # Route53, uncomment and set 'route53' to True. 60 | route53 = False 61 | 62 | # To exclude RDS instances from the inventory, uncomment and set to False. 63 | #rds = False 64 | 65 | # To exclude ElastiCache instances from the inventory, uncomment and set to False. 66 | #elasticache = False 67 | 68 | # Additionally, you can specify the list of zones to exclude looking up in 69 | # 'route53_excluded_zones' as a comma-separated list. 70 | # route53_excluded_zones = samplezone1.com, samplezone2.com 71 | 72 | # By default, only EC2 instances in the 'running' state are returned. Set 73 | # 'all_instances' to True to return all instances regardless of state. 74 | all_instances = False 75 | 76 | # By default, only EC2 instances in the 'running' state are returned. Specify 77 | # EC2 instance states to return as a comma-separated list. This 78 | # option is overriden when 'all_instances' is True. 79 | # instance_states = pending, running, shutting-down, terminated, stopping, stopped 80 | 81 | # By default, only RDS instances in the 'available' state are returned. Set 82 | # 'all_rds_instances' to True return all RDS instances regardless of state. 83 | all_rds_instances = False 84 | 85 | # By default, only ElastiCache clusters and nodes in the 'available' state 86 | # are returned. Set 'all_elasticache_clusters' and/or 'all_elastic_nodes' 87 | # to True return all ElastiCache clusters and nodes, regardless of state. 88 | # 89 | # Note that all_elasticache_nodes only applies to listed clusters. That means 90 | # if you set all_elastic_clusters to false, no node will be return from 91 | # unavailable clusters, regardless of the state and to what you set for 92 | # all_elasticache_nodes. 93 | all_elasticache_replication_groups = False 94 | all_elasticache_clusters = False 95 | all_elasticache_nodes = False 96 | 97 | # API calls to EC2 are slow. For this reason, we cache the results of an API 98 | # call. Set this to the path you want cache files to be written to. Two files 99 | # will be written to this directory: 100 | # - ansible-ec2.cache 101 | # - ansible-ec2.index 102 | cache_path = ~/.ansible/tmp 103 | 104 | # The number of seconds a cache file is considered valid. After this many 105 | # seconds, a new API call will be made, and the cache file will be updated. 106 | # To disable the cache, set this value to 0 107 | cache_max_age = 300 108 | 109 | # Organize groups into a nested/hierarchy instead of a flat namespace. 110 | nested_groups = False 111 | 112 | # Replace - tags when creating groups to avoid issues with ansible 113 | replace_dash_in_groups = True 114 | 115 | # If set to true, any tag of the form "a,b,c" is expanded into a list 116 | # and the results are used to create additional tag_* inventory groups. 117 | expand_csv_tags = False 118 | 119 | # The EC2 inventory output can become very large. To manage its size, 120 | # configure which groups should be created. 121 | group_by_instance_id = True 122 | group_by_region = True 123 | group_by_availability_zone = True 124 | group_by_ami_id = True 125 | group_by_instance_type = True 126 | group_by_key_pair = True 127 | group_by_vpc_id = True 128 | group_by_security_group = True 129 | group_by_tag_keys = True 130 | group_by_tag_none = True 131 | group_by_route53_names = True 132 | group_by_rds_engine = True 133 | group_by_rds_parameter_group = True 134 | group_by_elasticache_engine = True 135 | group_by_elasticache_cluster = True 136 | group_by_elasticache_parameter_group = True 137 | group_by_elasticache_replication_group = True 138 | 139 | # If you only want to include hosts that match a certain regular expression 140 | # pattern_include = staging-* 141 | 142 | # If you want to exclude any hosts that match a certain regular expression 143 | # pattern_exclude = staging-* 144 | 145 | # Instance filters can be used to control which instances are retrieved for 146 | # inventory. For the full list of possible filters, please read the EC2 API 147 | # docs: http://docs.aws.amazon.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeInstances.html#query-DescribeInstances-filters 148 | # Filters are key/value pairs separated by '=', to list multiple filters use 149 | # a list separated by commas. See examples below. 150 | 151 | # Retrieve only instances with (key=value) env=staging tag 152 | # instance_filters = tag:env=staging 153 | 154 | # Retrieve only instances with role=webservers OR role=dbservers tag 155 | # instance_filters = tag:role=webservers,tag:role=dbservers 156 | 157 | # Retrieve only t1.micro instances OR instances with tag env=staging 158 | # instance_filters = instance-type=t1.micro,tag:env=staging 159 | 160 | # You can use wildcards in filter values also. Below will list instances which 161 | # tag Name value matches webservers1* 162 | # (ex. webservers15, webservers1a, webservers123 etc) 163 | # instance_filters = tag:Name=webservers1* 164 | 165 | # A boto configuration profile may be used to separate out credentials 166 | # see http://boto.readthedocs.org/en/latest/boto_config_tut.html 167 | boto_profile = default 168 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/inventory/group_vars/all.yml: -------------------------------------------------------------------------------- 1 | ssh_port: 22 2 | 3 | users: 4 | - name: Brue Wayne 5 | username: bwayne 6 | email: bwayne@we.com 7 | 8 | admin_password: LearnAnsible{{ lookup('pipe', 'date +%m%y')}} 9 | admin_password_hash: "{{ admin_password | password_hash(salt='sRvXWmR5BBwqRlih') }}" 10 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/provision_lab.yml: -------------------------------------------------------------------------------- 1 | - name: Perform Checks to make sure this Playbook will complete successfully 2 | hosts: localhost 3 | connection: local 4 | become: no 5 | gather_facts: no 6 | tasks: 7 | - name: make sure we are running correct Ansible Version 8 | fail: 9 | msg: "Ansible version must be at least => 2.3.2" 10 | when: (ansible_version.major == 1) or 11 | (ansible_version.major == 2 and ansible_version.minor < 3) or 12 | (ansible_version.major == 2 and ansible_version.minor == 3 and ansible_version.revision < 2) 13 | 14 | - name: save username of AWS user 15 | set_fact: 16 | lightbulb_user: '{{ ec2_key_name }}' 17 | 18 | - name: Create lab instances in AWS 19 | hosts: localhost 20 | connection: local 21 | become: no 22 | gather_facts: no 23 | vars: 24 | teardown: false 25 | roles: 26 | - manage_ec2_instances 27 | 28 | - name: Configure common options on managed nodes and control nodes 29 | hosts: "managed_nodes:control_nodes" 30 | become: yes 31 | roles: 32 | - user_accounts 33 | - common 34 | 35 | - name: Configure control node 36 | hosts: control_nodes 37 | become: yes 38 | roles: 39 | - control_node 40 | 41 | - name: Email inventory to students 42 | hosts: localhost 43 | connection: local 44 | become: no 45 | gather_facts: no 46 | roles: 47 | - email 48 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/common/defaults/main.yml: -------------------------------------------------------------------------------- 1 | common_node_config_options: 2 | - dest: /etc/ssh/sshd_config 3 | regexp: '^#?Port' 4 | line: Port {{ ssh_port | default('22') }} 5 | validate: sshd -t -f %s 6 | 7 | - dest: /etc/ssh/sshd_config 8 | regexp: '^#?PasswordAuthentication' 9 | line: 'PasswordAuthentication yes' 10 | validate: sshd -t -f %s 11 | 12 | - dest: /etc/ssh/sshd_config 13 | regexp: '^#?UseDNS' 14 | line: 'UseDNS no' 15 | validate: sshd -t -f %s 16 | 17 | - dest: /etc/sudoers 18 | regexp: '^{{ username }}' 19 | line: '{{ username }} ALL=(ALL) NOPASSWD: ALL' 20 | validate: visudo -cf %s 21 | 22 | - dest: /etc/sudoers 23 | regexp: '^Defaults.*requiretty' 24 | line: 'Defaults !requiretty' 25 | validate: visudo -cf %s 26 | 27 | firewall_rules: 28 | - service: http 29 | - service: https 30 | - service: ssh 31 | - port: 5432 32 | protocol: udp 33 | - port: 5672 34 | protocol: udp 35 | - port: 5432 36 | protocol: tcp 37 | - port: 5672 38 | protocol: tcp 39 | 40 | firewalld_service: firewalld 41 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/common/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: restart sshd 2 | service: 3 | name: "{{ common_ssh_service_name }}" 4 | state: restarted 5 | 6 | - name: Reboot 7 | shell: sleep 2 && reboot 8 | async: 30 9 | poll: 0 10 | 11 | - name: Wait for instance 12 | delegate_to: localhost 13 | become: no 14 | wait_for: 15 | port: "{{ ssh_port | default('22') }}" 16 | host: "{{ ansible_host }}" 17 | search_regex: OpenSSH 18 | timeout: 500 19 | delay: 40 20 | 21 | - name: restart firewalld 22 | service: 23 | name: "{{ firewalld_service }}" 24 | state: restarted 25 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/common/tasks/RedHat.yml: -------------------------------------------------------------------------------- 1 | - name: RHEL | Set version specific variables 2 | include_vars: "{{ ansible_os_family }}-{{ ansible_distribution_major_version }}.yml" 3 | tags: 4 | - always 5 | 6 | - name: RHEL | Install {{ firewall_name }} and libselinux-python 7 | yum: 8 | name: 9 | - libselinux-python 10 | - "{{ firewall_name }}" 11 | state: present 12 | tags: 13 | - common 14 | 15 | - name: RHEL | Start firewalld 16 | service: 17 | name: "{{ firewalld_service }}" 18 | state: started 19 | 20 | - name: RHEL | Enable specific firewall services 21 | firewalld: 22 | immediate: yes 23 | permanent: yes 24 | port: "{{ item.port ~ '/' ~ item.protocol if (item.port is defined and item.protocol is defined) else omit }}" 25 | service: "{{ item.service | default(omit) }}" 26 | state: enabled 27 | with_items: "{{ firewall_rules }}" 28 | notify: restart firewalld 29 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/common/tasks/Ubuntu.yml: -------------------------------------------------------------------------------- 1 | - name: UBUNTU | Set version specific variables 2 | include_vars: "{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml" 3 | tags: 4 | - always 5 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/common/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Include Red Hat tasks 2 | include: "{{ ansible_os_family }}.yml" 3 | static: no 4 | when: ansible_os_family == 'RedHat' 5 | 6 | - name: Include Ubuntu tasks 7 | include: "{{ ansible_distribution }}.yml" 8 | static: no 9 | when: ansible_distribution == 'Ubuntu' 10 | 11 | - name: Configure sshd and sudoers 12 | lineinfile: 13 | dest: "{{ item.dest }}" 14 | regexp: "{{ item.regexp }}" 15 | line: "{{ item.line }}" 16 | state: "{{ item.state | default('present') }}" 17 | validate: "{{ item.validate | default(omit) }}" 18 | backup: no 19 | with_items: "{{ common_node_config_options }}" 20 | notify: restart sshd 21 | tags: 22 | - ssh 23 | - sudo 24 | - common 25 | 26 | - meta: flush_handlers 27 | tags: 28 | - common 29 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/common/vars/RedHat-6.yml: -------------------------------------------------------------------------------- 1 | firewall_name: iptables 2 | common_ssh_service_name: sshd 3 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/common/vars/RedHat-7.yml: -------------------------------------------------------------------------------- 1 | firewall_name: firewalld 2 | common_ssh_service_name: sshd 3 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/common/vars/Ubuntu-14.yml: -------------------------------------------------------------------------------- 1 | common_ssh_service_name: ssh 2 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/common/vars/Ubuntu-16.yml: -------------------------------------------------------------------------------- 1 | common_ssh_service_name: ssh 2 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/control_node/defaults/main.yml: -------------------------------------------------------------------------------- 1 | control_node_inventory_path: ~{{ username }}/lightbulb/lessons/lab_inventory/{{ username }}-instances.txt 2 | control_node_install_ansible: yes 3 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/control_node/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Install EPEL 2 | yum: 3 | name: "https://dl.fedoraproject.org/pub/epel/epel-release-latest-{{ ansible_distribution_major_version }}.noarch.rpm" 4 | state: present 5 | tags: 6 | - control_node 7 | - control 8 | 9 | - name: Install base packages 10 | yum: 11 | name: 12 | - vim 13 | - git 14 | - wget 15 | - nano 16 | 17 | state: latest 18 | enablerepo: epel-testing 19 | tags: 20 | - control_node 21 | - control 22 | 23 | - name: Install Ansible 24 | yum: 25 | name: 26 | - sshpass 27 | - ansible 28 | state: latest 29 | enablerepo: epel-testing 30 | tags: 31 | - control_node 32 | - control 33 | when: control_node_install_ansible 34 | 35 | 36 | - name: Clone lightbulb 37 | git: 38 | accept_hostkey: yes 39 | clone: yes 40 | dest: ~{{ username }}/lightbulb 41 | repo: https://github.com/ansible/lightbulb.git 42 | force: yes 43 | become_user: "{{ username }}" 44 | tags: 45 | - control_node 46 | - control 47 | 48 | - name: Remove things that students don't need 49 | file: 50 | state: absent 51 | path: ~{{ username }}/lightbulb/{{ item }} 52 | with_items: 53 | - aws_lab_setup 54 | - resources 55 | - Vagrantfile 56 | - README.md 57 | tags: 58 | - control_node 59 | - control 60 | 61 | - name: Install ansible.cfg and vimrc in home directory 62 | template: 63 | src: "{{ item }}" 64 | dest: ~{{ username }}/.{{ (item | splitext)[0] }} 65 | owner: "{{ username }}" 66 | group: "{{ username }}" 67 | with_items: 68 | - ansible.cfg.j2 69 | - vimrc.j2 70 | tags: 71 | - control_node 72 | - control 73 | - vim 74 | 75 | - name: Create lab inventory directory 76 | file: 77 | state: directory 78 | path: /home/{{ username }}/lightbulb/lessons/lab_inventory 79 | tags: 80 | - control_node 81 | - control 82 | 83 | - name: Put student inventory in proper spot 84 | copy: 85 | src: ./{{ username }}-instances.txt 86 | dest: "{{ control_node_inventory_path }}" 87 | owner: "{{ username }}" 88 | group: "{{ username }}" 89 | when: username in inventory_hostname 90 | tags: 91 | - control_node 92 | - control 93 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/control_node/templates/ansible.cfg.j2: -------------------------------------------------------------------------------- 1 | [defaults] 2 | connection = smart 3 | timeout = 60 4 | inventory = {{ control_node_inventory_path }} 5 | host_key_checking = False 6 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/control_node/templates/vimrc.j2: -------------------------------------------------------------------------------- 1 | set autoindent 2 | set tabstop=2 3 | set shiftwidth=2 4 | autocmd FileType yaml setlocal ai ts=2 sw=2 et 5 | autocmd FileType yml setlocal ai ts=2 sw=2 et 6 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/email/defaults/main.yml: -------------------------------------------------------------------------------- 1 | # sendgrid_user: 2 | # sendgrid_pass: 3 | # sendgrid_api_key: 4 | email: yes 5 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/email/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Send email to students with inventory attached 2 | delegate_to: localhost 3 | sendgrid: 4 | username: "{{ sendgrid_user | default(omit) }}" 5 | password: "{{ sendgrid_pass | default(omit) }}" 6 | api_key: "{{ sendgrid_api_key | default(omit) }}" 7 | subject: "[Ansible] Important Training Details" 8 | body: | 9 | Attached is the Ansible inventory to be used for training.
10 | Please check your ability to connect to each of the hosts via ssh.
11 |
12 | The username is '{{ item.username }}' and the password is '{{ admin_password }}'.
13 | If you have any issues connecting, please reply to this email to let me know.
14 | 15 | to_addresses: "{{ item.email }}" 16 | html_body: yes 17 | from_address: "{{ instructor_email }}" 18 | attachments: 19 | - "{{ item.username }}-instances.txt" 20 | with_items: "{{ users }}" 21 | when: email 22 | tags: 23 | - email 24 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/manage_ec2_instances/defaults/main.yml: -------------------------------------------------------------------------------- 1 | ec2_name_prefix: TRAINING 2 | ec2_region: us-east-1 3 | ec2_exact_count: 1 4 | ec2_wait: yes 5 | ec2_subnet: "172.16.0.0/16" 6 | ec2_subnet2: "172.17.0.0/16" 7 | 8 | ec2_lab_node_types: 9 | - name: ansible 10 | type: rhel7-tower 11 | 12 | - name: node1 13 | type: rhel7 14 | 15 | - name: node2 16 | type: rhel7 17 | 18 | - name: node3 19 | type: rhel7 20 | 21 | # - name: haproxy 22 | # type: rhel7 23 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/manage_ec2_instances/tasks/create.yml: -------------------------------------------------------------------------------- 1 | - name: Wait for instances to finish initializing 2 | pause: 3 | seconds: 90 4 | when: instances is changed 5 | tags: 6 | - always 7 | - provision 8 | 9 | - name: Add hosts to control_nodes group 10 | add_host: 11 | name: "{{ item.invocation.module_args.instance_tags.Name }}" 12 | ansible_host: "{{ item.tagged_instances[0].public_ip }}" 13 | ansible_user: "{{ ec2_login_names[item.item.1.type] }}" 14 | ansible_port: "{{ ssh_port | default('22') }}" 15 | groups: lab_hosts,control_nodes 16 | with_items: "{{ instances.results }}" 17 | when: "'ansible' in item.invocation.module_args.instance_tags.Name" 18 | changed_when: no 19 | tags: 20 | - always 21 | - provision 22 | 23 | - name: Add hosts to groups 24 | add_host: 25 | name: "{{ item.invocation.module_args.instance_tags.Name }}" 26 | ansible_host: "{{ item.tagged_instances[0].public_ip }}" 27 | ansible_user: "{{ ec2_login_names[item.item.1.type] }}" 28 | ansible_port: "{{ ssh_port | default('22') }}" 29 | groups: lab_hosts,managed_nodes 30 | with_items: "{{ instances.results }}" 31 | when: "'ansible' not in item.invocation.module_args.instance_tags.Name" 32 | changed_when: no 33 | tags: 34 | - always 35 | - provision 36 | 37 | - name: Wait for Ansible connection to all hosts 38 | wait_for_connection: 39 | delay: 0 40 | timeout: 400 41 | when: instances is changed 42 | delegate_to: "{{ item }}" 43 | loop: "{{ groups.lab_hosts }}" 44 | 45 | - name: Set local username to create on instances 46 | set_fact: 47 | username: "{{ item | regex_replace('.*-(\\w*)-\\w*$','\\1') }}" 48 | with_items: "{{ groups.lab_hosts }}" 49 | delegate_to: "{{ item }}" 50 | delegate_facts: yes 51 | tags: 52 | - always 53 | - provision 54 | 55 | - name: Generate student inventories 56 | template: 57 | src: instances.txt.j2 58 | dest: ./{{ item.username }}-instances.txt 59 | with_items: "{{ users }}" 60 | tags: 61 | - inventory 62 | - users 63 | - user_accounts 64 | 65 | - name: Generate instructor inventory 66 | template: 67 | src: instructor_inventory.j2 68 | dest: ./instructor_inventory.txt 69 | tags: 70 | - inventory 71 | - users 72 | - user_accounts 73 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/manage_ec2_instances/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - include_tasks: teardown.yml 2 | when: teardown 3 | 4 | - include_tasks: provision.yml 5 | when: not teardown 6 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/manage_ec2_instances/tasks/provision.yml: -------------------------------------------------------------------------------- 1 | - block: 2 | - name: Set EC2 security group type 3 | set_fact: 4 | ec2_security_group: insecure_all 5 | 6 | - name: Create EC2 security group 7 | ec2_group: 8 | name: "{{ ec2_security_group }}" 9 | description: all ports open 10 | region: "{{ ec2_region }}" 11 | vpc_id: "{{ ec2_vpc_id }}" 12 | rules: 13 | - proto: all 14 | cidr_ip: 0.0.0.0/0 15 | rules_egress: 16 | - proto: all 17 | cidr_ip: 0.0.0.0/0 18 | when: ec2_exact_count >= 1 19 | tags: 20 | - always 21 | - provision 22 | when: ec2_vpc_id is defined 23 | 24 | - block: 25 | - name: Create AWS VPC {{ ec2_name_prefix }}-vpc 26 | ec2_vpc_net: 27 | name: "{{ ec2_name_prefix }}-vpc" 28 | cidr_block: "{{ec2_subnet}}" 29 | region: "{{ ec2_region }}" 30 | tags: 31 | Username: "{{ lightbulb_user }}" 32 | Info: "Username that provisioned this-> {{ lightbulb_user }}" 33 | Lightbulb: "This was provisioned through the lightbulb provisioner" 34 | register: create_vpc 35 | until: create_vpc is not failed 36 | retries: 5 37 | tags: 38 | - provision 39 | 40 | - name: Create EC2 security group for VPC named {{ ec2_name_prefix }}-vpc 41 | ec2_group: 42 | name: "{{ ec2_name_prefix }}-insecure_all" 43 | description: all ports open 44 | region: "{{ ec2_region }}" 45 | vpc_id: "{{create_vpc.vpc.id}}" 46 | tags: 47 | Username: "{{ lightbulb_user }}" 48 | Info: "Username that provisioned this-> {{ lightbulb_user }}" 49 | Lightbulb: "This was provisioned through the lightbulb provisioner" 50 | rules: 51 | - proto: 47 52 | to_port: -1 53 | from_port: -1 54 | cidr_ip: 0.0.0.0/0 55 | - proto: tcp 56 | to_port: 443 57 | from_port: 443 58 | cidr_ip: 0.0.0.0/0 59 | - proto: icmp 60 | to_port: -1 61 | from_port: -1 62 | cidr_ip: 0.0.0.0/0 63 | - proto: tcp 64 | to_port: 80 65 | from_port: 80 66 | cidr_ip: 0.0.0.0/0 67 | - proto: tcp 68 | to_port: 22 69 | from_port: 22 70 | cidr_ip: 0.0.0.0/0 71 | rules_egress: 72 | - proto: all 73 | cidr_ip: 0.0.0.0/0 74 | when: ec2_exact_count >= 1 75 | tags: 76 | - provision 77 | 78 | - name: Create subnet for {{ ec2_name_prefix }}-vpc 79 | ec2_vpc_subnet: 80 | region: "{{ ec2_region }}" 81 | az: "{{ ec2_az }}" 82 | vpc_id: "{{ create_vpc.vpc.id }}" 83 | cidr: "{{ ec2_subnet }}" 84 | wait_timeout: 600 85 | resource_tags: 86 | Name: "{{ ec2_name_prefix }}-subnet" 87 | Username: "{{ lightbulb_user }}" 88 | Info: "Username that provisioned this-> {{ lightbulb_user }}" 89 | Lightbulb: "This was provisioned through the lightbulb provisioner" 90 | register: create_subnet 91 | until: create_subnet is not failed 92 | retries: 15 93 | tags: 94 | - provision 95 | 96 | - name: VPC internet gateway is present for {{ create_vpc.vpc.id }} 97 | ec2_vpc_igw: 98 | region: "{{ ec2_region }}" 99 | vpc_id: "{{ create_vpc.vpc.id }}" 100 | tags: 101 | Username: "{{ lightbulb_user }}" 102 | Info: "Username that provisioned this-> {{ lightbulb_user }}" 103 | lightbulb: "This was provisioned through the lightbulb provisioner" 104 | register: igw 105 | tags: 106 | - provision 107 | 108 | - name: VPC public subnet route table is present for {{ create_vpc.vpc.id }} 109 | ec2_vpc_route_table: 110 | region: "{{ ec2_region }}" 111 | vpc_id: "{{ create_vpc.vpc.id }}" 112 | subnets: 113 | - "{{ create_subnet.subnet.id }}" 114 | routes: 115 | - dest: 0.0.0.0/0 116 | gateway_id: "{{ igw.gateway_id }}" 117 | tags: 118 | Username: "{{ lightbulb_user }}" 119 | Info: "Username that provisioned this-> {{ lightbulb_user }}" 120 | Lightbulb: "This was provisioned through the lightbulb provisioner" 121 | register: routetable 122 | until: routetable is not failed 123 | retries: 5 124 | tags: 125 | - provision 126 | 127 | - name: Set variables for instance creation dynamically since VPC was not supplied by user 128 | set_fact: 129 | ec2_vpc_id: "{{ create_vpc.vpc.id }}" 130 | ec2_security_group: "{{ ec2_name_prefix }}-insecure_all" 131 | ec2_vpc_subnet_id: "{{ create_subnet.subnet.id }}" 132 | tags: 133 | - provision 134 | when: ec2_vpc_id is undefined 135 | 136 | - name: Create EC2 instances 137 | ec2: 138 | assign_public_ip: yes 139 | key_name: "{{ ec2_key_name }}" 140 | group: "{{ ec2_security_group }}" 141 | instance_type: "{{ ec2_instance_types[item.1.type].size }}" 142 | image: "{{ ec2_instance_types[item.1.type].ami_id }}" 143 | region: "{{ ec2_region }}" 144 | exact_count: "{{ ec2_exact_count }}" 145 | count_tag: 146 | Name: "{{ ec2_name_prefix }}-{{ item.0.username }}-{{ item.1.name }}" 147 | instance_tags: 148 | Name: "{{ ec2_name_prefix }}-{{ item.0.username }}-{{ item.1.name }}" 149 | Workshop: "{{ec2_name_prefix}}" 150 | Username: "{{ lightbulb_user }}" 151 | Info: "Username that provisioned this-> {{ lightbulb_user }}" 152 | Linklight: "This was provisioned through the lightbulb provisioner" 153 | wait: "{{ ec2_wait }}" 154 | vpc_subnet_id: "{{ ec2_vpc_subnet_id | default(omit) }}" 155 | volumes: 156 | - device_name: /dev/sda1 157 | volume_type: gp2 158 | volume_size: "{{ ec2_instance_types[item.1.type].disk_space }}" 159 | delete_on_termination: true 160 | with_nested: 161 | - "{{ users }}" 162 | - "{{ ec2_lab_node_types }}" 163 | register: instances 164 | tags: 165 | - always 166 | - provision 167 | 168 | - name: Include tasks only needed when creating instances 169 | include_tasks: create.yml 170 | when: ec2_exact_count >= 1 171 | tags: 172 | - provision 173 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/manage_ec2_instances/tasks/teardown.yml: -------------------------------------------------------------------------------- 1 | - name: grab facts for workshop 2 | ec2_instance_facts: 3 | region: "{{ ec2_region }}" 4 | filters: 5 | instance-state-name: running 6 | "tag:Workshop": "{{ec2_name_prefix}}" 7 | register: all_workshop_nodes 8 | 9 | - name: Destroy EC2 instances 10 | ec2: 11 | region: "{{ ec2_region }}" 12 | state: absent 13 | instance_ids: "{{ all_workshop_nodes.instances | map(attribute='instance_id') | list }}" 14 | register: result 15 | when: all_workshop_nodes.instances 16 | 17 | - name: Get the VPC ID for {{ ec2_name_prefix }} 18 | ec2_vpc_net_facts: 19 | filters: 20 | "tag:Name": "{{ ec2_name_prefix }}-vpc" 21 | region: "{{ ec2_region }}" 22 | register: vpc_net_facts 23 | 24 | - name: set variables for instance creation dynamically since VPC was not supplied by user 25 | set_fact: 26 | ec2_vpc_id: "{{vpc_net_facts.vpcs[0].id}}" 27 | ec2_security_group: "{{ ec2_name_prefix }}-insecure_all" 28 | when: vpc_net_facts.vpcs|length > 0 and ec2_security_group is undefined 29 | 30 | - name: Deleted EC2 security group for VPC vpc-{{ ec2_name_prefix }} 31 | ec2_group: 32 | name: "{{ec2_security_group}}" 33 | region: "{{ ec2_region }}" 34 | vpc_id: "{{ec2_vpc_id}}" 35 | state: absent 36 | register: delete_sg 37 | until: delete_sg is not failed 38 | retries: 50 39 | when: vpc_net_facts.vpcs|length > 0 40 | 41 | - name: Delete subnet for {{ ec2_name_prefix }}-vpc 42 | ec2_vpc_subnet: 43 | region: "{{ ec2_region }}" 44 | az: "{{ec2_az}}" 45 | vpc_id: "{{ec2_vpc_id}}" 46 | cidr: "{{ec2_subnet}}" 47 | state: absent 48 | when: vpc_net_facts.vpcs|length > 0 49 | 50 | - name: Ensure vpc internet gateway is deleted for vpc-{{ ec2_name_prefix }} 51 | ec2_vpc_igw: 52 | region: "{{ ec2_region }}" 53 | vpc_id: "{{ec2_vpc_id}}" 54 | state: absent 55 | when: vpc_net_facts.vpcs|length > 0 56 | 57 | - name: Grab route information for {{ ec2_name_prefix }} on {{ ec2_region }} 58 | ec2_vpc_route_table_facts: 59 | region: "{{ ec2_region }}" 60 | filters: 61 | vpc_id: "{{ec2_vpc_id}}" 62 | register: route_table_facts 63 | when: vpc_net_facts.vpcs|length > 0 64 | 65 | - name: VPC public subnet route table is deleted 66 | ec2_vpc_route_table: 67 | region: "{{ ec2_region }}" 68 | vpc_id: "{{ec2_vpc_id}}" 69 | route_table_id: "{{item.id}}" 70 | lookup: id 71 | state: absent 72 | with_items: "{{route_table_facts.route_tables}}" 73 | when: vpc_net_facts.vpcs|length > 0 and item.associations == [] 74 | 75 | - name: Delete AWS VPC {{ ec2_name_prefix }} 76 | ec2_vpc_net: 77 | name: "{{ ec2_name_prefix }}-vpc" 78 | cidr_block: "{{ ec2_subnet }}" 79 | region: "{{ ec2_region }}" 80 | state: absent 81 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/manage_ec2_instances/templates/instances.txt.j2: -------------------------------------------------------------------------------- 1 | [all:vars] 2 | ansible_user={{ item.username }} 3 | ansible_ssh_pass={{ admin_password }} 4 | {% if ssh_port is defined %} 5 | ansible_port={{ ssh_port }} 6 | {% endif %} 7 | 8 | [web] 9 | {% for grouper, list in instances.results|groupby('item') if grouper[0] == item %} 10 | {% for vm in list %} 11 | {% if 'ansible' not in vm.invocation.module_args.instance_tags.Name and 'haproxy' not in vm.invocation.module_args.instance_tags.Name%} 12 | {{ vm.invocation.module_args.instance_tags.Name | regex_replace('.*-(node)(\\d)', '\\1-\\2') }} ansible_host={{ vm.tagged_instances[0].public_ip }} 13 | {% endif %} 14 | {% endfor %} 15 | {% endfor %} 16 | 17 | [control] 18 | {% for grouper, list in instances.results|groupby('item') if grouper[0] == item %} 19 | {% for vm in list %} 20 | {% if 'ansible' in vm.invocation.module_args.instance_tags.Name %} 21 | {{ vm.invocation.module_args.instance_tags.Name | regex_replace('.*-([\\w]*)', '\\1') }} ansible_host={{ vm.tagged_instances[0].public_ip }} 22 | {% endif %} 23 | {% endfor %} 24 | {% endfor %} 25 | 26 | {# 27 | [haproxy] 28 | {% for grouper, list in instances.results|groupby('item') if grouper[0] == item %} 29 | {% for vm in list %} 30 | {% if 'haproxy' in vm.invocation.module_args.instance_tags.Name %} 31 | {{ vm.invocation.module_args.instance_tags.Name | regex_replace('.*-([\\w]*)', '\\1') }} ansible_host={{ vm.tagged_instances[0].public_ip }} 32 | {% endif %} 33 | {% endfor %} 34 | {% endfor %} 35 | #} 36 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/manage_ec2_instances/templates/instructor_inventory.j2: -------------------------------------------------------------------------------- 1 | [all:vars] 2 | {% if ssh_port is defined %} 3 | ansible_port={{ ssh_port }} 4 | {% endif %} 5 | 6 | {% for user in users %} 7 | [{{ user.username }}] 8 | {% for host in instances.results %} 9 | {% if user.username in host.invocation.module_args.instance_tags.Name %} 10 | {{ host.invocation.module_args.instance_tags.Name | regex_replace(ec2_name_prefix ~ '-','') }} ansible_host={{ hostvars[host.invocation.module_args.instance_tags.Name]['ansible_host'] }} ansible_user={{ ec2_login_names[host.item.1.type] }} 11 | {% endif %} 12 | {% endfor %} 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/manage_ec2_instances/vars/main.yml: -------------------------------------------------------------------------------- 1 | # --- Lookup tables --- # 2 | # Region specific AMIs, subnets, and VPCs 3 | ec2_regions: 4 | us-east-1: 5 | vpc: vpc-06c9a463 6 | subnet_id: subnet-a2169ed5 7 | key_name: "{{ ec2_key_name | default('training') }}" 8 | amis: 9 | centos7: ami-61bbf104 10 | centos7-tower: ami-877b9e91 11 | rhel7: ami-85241def 12 | rhel7-tower: ami-85241def 13 | ubuntu14: ami-feed08e8 14 | ubuntu16: ami-9dcfdb8a 15 | 16 | us-west-1: 17 | vpc: vpc-ce1f9aab 18 | subnet_id: subnet-25b9157c 19 | key_name: "{{ ec2_key_name | default('training') }}" 20 | amis: 21 | centos7: ami-af4333cf 22 | centos7-tower: ami-c04a00a0 23 | rhel7: ami-f88fc498 24 | rhel7-tower: ami-f88fc498 25 | ubuntu14: ami-6ebcec0e 26 | ubuntu16: ami-b05203d0 27 | 28 | eu-west-1: 29 | vpc: vpc-48141c2a 30 | subnet_id: subnet-70f9f012 31 | key_name: "{{ ec2_key_name | default('training') }}" 32 | amis: 33 | centos7: ami-af4333cf 34 | centos7-tower: ami-c04a00a0 35 | rhel7: ami-2b9d6c52 36 | rhel7-tower: ami-2b9d6c52 37 | ubuntu14: ami-6ebcec0e 38 | ubuntu16: ami-b05203d0 39 | 40 | ap-southeast-1: 41 | vpc: vpc-xxxxxxxx 42 | subnet_id: subnet-xxxxxxxx 43 | key_name: "{{ ec2_key_name | default('training') }}" 44 | amis: 45 | centos7: ami-7d2eab1e 46 | centos7-tower: ami-c7ed91a4 47 | rhel7: ami-dccc04bf 48 | rhel7-tower: ami-dccc04bf 49 | ubuntu14: ami-adb51dce 50 | ubuntu16: ami-87b917e4 51 | 52 | ap-southeast-2: 53 | vpc: vpc-xxxxxxxxa 54 | subnet_id: subnet-xxxxxxxx 55 | key_name: "{{ ec2_key_name | default('training') }}" 56 | amis: 57 | centos7: ami-34171d57 58 | centos7-tower: ami-01b45763 59 | rhel7: ami-286e4f4b 60 | rhel7-tower: ami-286e4f4b 61 | ubuntu14: ami-940e0bf7 62 | ubuntu16: ami-e6b58e85 63 | 64 | ap-south-1: 65 | vpc: vpc-xxxxxxxx 66 | subnet_id: subnet-xxxxxxxx 67 | key_name: "{{ ec2_key_name | default('training') }}" 68 | amis: 69 | centos7: ami-3c0e7353 70 | centos7-tower: ami-5b145434 71 | rhel7: ami-cdbdd7a2 72 | rhel7-tower: ami-cdbdd7a2 73 | ubuntu14: ami-533e4e3c 74 | ubuntu16: ami-dd3442b2 75 | 76 | ap-northeast-1: 77 | vpc: vpc-xxxxxxxx 78 | subnet_id: subnet-xxxxxxxx 79 | key_name: "{{ ec2_key_name | default('training') }}" 80 | amis: 81 | centos7: ami-29d1e34e 82 | centos7-tower: ami-0d05d46b 83 | rhel7: ami-a05854ce 84 | rhel7-tower: ami-a05854ce 85 | ubuntu14: ami-3995e55e 86 | ubuntu16: ami-18afc47f 87 | 88 | cn-north-1: 89 | vpc: vpc-xxxxxxxx 90 | subnet_id: subnet-xxxxxxxx 91 | key_name: "{{ ec2_key_name | default('training') }}" 92 | amis: 93 | centos7: ami-3d805750 94 | centos7-tower: ami-3d805750 95 | rhel7: ami-52d1183f 96 | rhel7-tower: ami-52d1183f 97 | ubuntu14: ami-0220b23b 98 | ubuntu16: ami-a6fc21cb 99 | 100 | # Instance types used for lab configurations 101 | ec2_instance_types: 102 | centos7: 103 | ami_id: "{{ ec2_regions[ec2_region].amis.centos7 }}" 104 | size: t2.micro 105 | os_type: linux 106 | disk_space: 10 107 | 108 | centos7-tower: 109 | ami_id: "{{ ec2_regions[ec2_region].amis['centos7-tower'] }}" 110 | size: t2.medium 111 | os_type: linux 112 | disk_space: 20 113 | 114 | # Look for owner 309956199498 to find official Red Hat AMIs 115 | rhel7: 116 | ami_id: "{{ ec2_regions[ec2_region].amis.rhel7 }}" 117 | size: t2.micro 118 | os_type: linux 119 | disk_space: 10 120 | 121 | rhel7-tower: 122 | ami_id: "{{ ec2_regions[ec2_region].amis['rhel7-tower'] }}" 123 | size: t2.medium 124 | os_type: linux 125 | disk_space: 20 126 | 127 | # Look at https://cloud-images.ubuntu.com/locator/ec2/ for Ubuntu AMIs 128 | ubuntu14: 129 | ami_id: "{{ ec2_regions[ec2_region].amis.ubuntu14 }}" 130 | size: t2.micro 131 | os_type: linux 132 | disk_space: 10 133 | 134 | ubuntu16: 135 | ami_id: "{{ ec2_regions[ec2_region].amis.ubuntu16 }}" 136 | size: t2.micro 137 | os_type: linux 138 | disk_space: 10 139 | 140 | # Login names used for SSH connections. These are baked in to the AMIs. 141 | ec2_login_names: 142 | rhel7-tower: ec2-user 143 | rhel7: ec2-user 144 | centos7-tower: centos 145 | centos7: centos 146 | ubuntu14: ubuntu 147 | ubuntu16: ubuntu 148 | 149 | 150 | # Backwards compatability 151 | types: "{{ ec2_lab_node_types }}" 152 | aws_key_name: "{{ ec2_key_name }}" 153 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/user_accounts/defaults/main.yml: -------------------------------------------------------------------------------- 1 | admin_password: LearnAnsible{{ lookup('pipe', 'date +%m%y')}} 2 | admin_password_hash: "{{ admin_password | password_hash(salt='sRvXWmR5BBwqRlih') }}" 3 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/roles/user_accounts/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Create User Group 2 | group: 3 | name: "{{ username }}" 4 | state: present 5 | tags: 6 | - user_accounts 7 | - users 8 | 9 | - name: Create User Account 10 | user: 11 | createhome: yes 12 | group: "{{ username }}" 13 | name: "{{ username }}" 14 | shell: /bin/bash 15 | state: present 16 | password: "{{ admin_password_hash }}" 17 | tags: 18 | - user_accounts 19 | - users 20 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/sample-users.yml: -------------------------------------------------------------------------------- 1 | users: 2 | - name: Luke Cage 3 | username: lcage 4 | email: lcage@marvel.com 5 | -------------------------------------------------------------------------------- /tools/aws_lab_setup/teardown_lab.yml: -------------------------------------------------------------------------------- 1 | - name: Destroy lab instances in AWS 2 | hosts: localhost 3 | connection: local 4 | become: no 5 | gather_facts: yes 6 | 7 | vars: 8 | ec2_exact_count: 0 9 | teardown: true 10 | ec2_wait: no 11 | 12 | roles: 13 | - manage_ec2_instances 14 | 15 | post_tasks: 16 | - name: Remove inventory files 17 | file: 18 | name: "{{ playbook_dir }}/*.txt" 19 | state: absent 20 | -------------------------------------------------------------------------------- /tools/inventory_import/README.md: -------------------------------------------------------------------------------- 1 | # Static Inventory Importer 2 | 3 | This playbook helps students import their local, static inventory into Ansible Tower. 4 | 5 | ## Usage 6 | 7 | This playbook users the tower-cli tool and it's associated Ansible modules to create an inventory, groups, and then hosts with a special type of loop: `with_inventory_hostnames` 8 | 9 | ### Pre-requisites 10 | 11 | In order for this play to work, you must have already completed the following: 12 | 13 | * The Ansible Tower install exercise 14 | * Logged in using the password you set for the admin user 15 | * Applied your license key 16 | 17 | ### Setup 18 | 19 | Assuming a standard setup of the Lightbulb environment -- meaning you've followed the guides here or an instructors directions -- the only item you need to adjust in `inventory_import.yml` is the value for `tower_host_password` on line 5. This is the same value that you set as your admin accounts password. 20 | 21 | ### Running the playbook 22 | 23 | Once you've modified the `tower_host_password` value, you can run the playbook normally as your student user: 24 | 25 | ```yaml 26 | [student1@~]$ansible-playbook lightbulb/tools/inventory_import/inventory_import.yml 27 | ``` 28 | 29 | Once that's done, you can check under the Inventory tab in Ansible Tower and you should now have 2 inventory groups: 30 | ![created inventory](./images/created_inventory.png) 31 | 32 | ## Next steps 33 | 34 | Tower-cli does not currently support creating hosts under a group, so they'll need to be moved individually to the appropriate group. 35 | 36 | Select the 'Ansible Lightbulb Lab' inventory, and begin moving the hosts to their respective groups by clicking the 'copy or move icon': 37 | ![move hosts](./images/move_host.png) 38 | 39 | Choose the 'web' group for nodes 1-3, and the 'control' group for the control node. The default behavior is to copy the hosts to groups, but you can choose move if desired. 40 | 41 | Once complete, you should be able to look at each group and see their associated hosts. Here's the web group as an example: 42 | ![modified group](./images/modified_group.png) 43 | -------------------------------------------------------------------------------- /tools/inventory_import/images/created_inventory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/tools/inventory_import/images/created_inventory.png -------------------------------------------------------------------------------- /tools/inventory_import/images/modified_group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/tools/inventory_import/images/modified_group.png -------------------------------------------------------------------------------- /tools/inventory_import/images/move_host.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/tools/inventory_import/images/move_host.png -------------------------------------------------------------------------------- /tools/inventory_import/inventory_import.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create an inventory, group, and hosts within Tower for the 'web' group nodes[1:3] 3 | hosts: localhost 4 | vars: 5 | tower_host_password: #Enter your password you setup for 'admin_password' when installing Tower 6 | pip_packages: 7 | - python-pip 8 | - python-devel 9 | tower_host_ip: 127.0.0.1 #Since Tower serves on localhost by default, this is sufficient for Lightbulb 10 | tower_host_user: admin #Admin is the default user for Lighbulb projects 11 | organization: "Default" #Default org setup by Tower Install 12 | inventory_name: "Ansible Lightbulb Lab" #Follows inventory_name in docs for Lightbulb 13 | group_name: 14 | - "web" 15 | - "control" 16 | 17 | tasks: 18 | - name: Install pip and ansible-tower-cli 19 | block: 20 | - name: Install pip packages 21 | yum: 22 | name: "{{ item }}" 23 | state: present 24 | with_items: "{{ pip_packages }}" 25 | - name: Install tower-cli 26 | pip: 27 | name: ansible-tower-cli 28 | become: yes 29 | 30 | - name: Create the Ansible Lightbulb inventory 31 | tower_inventory: 32 | name: "{{ inventory_name }}" 33 | description: "Generic Inventory" 34 | organization: "{{ organization }}" 35 | tower_host: "{{ tower_host_ip }}" 36 | tower_username: "{{ tower_host_user }}" 37 | tower_password: "{{ tower_host_password }}" 38 | state: present 39 | 40 | - name: Add tower group 41 | tower_group: 42 | name: "{{ item }}" 43 | description: "Generic group" 44 | inventory: "{{ inventory_name }}" 45 | tower_host: "{{ tower_host_ip }}" 46 | tower_username: "{{ tower_host_user }}" 47 | tower_password: "{{ tower_host_password }}" 48 | state: present 49 | with_items: "{{ group_name }}" 50 | 51 | - name: Add tower hosts 52 | tower_host: 53 | name: "{{item}}" 54 | variables: "ansible_host: {{ hostvars[item]['ansible_host'] }}" 55 | description: "{{ item }} from your static inventory file" 56 | inventory: "{{ inventory_name }}" 57 | tower_host: "{{ tower_host_ip }}" 58 | tower_username: "{{ tower_host_user }}" 59 | tower_password: "{{ tower_host_password }}" 60 | state: present 61 | with_inventory_hostnames: 62 | - web 63 | - control 64 | -------------------------------------------------------------------------------- /tools/lightbulb-from-tower/Job-Template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/tools/lightbulb-from-tower/Job-Template.png -------------------------------------------------------------------------------- /tools/lightbulb-from-tower/README.md: -------------------------------------------------------------------------------- 1 | # Controlling lightbulb from within Tower 2 | 3 | While this guide expects that the lightbulb environment is provisioned from the command line, it is actually possible to run the entire environment from within Tower. To do so, the following steps are required. 4 | 5 | ## Prepare Ansible environment on a Tower 6 | 7 | Lightbulb requires multiple libraries to be present. While `boto` and `boto3` are shipped as part of Tower, `passlib` is necessary. So it needs to be installed in the [Tower Ansible environment](http://docs.ansible.com/ansible-tower/latest/html/upgrade-migration-guide/virtualenv.html). 8 | 9 | ```bash 10 | $ ssh tower.example.com 11 | $ sudo -i 12 | # . /var/lib/awx/venv/ansible/bin/activate 13 | (ansible) # pip install passlib 14 | ``` 15 | 16 | ## Add credentials and project to Ansible Tower 17 | 18 | 1. Create [AWS credentials](http://docs.ansible.com/ansible-tower/latest/html/userguide/credentials.html#amazon-web-services): In Tower, go to "SETTINGS", "CREDENTIALS", click on "+ADD", enter a name, pick the "CREDENTIAL TYPE" "Amazon Web Services" and fill in the necessary details. 19 | 1. Create [machines credentials](http://docs.ansible.com/ansible-tower/latest/html/userguide/credentials.html#machine) containing your AWS SSH key. 20 | 1. Add a [new project](http://docs.ansible.com/ansible-tower/latest/html/userguide/projects.html#add-a-new-project), the Lightbulb Github repository, to Tower: Create a new Tower project, and add [lightbulb]() as source repository. 21 | 22 | ![Amazon web Services credentials](aws-credentials.png) 23 | 24 | ## Create Provision Job Template in Ansible Tower 25 | 26 | 1. Create a new [job template](http://docs.ansible.com/ansible-tower/latest/html/userguide/job_templates.html) with the Git repo as project. 27 | 1. Use an [inventory](http://docs.ansible.com/ansible-tower/latest/html/userguide/inventories.html) only containing localhost. 28 | 1. As credentials, use the Amazon Web Services and also the corresponding machines credentials created above. 29 | 1. The playbook needs to be `tools/aws_lab_setup/provision_lab.yml`. 30 | 1. In the "EXTRA VARIABLES" field, provide the variables necessary for the AWS provider, like list of users, `ec2_name_prefix`, and so on. 31 | 32 | ![Provision Job Template](Job-Template.png) 33 | 34 | ## Create Teardown Job Template in Ansible Tower 35 | 36 | 1. Copy the just created job template. 37 | 1. Change the playbook to `tools/aws_lab_setup/teardown_lab.yml`. 38 | 39 | That's already it. The proper function is ensured via the variables. 40 | -------------------------------------------------------------------------------- /tools/lightbulb-from-tower/aws-credentials.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible/lightbulb/750f58cc038592fe9b373337d101dd96a2e39fc6/tools/lightbulb-from-tower/aws-credentials.png -------------------------------------------------------------------------------- /workshops/README.md: -------------------------------------------------------------------------------- 1 | # Ansible Workshops 2 | 3 | The workshops are a collection of assignments for learning how to automate with Ansible. The workshops are introduced by the decks and are assigned to the students during the presentations. 4 | 5 | The workshops are set up as exercises to be done by the participants, and are most suitable for smaller audiences. 6 | 7 | ## Available Workshops 8 | 9 | Currently there are two workshops available: 10 | 11 | * [Ansible Engine](ansible_engine/README.md) 12 | * [Ansible Tower](ansible_tower/README.md) 13 | 14 | ## Additional information 15 | 16 | Additional information about Ansible, how to get started and where to proceed after this workshop, have a look at the following sources: 17 | 18 | * [Ansible Getting Started](http://docs.ansible.com/ansible/latest/intro_getting_started.html) 19 | -------------------------------------------------------------------------------- /workshops/ansible_engine/README.md: -------------------------------------------------------------------------------- 1 | # Ansible Workshops 2 | 3 | This workshop is part of lightbulb, and is a collection of assignments for learning how to automate with Ansible. The workshops are introduced by the decks and are assigned to the students during the presentations. 4 | 5 | The focus of this workshop is on the set up and usage of Ansible Engine. 6 | 7 | ## Ansible Engine Exercises 8 | 9 | * [Ansible installation](ansible_install) 10 | * [Ad-Hoc commands](adhoc_commands) 11 | * [Simple playbook](simple_playbook) 12 | * [Basic playbook](basic_playbook) 13 | * [Roles](roles) 14 | 15 | ## Additional information 16 | 17 | Additional information about Ansible, how to get started and where to proceed after this workshop, have a look at the following sources: 18 | 19 | * [Ansible Getting Started](http://docs.ansible.com/ansible/latest/intro_getting_started.html) 20 | -------------------------------------------------------------------------------- /workshops/ansible_engine/adhoc_commands/README.md: -------------------------------------------------------------------------------- 1 | # Workshop: Ad-Hoc Commands 2 | 3 | ## Topics Covered 4 | 5 | * Ansible Modules 6 | * Facts 7 | * Inventory and Groups 8 | * `ansible` command-line options: `-i -m -a -b --limit` 9 | 10 | ## What You Will Learn 11 | 12 | * How to test your Ansible configuration and connectivity 13 | * How to get and display Ansible facts 14 | * How to install a package 15 | 16 | ## The Assignment 17 | 18 | Perform the following operations using ad-hoc commands: 19 | 20 | 1. Test that Ansible is setup correctly to communicate with all hosts in your inventory using the `ping` module. 21 | 1. Fetch and display to STDOUT Ansible facts using the `setup` module. 22 | 1. Setup and enable the EPEL package repository on the hosts in the "web" group using the yum module. 23 | * CentOS systems use the latest `epel-release` package 24 | * RHEL systems should use [https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm](https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm) 25 | 26 | ### Extra Credit 27 | 28 | 1. Fetch and display only the "virtual" subset of facts for each host. 29 | 1. Fetch and display the value of fully qualified domain name (FQDN) of each host from their Ansible facts. 30 | 1. Display the uptime of all hosts using the `command` module. 31 | 1. Ping all hosts **except** the 'control' host using the `--limit` option 32 | 33 | ## Reference 34 | 35 | * `ansible --help` 36 | * [ping module](http://docs.ansible.com/ansible/ping_module.html) 37 | * [setup module](http://docs.ansible.com/ansible/setup_module.html) 38 | * [yum module](http://docs.ansible.com/ansible/yum_module.html) 39 | * [command module](http://docs.ansible.com/ansible/command_module.html) 40 | * [Introduction To Ad-Hoc Commands](http://docs.ansible.com/ansible/intro_adhoc.html) 41 | 42 | --- 43 | 44 | [Click Here to return to the Ansible Lightbulb - Ansible Engine Workshop](../README.md) 45 | -------------------------------------------------------------------------------- /workshops/ansible_engine/ansible_install/README.md: -------------------------------------------------------------------------------- 1 | # Workshop: Installing Ansible 2 | 3 | ## Topics Covered 4 | 5 | * Installing Ansible using pip or yum 6 | * Configuration file basics 7 | 8 | ## What You Will Learn 9 | 10 | * How easy it is to install and configure Ansible for yourself. 11 | 12 | ## The Assignment 13 | 14 | 1. Use pip to install the `ansible` package and its dependencies to you control machine. 15 | 1. Display the Ansible version and man page to STDOUT. 16 | 1. In `~/.ansible.cfg` file (create the file if it doesn't exist already) do the following: 17 | * Create a new directory `~/.ansible/retry-files` and set `retry_files_save_path` to it. 18 | * Set the Ansible system `forks` to 10 19 | 20 | ## Reference 21 | 22 | * [Ansible Installation](http://docs.ansible.com/ansible/intro_installation.html) 23 | * [Ansible Configuration File](http://docs.ansible.com/ansible/intro_configuration.html) 24 | 25 | --- 26 | 27 | [Click Here to return to the Ansible Lightbulb - Ansible Engine Workshop](../README.md) 28 | -------------------------------------------------------------------------------- /workshops/ansible_engine/basic_playbook/README.md: -------------------------------------------------------------------------------- 1 | # Workshop: Basic Playbook 2 | 3 | ## Topics Covered 4 | 5 | * Using `ansible-playbook` 6 | * YAML syntax basics 7 | * Basic Ansible playbook structure 8 | * Tasks and modules 9 | * Handlers 10 | * Variables 11 | * Loops 12 | 13 | ## What You Will Learn 14 | 15 | * How to use `ansible-playbook` 16 | * The basics of YAML syntax and Ansible playbook structure 17 | * How to deploy and configure an application onto a group of hosts 18 | 19 | ## Before You Begin 20 | 21 | If you're not familiar with the structure and authoring YAML files take a moment to read thru the Ansible [YAML Syntax](http://docs.ansible.com/ansible/YAMLSyntax.html) guide. 22 | 23 | ### NOTE 24 | 25 | You will need to assure each host in "web" group has setup the EPEL repository to find and install the nginx package with yum. 26 | 27 | ## The Assignment 28 | 29 | Create an Ansible playbook that will assure nginx is present, configured and running on all hosts in the "web" group: 30 | 31 | 1. Has variables for `nginx_test_message` and `nginx_webserver_port`. 32 | 1. Assures that the following yum packages are present on the each web host: 33 | * nginx 34 | * python-pip 35 | * python-devel 36 | * gcc 37 | 1. Assure that the uwsgi pip package is present on each host. 38 | 1. Generate a host-specific home page with the value of `nginx_test_message` for each host using the provided `index.html.j2` template. 39 | 1. Generate a configuration with the value of `nginx_webserver_port` for each host using the provided `nginx.conf.j2` template. 40 | 1. Assure that nginx is running on each host. 41 | 1. The playbook should restart nginx if the homepage or configuration file is altered. 42 | 43 | While developing the playbook use the `--syntax-check` to check your work and debug problems. Run your playbook in verbose mode using the `-v` switch to get more information on what Ansible is doing. Try `-vv` and `-vvv` for added verbosity. Also consider running `--check` to do a dry-run as you are developing. 44 | 45 | ### Extra Credit 46 | 47 | 1. Add a smoke test to your playbook using the `uri` module that test nginx is serving the sample home page. 48 | 1. Create a separate playbook that stops and removes nginx along with its configuration file and home page. 49 | 50 | ## Resources 51 | 52 | * [YAML Syntax](http://docs.ansible.com/ansible/YAMLSyntax.html) 53 | * [Intro to Ansible Playbooks](http://docs.ansible.com/ansible/playbooks_intro.html) 54 | * [Handlers](http://docs.ansible.com/ansible/playbooks_intro.html#handlers-running-operations-on-change) 55 | * [Variables](http://docs.ansible.com/ansible/playbooks_variables.html) 56 | * [Loops](http://docs.ansible.com/ansible/playbooks_loops.html) 57 | * [yum module](http://docs.ansible.com/ansible/yum_module.html) 58 | * [pip module](http://docs.ansible.com/ansible/pip_module.html) 59 | * [template module](http://docs.ansible.com/ansible/template_module.html) 60 | * [service module](http://docs.ansible.com/ansible/service_module.html) 61 | * [uri module](http://docs.ansible.com/ansible/uri_module.html) 62 | * [file module](http://docs.ansible.com/ansible/file_module.html) 63 | 64 | --- 65 | 66 | [Click Here to return to the Ansible Lightbulb - Ansible Engine Workshop](../README.md) 67 | -------------------------------------------------------------------------------- /workshops/ansible_engine/basic_playbook/resources/index.html.j2: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ansible: Automation for Everyone 5 | 6 | 30 | 31 | 32 |
33 | 34 |

{{ nginx_test_message }}

35 |
36 |
{{ inventory_hostname }}
Ansible by Red Hat
37 | 38 | 39 | -------------------------------------------------------------------------------- /workshops/ansible_engine/basic_playbook/resources/nginx.conf.j2: -------------------------------------------------------------------------------- 1 | # Based on nginx version: nginx/1.10.1 2 | # For more information on configuration, see: 3 | # * Official English Documentation: http://nginx.org/en/docs/ 4 | # * Official Russian Documentation: http://nginx.org/ru/docs/ 5 | 6 | user nginx; 7 | worker_processes auto; 8 | error_log /var/log/nginx/error.log; 9 | pid /run/nginx.pid; 10 | 11 | # Load dynamic modules. See /usr/share/nginx/README.dynamic. 12 | include /usr/share/nginx/modules/*.conf; 13 | 14 | events { 15 | worker_connections 1024; 16 | } 17 | 18 | http { 19 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 20 | '$status $body_bytes_sent "$http_referer" ' 21 | '"$http_user_agent" "$http_x_forwarded_for"'; 22 | 23 | access_log /var/log/nginx/access.log main; 24 | 25 | sendfile on; 26 | tcp_nopush on; 27 | tcp_nodelay on; 28 | keepalive_timeout 115; 29 | types_hash_max_size 2048; 30 | 31 | include /etc/nginx/mime.types; 32 | default_type application/octet-stream; 33 | 34 | # Load modular configuration files from the /etc/nginx/conf.d directory. 35 | # See http://nginx.org/en/docs/ngx_core_module.html#include 36 | # for more information. 37 | include /etc/nginx/conf.d/*.conf; 38 | 39 | server { 40 | listen {{ nginx_webserver_port }} default_server; 41 | listen [::]:{{ nginx_webserver_port }} default_server; 42 | server_name _; 43 | root /usr/share/nginx/html; 44 | 45 | # Load configuration files for the default server block. 46 | include /etc/nginx/default.d/*.conf; 47 | 48 | location / { 49 | } 50 | 51 | error_page 404 /404.html; 52 | location = /40x.html { 53 | } 54 | 55 | error_page 500 502 503 504 /50x.html; 56 | location = /50x.html { 57 | } 58 | } 59 | 60 | # Settings for a TLS enabled server. 61 | # 62 | # server { 63 | # listen 443 ssl http2 default_server; 64 | # listen [::]:443 ssl http2 default_server; 65 | # server_name _; 66 | # root /usr/share/nginx/html; 67 | # 68 | # ssl_certificate "/etc/pki/nginx/server.crt"; 69 | # ssl_certificate_key "/etc/pki/nginx/private/server.key"; 70 | # ssl_session_cache shared:SSL:1m; 71 | # ssl_session_timeout 10m; 72 | # ssl_ciphers HIGH:!aNULL:!MD5; 73 | # ssl_prefer_server_ciphers on; 74 | # 75 | # # Load configuration files for the default server block. 76 | # include /etc/nginx/default.d/*.conf; 77 | # 78 | # location / { 79 | # } 80 | # 81 | # error_page 404 /404.html; 82 | # location = /40x.html { 83 | # } 84 | # 85 | # error_page 500 502 503 504 /50x.html; 86 | # location = /50x.html { 87 | # } 88 | # } 89 | 90 | } 91 | 92 | -------------------------------------------------------------------------------- /workshops/ansible_engine/roles/README.md: -------------------------------------------------------------------------------- 1 | # Workshop: Roles 2 | 3 | ## Topics Covered 4 | 5 | * Roles 6 | 7 | ## What You Will Learn 8 | 9 | * How Ansible roles are developed and structured 10 | * How to use a role in a playbook 11 | 12 | ## The Assignment 13 | 14 | Your assignment is simple: refactor the Ansible playbook you've been developing into a role called "nginx-simple". 15 | 16 | This assignment should result in a drop in replacement that is portable and more modular. It does not add any new tasks or functionality. 17 | 18 | 1. Initialize your role with `ansible-galaxy init` in a new subdirectory `roles/`. 19 | 1. Refactor your existing basic playbook and associated resources into your role. 20 | 1. Create a new playbook that uses the role still targeting the "web" group. 21 | 1. Remove any empty files and directories from your role. 22 | 23 | ### Extra Credit 24 | 25 | 1. Refactor and merge the Nginx remove and uninstall playbook from the Basic Playbook Extra Credit assignments into your "nginx-simple" role. Create a separate playbook to execute that function of the role. 26 | 27 | ## Resources 28 | 29 | * [Ansible Roles](http://docs.ansible.com/ansible/playbooks_roles.html#roles) 30 | * [Create Roles (with ansible-galaxy)](http://docs.ansible.com/ansible/galaxy.html#create-roles) 31 | * [inculde_role](http://docs.ansible.com/ansible/include_role_module.html) 32 | 33 | --- 34 | 35 | [Click Here to return to the Ansible Lightbulb - Ansible Engine Workshop](../README.md) 36 | -------------------------------------------------------------------------------- /workshops/ansible_engine/simple_playbook/README.md: -------------------------------------------------------------------------------- 1 | # Workshop: Simple Playbook 2 | 3 | ## Topics Covered 4 | 5 | * Using `ansible-playbook` 6 | * YAML syntax basics 7 | * Basic Ansible playbook structure 8 | * Tasks and modules 9 | 10 | ## What You Will Learn 11 | 12 | * How to use `ansible-playbook` 13 | * The basics of YAML syntax and Ansible playbook structure 14 | 15 | ## Before You Begin 16 | 17 | If you're not familiar with the structure and authoring YAML files take a moment to read thru the Ansible [YAML Syntax](http://docs.ansible.com/ansible/YAMLSyntax.html) guide. 18 | 19 | ### NOTE 20 | 21 | You will need to assure each host in "web" group has setup the EPEL repository to find and install the nginx package with yum. 22 | 23 | ## The Assignment 24 | 25 | Create an Ansible playbook that targets members of the "web" group has the following state: 26 | 27 | 1. The nginx package is present using yum 28 | 1. Has the homepage that is provided in `resources/`. 29 | 1. Nginx is started on each host. 30 | 31 | While developing the playbook use the `--syntax-check` to check your work and debug problems. Run your playbook in verbose mode using the `-v` switch to get more information on what Ansible is doing. Try `-vv` and `-vvv` for added verbosity. Also consider running `--check` to do a dry-run as you are developing. 32 | 33 | ## Resources 34 | 35 | * [YAML Syntax](http://docs.ansible.com/ansible/YAMLSyntax.html) 36 | * [Intro to Ansible Playbooks](http://docs.ansible.com/ansible/playbooks_intro.html) 37 | * [yum module](http://docs.ansible.com/ansible/yum_module.html) 38 | * [file module](http://docs.ansible.com/ansible/file_module.html) 39 | * [service module](http://docs.ansible.com/ansible/service_module.html) 40 | 41 | --- 42 | 43 | [Click Here to return to the Ansible Lightbulb - Ansible Engine Workshop](../README.md) 44 | -------------------------------------------------------------------------------- /workshops/ansible_engine/simple_playbook/resources/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ansible: Automation for Everyone 5 | 6 | 30 | 31 | 32 |
33 | 34 |
35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /workshops/ansible_tower/README.md: -------------------------------------------------------------------------------- 1 | # Ansible Workshops 2 | 3 | This workshop is part of lightbulb, and is a collection of assignments for learning how to automate with Ansible. The workshops are introduced by the decks and are assigned to the students during the presentations. 4 | 5 | The focus of this workshop is on the set up and usage of Ansible Tower. 6 | 7 | ## Ansible Tower Exercises 8 | 9 | * [Tower installation](tower_install) 10 | * [Tower basic setup](tower_basic_setup) 11 | 12 | ## Additional information 13 | 14 | * [Ansible Tower User Guide](http://docs.ansible.com/ansible-tower/latest/html/userguide/index.html) 15 | * [Ansible Tower Administration Guide](http://docs.ansible.com/ansible-tower/latest/html/administration/index.html) 16 | -------------------------------------------------------------------------------- /workshops/ansible_tower/tower_basic_setup/README.md: -------------------------------------------------------------------------------- 1 | # Workshop: Ansible Tower Basic Setup 2 | 3 | ## Topics Covered 4 | 5 | * Credentials 6 | * Inventory 7 | * Users 8 | * Roles & Permissions 9 | * Projects 10 | * Job Templates 11 | * Running a Job (Playbook) 12 | 13 | ## What You Will Learn 14 | 15 | * Setting up a new instance of Tower with all the parts needed to run an existing Ansible playbook. 16 | 17 | ## Requirements 18 | 19 | * A running instance of Ansible Tower with sufficient permissions to create credentials, inventory sources, projects etc. 20 | 21 | ## Before You Begin 22 | 23 | Before doing this assignment you will need to perform a task you typical won't have to do when setting up Ansible Tower: manually enter your inventory. Commonly, Ansible Tower will be setup with one or more dynamic inventory sources such as AWS EC2 or vSphere or internal CMDB as a source of truth. Given the size and static nature of the Lightbulb lab environment, taking the time to setup and configure dynamic inventory is unnecessary. 24 | 25 | To make this process a bit easier, we now include a playbook to automatically import your inventory into tower to reduce the configuration needed. See the [Inventory Import README](../../tools/inventory_import/README.md) for additional details. 26 | 27 | If you choose to run this playbook and its next steps, you can skip items 1 & 3 in the below assignment. 28 | 29 | ## The Assignment 30 | 31 | NOTE: Create all new entities under the "Default" organization Ansible Tower create during setup unless noted otherwise. 32 | 33 | 1. Enter your lab inventory's groups and hosts into Tower. (See "Before You Begin" above.) 34 | 1. Create a machine credential called "Ansible Lab Machine" with the username and password for the hosts in your lab. 35 | 1. Create an inventory source called "Ansible Lightbulb Lab" and create the groups and hosts in your static inventory file. 36 | 1. Create a project called "Ansible Lightbulb Examples Project" with a SCM type of Git and URL of [https://github.com/ansible/lightbulb](https://github.com/ansible/lightbulb). You should also enable "Update on Launch". 37 | 1. Create a Job Template called "Nginx Role Example" with the machine credential, inventory and project you created in the previous steps. Select "examples/nginx-role/site.yml" as the playbook. 38 | 1. Execute the job template. Check that it runs without errors and the web servers are serving the home page. 39 | 1. Add an extra variables of `nginx_test_message` with a string like "Hello World" then run the "Nginx Role Example" job template again. Again, check that it executes without errors and the web servers are serving the home page with the new test message. 40 | 41 | ### Extra Credit 42 | 43 | Setup a self-service user simulation with the playbook 44 | 45 | * Create a "Normal" user with the name "someuser" 46 | * Assign the new user "Execute" permissions on the "Nginx Role Example" job template 47 | * Create a user survey on the job template that enables users to update the test message on the home page 48 | 49 | --- 50 | 51 | [Click Here to return to the Ansible Lightbulb - Ansible Tower Workshop](../README.md) 52 | -------------------------------------------------------------------------------- /workshops/ansible_tower/tower_install/README.md: -------------------------------------------------------------------------------- 1 | # Workshop: Installing Tower 2 | 3 | ## Topics Covered 4 | 5 | * Installing Ansible Tower 6 | * Importing a License File 7 | 8 | ## What You Will Learn 9 | 10 | * The installation process for a standalone instance of Ansible Tower using the bundled installer. 11 | 12 | ## The Assignment 13 | 14 | Install Ansible Tower on your controller machine using the [latest installer](http://releases.ansible.com/ansible-tower/setup/ansible-tower-setup-latest.tar.gz) and upload your license file. 15 | 16 | 1. Follow the [quick installation instructions](http://docs.ansible.com/ansible-tower/latest/html/quickinstall/index.html) to configure and run the single integrated installation of Ansible Tower on the control machine. 17 | 1. Sign into the Ansible Tower UI and upload the license file to enable the instance when prompted. Request a trial license if one hasn't been provided already. (Either trial license type will suffice for these lab assignments.) 18 | 19 | ## Extra Credit 20 | 21 | * After importing the license file, access the ping API endpoint using a browser. 22 | 23 | ## Reference 24 | 25 | * [Ansible Tower Software Releases Archive](http://releases.ansible.com/ansible-tower/) 26 | * [Ansible Tower Quick Installation Guide](http://docs.ansible.com/ansible-tower/latest/html/quickinstall/index.html) 27 | * [Import a License](http://docs.ansible.com/ansible-tower/latest/html/userguide/import_license.html) 28 | * [Ansible Tower Ping API Endpoint](http://docs.ansible.com/ansible-tower/3.0.3/html/towerapi/ping.html) 29 | 30 | --- 31 | 32 | [Click Here to return to the Ansible Lightbulb - Ansible Tower Workshop](../README.md) 33 | --------------------------------------------------------------------------------