diff --git a/.gitignore b/.gitignore index 399985f..e19aca8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ .vagrant/ -*.vdi/ -*.retry.yml/ \ No newline at end of file +*.vdi +*.retry.yml \ No newline at end of file diff --git a/ExamMaterial.md b/ExamMaterial.md new file mode 100644 index 0000000..e62ab3e --- /dev/null +++ b/ExamMaterial.md @@ -0,0 +1,79 @@ +# Exam Material + +A collection of information for the RHCE v8 exam. + +## Exam Page + +[Red Hat Certified Engineer (RHCE) exam | EX294](https://www.redhat.com/en/services/training/ex294-red-hat-certified-engineer-rhce-exam-red-hat-enterprise-linux-9) + +### Remote Exam Info + +[Getting Ready for your Red Hat Remote Exam - Red Hat Learning Community](https://learn.redhat.com/t5/Certification-Resources/Getting-Ready-for-your-Red-Hat-Remote-Exam/ba-p/33528) + +## Objectives + +[Red Hat Certification Exam Objectives by Version](https://training-lms.redhat.com/public_content/redhat/training/Red%20Hat%20Certification%20Exam%20Objectives%20by%20Version.pdf) + +### EX294V84K + ++ **Be able to perform all tasks expected of a Red Hat Certified System Administrator** + + Understand and use essential tools + + Operate running systems + + Configure local storage + + Create and configure file systems + + Deploy, configure, and maintain systems + + Manage users and groups + + Manage security ++ **Understand core components of Ansible** + + Inventories + + Modules + + Variables + + Facts + + Plays + + Playbooks + + Configuration files ++ **Install and configure an Ansible control node** + + Install required packages + + Create a static host inventory file + + Create a configuration file ++ **Configure Ansible managed nodes** + + Create and distribute SSH keys to managed nodes + + Configure privilege escalation on managed nodes + + Validate a working configuration using ad hoc Ansible commands ++ **Script administration tasks** + + Create simple shell scripts + + Create simple shell scripts that run ad hoc Ansible commands ++ **Create and use static inventories to define groups of hosts** ++ **Create Ansible plays and playbooks** + + Know how to work with commonly used Ansible modules + + Use variables to retrieve the results of running a command + + Use conditionals to control play execution + + Configure error handling + + Create playbooks to configure systems to a specified state ++ **Use Ansible modules for system administration tasks that work with:** + + Software packages and repositories + + Services + + Firewall rules + + File systems + + Storage devices + + File content + + Archiving + + Scheduled tasks + + Security + + Users and groups ++ **Create and use templates to create customized configuration files** ++ **Work with Ansible variables and facts** ++ **Create and work with roles** ++ **Download roles from an Ansible Galaxy and use them** ++ **Use Ansible Vault in playbooks to protect sensitive data** ++ **Use provided documentation to look up specific information about Ansible modules and commands** + +As with all Red Hat performance-based exams, configurations must persist after reboot without intervention. + +## Books + ++ [RHCE 8 prep book by Sander Van Vugt](https://www.amazon.com/RHCE-EX294-Cert-Guide-Certification/dp/0136872433) + +## Courses + ++ TBA diff --git a/README.md b/README.md index 40593c2..42821e3 100644 --- a/README.md +++ b/README.md @@ -1,149 +1,154 @@ # RHCE 8 Automated Practice Deployment -_Powered by Ansible and Vagrant_ -## Installation options below: -## macOS -_Gatekeeper will block virtualbox from installing. All you have to do is go into Security & Privacy of System Preferences and click Allow under the General tab and rerun installation._ -##### Install all at once with the command below: -``` -/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" && xcode-select --install &&brew install ansible ; brew install python ; brew cask install vagrant ; brew cask install VirtualBox ; brew cask install virtualbox-extension-pack ; vagrant plugin install vagrant-guest_ansible -``` +_Powered by Ansible and Vagrant_ -##### Alternatively, you can install everything individually below. -- [Install the Latest Version of Vagrant](https://www.vagrantup.com/downloads.html) - (`brew cask install vagrant`) - - Vagrant Plugin - `vagrant plugin install vagrant-guest_ansible` -- [Install the Latest Version of Virtualbox](https://www.virtualbox.org/wiki/Downloads) (`brew cask install VirtualBox`) - - Virtual Box Extension Pack (`brew cask install virtualbox-extension-pack`) +## Setting Up the Environment -##### Once the above software is installed. Do the following if you're running the environment on Mac: -1. Create a separate `~/bin` directory and `cd` to it. (The directory doesn't have to be ~/bin, it can be anything you want.) -2. Clone the environment repo to it with `git clone https://github.com/rdbreak/rhce8env.git` -3. Change to the `rhce8env` directory that is now in your `~/bin` directory. -4. Run `vagrant up` to deploy the environment (If the environment has a designated repo VM it will take the longest to deploy the first time only, this is because the repo system has all the packages available to the base release but will be quicker on subsequent deployments.) +See the [Setup](./Setup.md) page for details instructions on how to install and configure the environment. -## CentOS/RHEL/Manjaro/Arch - Install all at once by Copy/Pasting the below command into your terminal as root. -_NOTE - If it's been awhile since you've run yum update, do that first. Reboot if the kernel was updated. There may be some dependencies errors but don't be alarmed as this won't stop the environment from working._ +## Environment Info + +### Included systems + +- repo.ansi.example.com +- control.ansi.example.com +- node1.ansi.example.com +- node2.ansi.example.com +- node3.ansi.example.com +- node4.ansi.example.com + +### System Details + ++ control + - 192.168.55.200 + - Gateway - 192.168.55.1 + - DNS - 8.8.8.8 ++ node1 + - 192.168.55.201 + - Gateway - 192.168.55.1 + - DNS - 8.8.8.8 ++ node2 + - 192.168.55.202 + - Gateway - 192.168.55.1 + - DNS - 8.8.8.8 ++ node3 + - 192.168.55.203 + - Gateway - 192.168.55.1 + - DNS - 8.8.8.8 ++ node4 + - 192.168.55.204 + - Gateway - 192.168.55.1 + - DNS - 8.8.8.8 ++ repo + - 192.168.55.199 + - There is a Repo/AppStream available to use from `http://repo.ansi.example.com/BaseOS` and `http://repo.ansi.example.com/AppStream`. + +### Vagrant Commands to control the environment + +- `vagrant up` - Boots and provisions the environment +- `vagrant destroy -f` - Shuts down and destroys the environment +- `vagrant halt` - Only shuts down the environment VMs (can be booted up with `vagrant up`) +- `vagrant suspend` - Puts the VMs in a suspended state +- `vagrant resume` - Takes VMs out of a suspended state + +### Reseting the environment + +- `ansible-playbook playbooks/reset.yml` - Used for resetting the environment after attempting a practice exam. + +### Accessing the systems + +You can access the systems using `vagrant ssh`. + +Example: -_NOTE2 - If you receive an error for an ansible guest vagrant plugin, DO NOT worry, as there are two different plugins related to Ansible and only one needs to be installed._ -##### For CentoOS/RHEL7/Manjaro/Arch (Continue below for RHEL 8 specific script) -``` -systemctl stop packagekit; yum install -y epel-release && yum install -y git binutils gcc make patch libgomp glibc-headers glibc-devel kernel-headers kernel-devel dkms libvirt libvirt-devel ruby-devel libxslt-devel libxml2-devel libguestfs-tools-c ; mkdir ~/Vagrant ; cd ~/Vagrant ; curl -o vagrant_2.2.6_x86_64.rpm https://releases.hashicorp.com/vagrant/2.2.6/vagrant_2.2.6_x86_64.rpm && yum install -y vagrant_2.2.6_x86_64.rpm && vagrant plugin install vagrant-guest_ansible ; vagrant plugin install vagrant-guest-ansible ; wget -O /etc/yum.repos.d/virtualbox.repo wget http://download.virtualbox.org/virtualbox/rpm/rhel/virtualbox.repo ; yum install -y VirtualBox-6.0 && systemctl start packagekit -``` -##### If you're using RHEL 8, use the script below: -``` -systemctl stop packagekit; dnf -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm ; dnf install -y git binutils gcc make patch libgomp glibc-headers glibc-devel kernel-headers kernel-devel dkms libvirt libvirt-devel ruby-devel libxslt-devel libxml2-devel libguestfs-tools-c ; mkdir ~/Vagrant ; cd ~/Vagrant ; curl -o vagrant_2.2.19_x86_64.rpm https://releases.hashicorp.com/vagrant/2.2.19/vagrant_2.2.19_x86_64.rpm && dnf install -y vagrant_2.2.19_x86_64.rpm && vagrant plugin install vagrant-guest_ansible ; wget -O /etc/yum.repos.d/virtualbox.repo wget http://download.virtualbox.org/virtualbox/rpm/rhel/virtualbox.repo ; dnf install -y VirtualBox-6.1 && /usr/lib/virtualbox/vboxdrv.sh setup ; usermod -a -G vboxusers root ; systemctl start packagekit -``` -##### Also, install the Virtualbox extension pack below -- [Install the Virtual Box Extension Pack](https://www.virtualbox.org/wiki/Downloads) - -##### Once the above software is installed. Do the following if you're running the environment on Mac: -1. Create a separate `~/bin` directory and `cd` to it. (The directory doesn't have to be ~/bin, it can be anything you want.) -2. Clone the environment repo to it with `git clone https://github.com/rdbreak/rhce8env.git` -3. Change to the `rhcsa8env` directory that is now in your `~/bin` directory. -4. Run `vagrant up` to deploy the environment (If the environment has a designated repo VM it will take the longest to deploy the first time only, this is because the repo system has all the packages available to the base release but will be quicker on subsequent deployments.) - -## Windows/Fedora -- If using Windows: -- [Install the Latest Version of Vagrant](https://www.vagrantup.com/downloads.html) -- [Install the Latest Version of Virtualbox and Virtual Box Extension Pack](https://www.virtualbox.org/wiki/Downloads) -- Then install the following vagrant plugin via PowerShell as Administrator `vagrant plugin install vagrant-guest_ansible` -- If using Fedora, run `dnf update -y` to update your system, then run the script below as root to install everything at once: ``` -dnf -y install wget git binutils gcc make patch libgomp glibc-headers glibc-devel kernel-headers kernel-devel dkms libvirt libvirt-devel ruby-devel libxslt-devel libxml2-devel ; wget http://download.virtualbox.org/virtualbox/rpm/fedora/virtualbox.repo ; mv virtualbox.repo /etc/yum.repos.d/virtualbox.repo ; dnf install -y VirtualBox-6.0 ; usermod -a -G vboxusers ${USER} ; /usr/lib/virtualbox/vboxdrv.sh setup ; dnf -y install vagrant ; dnf remove -y rubygem-fog-core ; vagrant plugin install vagrant-guest_ansible +vagrant ssh node1 ``` -##### Once the above software is installed. Do the following if you're running the environment on Windows: -1. Create a separate `~/bin` directory and `cd` to it using the same PowerShell/Terminal as Administrator/Root.  (The directory doesn't have to be ~/bin, it can be anything you want.) -2. Use your browser of choice and navigate to https://github.com/rdbreak/rhce8env, press the green “Clone or download” button then the “Download ZIP” button. Or use Github Desktop (See below). -3. Once downloaded, unzip the file and move it to the directory you created earlier, `~/bin` in the above example. -4. Use PowerShell/Terminal as Administrator/Root again and cd to the `~/bin/rhce8env` directory then run `vagrant up` to deploy the environment. (If the environment has a designated repo VM it will take the longest to deploy the first time only, this is because the repo system has all the packages available to the base release but will be quicker on subsequent deployments.) +Or you can SSH to the VM IP using your systems built-in SSH client. ++ Username - `user` or `root` ('*user*' is the actual username) ++ Password - `password` ('*password*' is the actual password) -## Debian -_NOTE - If it's been awhile since you've run apt update, do that first. Reboot if the kernel was updated._ +Example: -##### Install all at once by Copy/Pasting the below command into your terminal as root. ``` -sudo snap install ruby ; sudo apt install ruby-bundler git -y; wget -c https://releases.hashicorp.com/vagrant/2.2.6/vagrant_2.2.6_x86_64.deb ; sudo dpkg -i vagrant_2.2.6_x86_64.deb ; wget -q https://www.virtualbox.org/download/oracle_vbox_2016.asc -O- | sudo apt-key add - ; wget -q https://www.virtualbox.org/download/oracle_vbox.asc -O- | sudo apt-key add - ; sudo add-apt-repository "deb http://download.virtualbox.org/virtualbox/debian bionic contrib"; sudo apt update; sudo apt install -y virtualbox-6.0 ; vagrant plugin install vagrant-guest_ansible +ssh user@192.168.55.201 ``` -##### Also, install the Virtualbox extension pack below -- [Virtual Box Extension Pack](https://www.virtualbox.org/wiki/Downloads) -##### Once the above software is installed. Do the following if you're running the environment on Linux: -1. Create a separate `~/bin` directory and `cd` to it. (The directory doesn't have to be ~/bin, it can be anything you want.) -2. Clone the environment repo to it with `git clone https://github.com/rdbreak/rhce8env.git` -3. Change to the `rhce8env` directory that is now in your `~/bin` directory. -4. Run `vagrant up` to deploy the environment (If the environment has a designated repo VM it will take the longest to deploy the first time only, this is because the repo system has all the packages available to the base release but will be quicker on subsequent deployments.) +To change into root you can use `sudo` or `sudo su` after logging in. + +>[!tip] +> Add the IP addresses to your local host file if you want to connect to the guest systems with the hostname. + +## Practice Exams + +A few practice exams are included. See the [Practice Exams](./practice_exams/README.md) page. + +## Additional Information -**Also, don't be spooked by any scary red font during the setup process. There are known issues that won't have a negative affect on the environment.** +You can also use the VirtualBox console to interact with the VMs or through a terminal. If you need to reset the root password, you would need to use the console. -_Now the deployment should be up and running!_ +I'm constantly making upgrades to the environments, so every once and awhile run `git pull` in the repo directory to pull down changes. If you're using Windows, it's recommended to use Github Desktop so you can easily pull changes that are made to the environment. + +The first time you run the vagrant up command, it will download the OS images for later use. In other words, it will take longest the first time around but will be faster when it is deployed again. You can run `vagrant destroy -f` to destroy your environment at anytime. **This will erase everything**. This environment is meant to be reusable, If you run the `vagrant up` command after destroying the environment, the OS image will already be downloaded and environment will deploy faster. Deployment should take around 15 minutes depending on your computer. + +### Recommended + +#### Install Github Desktop to make pulling down changes easier -## (Recommended) Install Github Desktop to make pulling down changes easier _NOTE this requires a free Github account_ -1. Navigate to https://desktop.github.com/ and download Github Desktop. + +1. Navigate to and download Github Desktop. 2. Create or sign in to your account. 3. Click "Clone a repository from the Internet" and enter "rdbreak/rhce8env" and choose a location then "Clone". 4. You are also able to easily pull changes when they're made available. -## Notable Vagrant Commands to control the environment: -- `ansible-playbook playbooks/reset.yml` - Used for resetting the environment after attempting the practice exam in the Red Hat Certs Slack workspace practice exam channel. -- `vagrant up` - Boots and provisions the environment -- `vagrant destroy -f` - Shuts down and destroys the environment -- `vagrant halt` - Only shuts down the environment VMs (can be booted up with `vagrant up`) -- `vagrant suspend` - Puts the VMs in a suspended state -- `vagrant resume` - Takes VMs out of a suspended state +#### Get latest Ansible with man pages and GUI on Control node -## Other Useful Information: -You can also use the VirtualBox console to interact with the VMs or through a terminal. If you need to reset the root password, you would need to use the console. I'm constantly making upgrades to the environments, so every once and awhile run `git pull` in the repo directory to pull down changes. If you're using Windows, it's recommended to use Github Desktop so you can easily pull changes that are made to the environment. The first time you run the vagrant up command, it will download the OS images for later use. In other words, it will take longest the first time around but will be faster when it is deployed again. You can run `vagrant destroy -f` to destroy your environment at anytime. **This will erase everything**. This environment is meant to be reuseable, If you run the `vagrant up` command after destroying the environment, the OS image will already be downloaded and environment will deploy faster. Deployment should take around 15 minutes depending on your computer. You shouldn't need to access the IPA server during your practice exams. Everything should be provided that you would normally need during an actual exam. Hope this helps in your studies! +You can register your control node (or all nodes) using free RHEL licenses that are provided with the Red Hat Developer Program (you can read more about it [here](https://developers.redhat.com/articles/faqs-no-cost-red-hat-enterprise-linux#)). By doing that, you will be able to run full updates on the node(s), get a GUI and install Ansible with man pages. -## Included systems: -- repo.ansi.example.com -- control.ansi.example.com -- node1.ansi.example.com -- node2.ansi.example.com -- node3.ansi.example.com -- node4.ansi.example.com - -## System Details: -> control -- 192.168.55.200 -- Gateway - 192.168.55.1 -- DNS - 8.8.8.8 -> node1 -- 192.168.55.201 -- Gateway - 192.168.55.1 -- DNS - 8.8.8.8 -> node2 -- 192.168.55.202 -- Gateway - 192.168.55.1 -- DNS - 8.8.8.8 -> node3 -- 192.168.55.203 -- Gateway - 192.168.55.1 -- DNS - 8.8.8.8 -> node4 -- 192.168.55.204 -- Gateway - 192.168.55.1 -- DNS - 8.8.8.8 - -There is a Repo/AppStream available to use from `http://repo.ansi.example.com/BaseOS` and `http://repo.ansi.example.com/AppStream` - -## Accessing the systems -Remember to add the IP addresses to your local host file if you want to connect to the guest systems with the hostname. -Username - user or root -Password - password - -- For root - use `sudo` or `sudo su` -Access example - `ssh user@192.168.55.201` or `vagrant ssh system` ++ Register for the [Red Hat Developer Program](https://developers.redhat.com/register) ++ Disable the 'ipa.repo' ++ Register the control node to your new developer account using `subscritption-manager` ++ Update and reboot the server ++ Install the 'Server with GUI' group package and change into 'graphical.target' ++ Update VirtualBox guest additions ++ Install Ansible and optionally jinja2 ++ Optionally: + + Enable the 'CodeReady Linux Builder' repo + + Install the EPEL repo ## Help -If you're having problems with the environment, please submit an issue by going to the `ISSUES` tab at the top. If you have more questions, looking for practice exams to use against this environment, or just looking for a fantastic Red Hat community to join to get your questions answered, check out the Red Hat Certs Slack Workspace. You can find the invite link at the top of this page next to the description. -## Known Issues: +If you're having problems with the environment, please submit an issue by going to the `ISSUES` tab at the top. If you have more questions, if you are looking for practice exams to use against this environment, or just looking for a fantastic Red Hat community to join to get your questions answered, check out the Red Hat Certs Slack Workspace. You can find the invite link in the 'About' section for this repo. + +### Known Issues -Running the 'vagrant up' environment build will fail If HyperV is installed on the Windows VirtualBox host. +#### VT-x is not available. (VERR_VMX_NO_VMX) + +Running the `vagrant up` environment build will fail If HyperV is installed on the Windows VirtualBox host. Error is usually "VT-x is not available. (VERR_VMX_NO_VMX)" or similar, when the script attempts to boot the first VM. -Resolution seems to be either remove HyperV, or preventing its hypervisor from starting with the command: -bcdedit /set hypervisorlaunchtype off, followed by a reboot. +Resolution seems to be either remove HyperV, or preventing its hypervisor from starting with the command below followed by a reboot: + +``` +bcdedit /set hypervisorlaunchtype off +``` + +#### Could not create the medium storage unit (VERR_ALREADY_EXISTS) + +The following error might appear when re-creating one or more VMs in VirtualBox: + +``` +Stderr: 0%...VBOX_E_FILE_ERROR +VBoxManage: error: Failed to create medium +VBoxManage: error: Could not create the medium storage unit 'rhce8env/disk-0-4.vdi'. +VBoxManage: error: VDI: cannot create image 'rhce8env/disk-0-4.vdi' (VERR_ALREADY_EXISTS) +``` + +If you have VirtualBox Manager open, check the disks in the 'Media' section and you might notice that a disk for a deleted VM is still listed. If the file itself doesn't exist, close the VirtualBox Manager and try running `vagrant up` again. + +## Exam Material + +See the [Exam Material](./ExamMaterial.md) page. diff --git a/Setup.md b/Setup.md new file mode 100644 index 0000000..6c9849f --- /dev/null +++ b/Setup.md @@ -0,0 +1,175 @@ +# Setting Up the Environment + +Follow the instructions below to setup the lab environment on your machine. We will be installing the requirements, then cloning this repo and initializing the VMs. + +## Install the Required Software + +### macOS + +_Gatekeeper will block virtualbox from installing. All you have to do is go into Security & Privacy of System Preferences and click Allow under the General tab and rerun installation._ + +Install all at once with the command below: + +``` +/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" && xcode-select --install &&brew install ansible ; brew install python ; brew cask install vagrant ; brew cask install VirtualBox ; brew cask install virtualbox-extension-pack ; vagrant plugin install vagrant-guest_ansible +``` + +Alternatively, you can install everything individually below: + +- [Install the Latest Version of Vagrant](https://www.vagrantup.com/downloads.html) - (`brew cask install vagrant`) + - Vagrant Plugin - `vagrant plugin install vagrant-guest_ansible` +- [Install the Latest Version of Virtualbox](https://www.virtualbox.org/wiki/Downloads) (`brew cask install VirtualBox`) + - Virtual Box Extension Pack (`brew cask install virtualbox-extension-pack`) + +### Linux + +> [!IMPORTANT] +> + If it's been awhile since you've run an update, do that first. Reboot if the kernel was updated. There may be some dependencies errors but don't be alarmed as this won't stop the environment from working. +> + If you receive an error for an Ansible guest vagrant plugin, DO NOT worry, as there are two different plugins related to Ansible and only one needs to be installed. + +#### RHEL7 - CentOS7 + +Install the required software: + +```bash +{ + systemctl stop packagekit + yum install -y epel-release && yum install -y git binutils gcc make patch libgomp glibc-headers glibc-devel kernel-headers kernel-devel dkms libvirt libvirt-devel ruby-devel libxslt-devel libxml2-devel libguestfs-tools-c + mkdir ~/Vagrant + cd ~/Vagrant + curl -o vagrant_2.2.6_x86_64.rpm https://releases.hashicorp.com/vagrant/2.2.6/vagrant_2.2.6_x86_64.rpm && yum install -y vagrant_2.2.6_x86_64.rpm && vagrant plugin install vagrant-guest_ansible + vagrant plugin install vagrant-guest-ansible + wget -O /etc/yum.repos.d/virtualbox.repo wget http://download.virtualbox.org/virtualbox/rpm/rhel/virtualbox.repo + yum install -y VirtualBox-6.0 && systemctl start packagekit +} +``` + +Also, install the VirtualBox extension pack below: + +- [Virtual Box Extension Pack](https://www.virtualbox.org/wiki/Downloads) + +#### RHEL8 + +Install the required software: + +```bash +{ + systemctl stop packagekit + dnf -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm + dnf install -y git binutils gcc make patch libgomp glibc-headers glibc-devel kernel-headers kernel-devel dkms libvirt libvirt-devel ruby-devel libxslt-devel libxml2-devel libguestfs-tools-c + mkdir ~/Vagrant + cd ~/Vagrant + curl -o vagrant_2.2.19_x86_64.rpm https://releases.hashicorp.com/vagrant/2.2.19/vagrant_2.2.19_x86_64.rpm && dnf install -y vagrant_2.2.19_x86_64.rpm && vagrant plugin install vagrant-guest_ansible + wget -O /etc/yum.repos.d/virtualbox.repo + wget http://download.virtualbox.org/virtualbox/rpm/rhel/virtualbox.repo + dnf install -y VirtualBox-6.1 && /usr/lib/virtualbox/vboxdrv.sh setup + usermod -a -G vboxusers root + systemctl start packagekit +} +``` + +Also, install the Virtualbox extension pack below: + +- [Virtual Box Extension Pack](https://www.virtualbox.org/wiki/Downloads) + +#### Arch / Manjaro + +Install the required software: + +```bash +{ + sudo /usr/bin/pacman -Sy + sudo /usr/bin/pacman -S --needed ansible virtualbox virtualbox-host-modules-arch virtualbox-guest-iso vagrant libvirt +} +``` + +Also, install the Virtualbox extension pack from the AUR: + ++ `virtualbox-ext-oracle` + +#### Fedora + +Run `dnf update -y` to update your system, then run the script below as root to install everything at once: + +```bash +{ + dnf -y install wget git binutils gcc make patch libgomp glibc-headers glibc-devel kernel-headers kernel-devel dkms libvirt libvirt-devel ruby-devel libxslt-devel libxml2-devel + wget http://download.virtualbox.org/virtualbox/rpm/fedora/virtualbox.repo + mv virtualbox.repo /etc/yum.repos.d/virtualbox.repo + dnf install -y VirtualBox-6.0 + usermod -a -G vboxusers ${USER} + /usr/lib/virtualbox/vboxdrv.sh setup + dnf -y install vagrant + dnf remove -y rubygem-fog-core + vagrant plugin install vagrant-guest_ansible +} +``` + +Also, install the Virtualbox extension pack below: + +- [Install the Virtual Box Extension Pack](https://www.virtualbox.org/wiki/Downloads) + +#### Debian + +_NOTE - If it's been awhile since you've run apt update, do that first. Reboot if the kernel was updated._ + +Install the required software (as root): + +```bash +{ + sudo snap install ruby + sudo apt install ruby-bundler git -y + wget -c https://releases.hashicorp.com/vagrant/2.2.6/vagrant_2.2.6_x86_64.deb + sudo dpkg -i vagrant_2.2.6_x86_64.deb + wget -q https://www.virtualbox.org/download/oracle_vbox_2016.asc -O- | sudo apt-key add - + wget -q https://www.virtualbox.org/download/oracle_vbox.asc -O- | sudo apt-key add - + sudo add-apt-repository "deb http://download.virtualbox.org/virtualbox/debian bionic contrib" + sudo apt update + sudo apt install -y virtualbox-6.0 + vagrant plugin install vagrant-guest_ansible +} +``` + +Also, install the Virtualbox extension pack below: + +- [Virtual Box Extension Pack](https://www.virtualbox.org/wiki/Downloads) + +### Windows + +Follow the steps below: + +- [Install the Latest Version of Vagrant](https://www.vagrantup.com/downloads.html) +- [Install the Latest Version of Virtualbox and Virtual Box Extension Pack](https://www.virtualbox.org/wiki/Downloads) +- Then install the following vagrant plugin via PowerShell as Administrator `vagrant plugin install vagrant-guest_ansible` + +## Initialize and Start the Environment + +Once the required software is installed, do the following: + +### macOS + +1. Create a separate `~/bin` directory and `cd` to it. (The directory doesn't have to be ~/bin, it can be anything you want.) +2. Clone the environment repo to it with `git clone https://github.com/rdbreak/rhce8env.git` +3. Change to the `rhce8env` directory that is now in your `~/bin` directory. +4. Run `vagrant up` to deploy the environment (If the environment has a designated repo VM it will take the longest to deploy the first time only, this is because the repo system has all the packages available to the base release but will be quicker on subsequent deployments.) + +### Linux + +1. Create a separate `~/bin` directory and `cd` to it. (The directory doesn't have to be ~/bin, it can be anything you want.) +2. Clone the environment repo to it with `git clone https://github.com/rdbreak/rhce8env.git` +3. Change to the `rhcsa8env` directory that is now in your `~/bin` directory. +4. Run `vagrant up` to deploy the environment (If the environment has a designated repo VM it will take the longest to deploy the first time only, this is because the repo system has all the packages available to the base release but will be quicker on subsequent deployments.) + +### Windows + +1. Create a separate `~/bin` directory and `cd` to it using the same PowerShell/Terminal as Administrator/Root.  (The directory doesn't have to be ~/bin, it can be anything you want.) +2. Use your browser of choice and navigate to , press the green “Clone or download” button then the “Download ZIP” button. Or use Github Desktop (See below). +3. Once downloaded, unzip the file and move it to the directory you created earlier, `~/bin` in the above example. +4. Use PowerShell/Terminal as Administrator/Root again and cd to the `~/bin/rhce8env` directory then run `vagrant up` to deploy the environment. (If the environment has a designated repo VM it will take the longest to deploy the first time only, this is because the repo system has all the packages available to the base release but will be quicker on subsequent deployments.) + +--- + +**_The deployment should be up and running!_** + +>[!NOTE] +> Don't be spooked by any scary red font during the setup process. There are known issues that won't have a negative affect on the environment. diff --git a/Vagrantfile b/Vagrantfile index c996dbb..74bbe37 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -6,135 +6,166 @@ file_to_disk3 = './disk-0-3.vdi' file_to_disk4 = './disk-0-4.vdi' file_to_disk5 = './disk-1-3.vdi' Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| -# Use same SSH key for each machine -config.ssh.insert_key = false -config.vm.box_check_update = false - -# Repo -config.vm.define "repo" do |repo| - - repo.vm.box = "rdbreak/rhel8repo" - repo.vm.provider "virtualbox" do |repo| - repo.memory = "1024" - unless File.exist?(file_to_disk5) - repo.customize ['createhd', '--filename', file_to_disk5, '--variant', 'Standard', '--size', 2 * 1024] - repo.customize ['storagectl', :id, '--name', 'SATA Controller', '--add', 'sata', '--portcount', 1] - repo.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 1, '--device', 0, '--type', 'hdd', '--medium', file_to_disk5] - end + # Use same SSH key for each machine + config.ssh.insert_key = false + config.vm.box_check_update = false + + #-- Repo --------------------------------------------------------------------- + config.vm.define "repo" do |repo| + repo.vm.box = "rdbreak/rhel8repo" + repo.vm.provider "virtualbox" do |repo| + repo.memory = "1024" + unless File.exist?(file_to_disk5) + repo.customize ['createhd', '--filename', file_to_disk5, '--variant', 'Standard', '--size', 1 * 1024] + repo.customize ['storagectl', :id, '--name', 'SATA Controller', '--add', 'sata', '--portcount', 1] + repo.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 1, '--device', 0, '--type', 'hdd', '--medium', file_to_disk5] + end + end + repo.vm.provision :shell, :inline => "rm -f /EMPTY" + repo.vm.provision :shell, :inline => "sudo sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config; sudo systemctl restart sshd;" + repo.vm.provision :shell, :inline => "yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm -y; sudo yum install -y sshpass python3-pip python3-devel httpd sshpass vsftpd createrepo" + repo.vm.provision :shell, :inline => "python3 -m pip install -U pip ; python3 -m pip install pexpect ; python3 -m pip install ansible" + repo.vm.synced_folder ".", "/vagrant", type: "rsync", rsync__exclude: [".git/", "*.vdi"] + repo.vm.network "private_network", ip: "192.168.55.199" + + # Run ansible on creation + repo.vm.provision :ansible_local do |ansible| + ansible.playbook = "/vagrant/playbooks/build-nodes.yml" + ansible.install = false + ansible.compatibility_mode = "2.0" + ansible.inventory_path = "/vagrant/inventory/hosts.ini" + ansible.config_file = "/vagrant/ansible.cfg" + ansible.limit = "repo" + end end - repo.vm.provision :shell, :inline => "pvs | grep '/dev/sdb' && echo 'The disk was already expanded!' || (pvcreate /dev/sdb; vgextend rhel_rhel8 /dev/sdb; lvextend -l +100%FREE /dev/rhel_rhel8/root; xfs_growfs /dev/rhel_rhel8/root)" - - repo.vm.provision :shell, :inline => "sudo sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config; sudo systemctl restart sshd;", run: "always" - repo.vm.provision :shell, :inline => "yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm -y; sudo yum install -y sshpass python3-pip python3-devel httpd sshpass vsftpd createrepo", run: "always" - repo.vm.provision :shell, :inline => " python3 -m pip install -U pip ; python3 -m pip install pexpect; python3 -m pip install ansible", run: "always" - repo.vm.synced_folder ".", "/vagrant", type: "rsync", rsync__exclude: ".git/" - repo.vm.network "private_network", ip: "192.168.55.199" -end - -# Node 1 -config.vm.define "node1" do |node1| - node1.vm.box = "rdbreak/rhel8node" -# node1.vm.hostname = "node1.ansi.example.com" - node1.vm.network "private_network", ip: "192.168.55.201" - node1.vm.synced_folder ".", "/vagrant", type: "rsync", rsync__exclude: [".git/", "*.vdi"] - node1.vm.provider "virtualbox" do |node1| - node1.memory = "1024" - - unless File.exist?(file_to_disk1) - node1.customize ['createhd', '--filename', file_to_disk1, '--variant', 'Fixed', '--size', 2 * 1024] - node1.customize ['storagectl', :id, '--name', 'SATA Controller', '--add', 'sata', '--portcount', 2] - node1.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 1, '--device', 0, '--type', 'hdd', '--medium', file_to_disk1] + + #-- Node 1 ------------------------------------------------------------------- + config.vm.define "node1" do |node1| + node1.vm.box = "rdbreak/rhel8node" + node1.vm.network "private_network", ip: "192.168.55.201" + node1.vm.synced_folder ".", "/vagrant", type: "rsync", rsync__exclude: [".git/", "*.vdi"] + node1.vm.provider "virtualbox" do |node1| + node1.memory = "1024" + + # Create the secondary disk + unless File.exist?(file_to_disk1) + node1.customize ['createhd', '--filename', file_to_disk1, '--variant', 'Fixed', '--size', 2 * 1024] + node1.customize ['storagectl', :id, '--name', 'SATA Controller', '--add', 'sata', '--portcount', 2] + node1.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 1, '--device', 0, '--type', 'hdd', '--medium', file_to_disk1] end + end + + # Run ansible on creation + node1.vm.provision :ansible_local do |ansible| + ansible.playbook = "/vagrant/playbooks/build-nodes.yml" + ansible.install = true + ansible.compatibility_mode = "2.0" + ansible.inventory_path = "/vagrant/inventory/hosts.ini" + ansible.config_file = "/vagrant/ansible.cfg" + ansible.limit = "node1" + end end - - node1.vm.provision "shell", inline: <<-SHELL - yes| sudo mkfs.ext4 /dev/sdb - SHELL - node1.vm.synced_folder ".", "/vagrant" - end - -# Node 2 -config.vm.define "node2" do |node2| - node2.vm.box = "rdbreak/rhel8node" -# node2.vm.hostname = "node2.ansi.example.com" - node2.vm.network "private_network", ip: "192.168.55.202" - node2.vm.synced_folder ".", "/vagrant", type: "rsync", rsync__exclude: [".git/", "*.vdi"] - node2.vm.provider "virtualbox" do |node2| - node2.memory = "1024" - - unless File.exist?(file_to_disk2) - node2.customize ['createhd', '--filename', file_to_disk2, '--variant', 'Fixed', '--size', 2 * 1024] - node2.customize ['storagectl', :id, '--name', 'SATA Controller', '--add', 'sata', '--portcount', 2] - node2.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 1, '--device', 0, '--type', 'hdd', '--medium', file_to_disk2] + + #-- Node 2 ------------------------------------------------------------------- + config.vm.define "node2" do |node2| + node2.vm.box = "rdbreak/rhel8node" + node2.vm.network "private_network", ip: "192.168.55.202" + node2.vm.synced_folder ".", "/vagrant", type: "rsync", rsync__exclude: [".git/", "*.vdi"] + + node2.vm.provider "virtualbox" do |node2| + node2.memory = "1024" + + unless File.exist?(file_to_disk2) + node2.customize ['createhd', '--filename', file_to_disk2, '--variant', 'Fixed', '--size', 2 * 1024] + node2.customize ['storagectl', :id, '--name', 'SATA Controller', '--add', 'sata', '--portcount', 2] + node2.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 1, '--device', 0, '--type', 'hdd', '--medium', file_to_disk2] end - end - - node2.vm.provision "shell", inline: <<-SHELL - yes| sudo mkfs.ext4 /dev/sdb - SHELL - node2.vm.synced_folder ".", "/vagrant" -end - -# Node 3 -config.vm.define "node3" do |node3| - node3.vm.box = "rdbreak/rhel8node" -# node3.vm.hostname = "node3.ansi.example.com" - node3.vm.network "private_network", ip: "192.168.55.203" - node3.vm.synced_folder ".", "/vagrant", type: "rsync", rsync__exclude: [".git/", "*.vdi"] - node3.vm.provider "virtualbox" do |node3| - node3.memory = "512" - - unless File.exist?(file_to_disk3) - node3.customize ['createhd', '--filename', file_to_disk3, '--variant', 'Fixed', '--size', 2 * 1024] - node3.customize ['storagectl', :id, '--name', 'SATA Controller', '--add', 'sata', '--portcount', 2] - node3.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 1, '--device', 0, '--type', 'hdd', '--medium', file_to_disk3] + end + + # Run ansible on creation + node2.vm.provision :ansible_local do |ansible| + ansible.playbook = "/vagrant/playbooks/build-nodes.yml" + ansible.install = true + ansible.compatibility_mode = "2.0" + ansible.inventory_path = "/vagrant/inventory/hosts.ini" + ansible.config_file = "/vagrant/ansible.cfg" + ansible.limit = "node2" + end + end + + #-- Node 3 ------------------------------------------------------------------- + config.vm.define "node3" do |node3| + node3.vm.box = "rdbreak/rhel8node" + node3.vm.network "private_network", ip: "192.168.55.203" + node3.vm.synced_folder ".", "/vagrant", type: "rsync", rsync__exclude: [".git/", "*.vdi"] + + node3.vm.provider "virtualbox" do |node3| + node3.memory = "512" + + unless File.exist?(file_to_disk3) + node3.customize ['createhd', '--filename', file_to_disk3, '--variant', 'Fixed', '--size', 2 * 1024] + node3.customize ['storagectl', :id, '--name', 'SATA Controller', '--add', 'sata', '--portcount', 2] + node3.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 1, '--device', 0, '--type', 'hdd', '--medium', file_to_disk3] end + end + + # Run ansible on creation + node3.vm.provision :ansible_local do |ansible| + ansible.playbook = "/vagrant/playbooks/build-nodes.yml" + ansible.install = true + ansible.compatibility_mode = "2.0" + ansible.inventory_path = "/vagrant/inventory/hosts.ini" + ansible.config_file = "/vagrant/ansible.cfg" + ansible.limit = "node3" + end end - - node3.vm.provision "shell", inline: <<-SHELL - yes| sudo mkfs.ext4 /dev/sdb - SHELL - node3.vm.synced_folder ".", "/vagrant" -end - -# Node 4 -config.vm.define "node4" do |node4| - node4.vm.box = "rdbreak/rhel8node" -# node4.vm.hostname = "node4.ansi.example.com" - node4.vm.network "private_network", ip: "192.168.55.204" - node4.vm.synced_folder ".", "/vagrant", type: "rsync", rsync__exclude: [".git/", "*.vdi"] - node4.vm.provider "virtualbox" do |node4| - node4.memory = "512" - - unless File.exist?(file_to_disk4) - node4.customize ['createhd', '--filename', file_to_disk4, '--variant', 'Fixed', '--size', 2 * 1024] - node4.customize ['storagectl', :id, '--name', 'SATA Controller', '--add', 'sata', '--portcount', 2] - node4.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 1, '--device', 0, '--type', 'hdd', '--medium', file_to_disk4] + + #-- Node 4 ------------------------------------------------------------------- + config.vm.define "node4" do |node4| + node4.vm.box = "rdbreak/rhel8node" + node4.vm.network "private_network", ip: "192.168.55.204" + node4.vm.synced_folder ".", "/vagrant", type: "rsync", rsync__exclude: [".git/", "*.vdi"] + node4.vm.provider "virtualbox" do |node4| + node4.memory = "512" + + unless File.exist?(file_to_disk4) + node4.customize ['createhd', '--filename', file_to_disk4, '--variant', 'Fixed', '--size', 2 * 1024] + node4.customize ['storagectl', :id, '--name', 'SATA Controller', '--add', 'sata', '--portcount', 2] + node4.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 1, '--device', 0, '--type', 'hdd', '--medium', file_to_disk4] end + end + + # Run ansible on creation + node4.vm.provision :ansible_local do |ansible| + ansible.playbook = "/vagrant/playbooks/build-nodes.yml" + ansible.install = true + ansible.compatibility_mode = "2.0" + ansible.inventory_path = "/vagrant/inventory/hosts.ini" + ansible.config_file = "/vagrant/ansible.cfg" + ansible.limit = "node4" + end end - - node4.vm.provision "shell", inline: <<-SHELL - yes| sudo mkfs.ext4 /dev/sdb - SHELL - node4.vm.synced_folder ".", "/vagrant" -end - -# Control Node -config.vm.define "control" do |control| - control.vm.box = "rdbreak/rhel8node" -# control.vm.hostname = "control.ansi.example.com" - control.vm.network "private_network", ip: "192.168.55.200" - control.vm.provider :virtualbox do |control| - control.customize ['modifyvm', :id,'--memory', '2048'] + + #-- Control Node ------------------------------------------------------------- + config.vm.define "control" do |control| + control.vm.box = "rdbreak/rhel8node" + control.vm.network "private_network", ip: "192.168.55.200" + + control.vm.provider :virtualbox do |control| + control.customize ['modifyvm', :id,'--memory', '2048'] end - control.vm.synced_folder ".", "/vagrant", type: "rsync", rsync__exclude: [".git/", "*.vdi"] - control.vm.provision :ansible_local do |ansible| - ansible.playbook = "/vagrant/playbooks/master.yml" - ansible.install = false - ansible.compatibility_mode = "2.0" - ansible.inventory_path = "/vagrant/inventory" - ansible.config_file = "/vagrant/ansible.cfg" - ansible.limit = "all" - end -end -end + + # Make the /vagrant folder sync both ways on the controller + control.vm.synced_folder ".", "/vagrant", type: "virtualbox" + + control.vm.provision :ansible_local do |ansible| + ansible.playbook = "/vagrant/playbooks/build-nodes.yml" + ansible.install = false + ansible.compatibility_mode = "2.0" + ansible.inventory_path = "/vagrant/inventory/hosts.ini" + ansible.config_file = "/vagrant/ansible.cfg" + ansible.limit = "control" + end + end + #----------------------------------------------------------------------------- +end \ No newline at end of file diff --git a/ansible.cfg b/ansible.cfg index ec41023..c0ff266 100644 --- a/ansible.cfg +++ b/ansible.cfg @@ -1,6 +1,6 @@ [defaults] host_key_checking = false -inventory = ./inventory +inventory = ./inventory/hosts.ini deprecation_warnings = false stdout_callback = yaml scp_if_ssh = true @@ -11,8 +11,11 @@ remote_tmp = /tmp forks = 10 force_handlers = True timeout = 30 +roles_path = ./roles + [ssh_connection] pipelining = True + [privilege_escalation] become= True become_method = sudo diff --git a/inventory b/inventory deleted file mode 100644 index d85bd30..0000000 --- a/inventory +++ /dev/null @@ -1,12 +0,0 @@ -[repo] -repo.ansi.example.com ansible_host=192.168.55.199 ansible_user=vagrant ansible_ssh_pass=vagrant ansible_python_interpreter=/usr/bin/python3 -[control] -control.ansi.example.com ansible_host=192.168.55.200 ansible_user=vagrant ansible_ssh_pass=vagrant ansible_python_interpreter=/usr/bin/python3 -[node1] -node1.ansi.example.com ansible_host=192.168.55.201 ansible_user=vagrant ansible_ssh_pass=vagrant ansible_python_interpreter=/usr/bin/python3 -[node2] -node2.ansi.example.com ansible_host=192.168.55.202 ansible_user=vagrant ansible_ssh_pass=vagrant ansible_python_interpreter=/usr/bin/python3 -[node3] -node3.ansi.example.com ansible_host=192.168.55.203 ansible_user=vagrant ansible_ssh_pass=vagrant ansible_python_interpreter=/usr/bin/python3 -[node4] -node4.ansi.example.com ansible_host=192.168.55.204 ansible_user=vagrant ansible_ssh_pass=vagrant ansible_python_interpreter=/usr/bin/python3 \ No newline at end of file diff --git a/inventory/group_vars/all.yml b/inventory/group_vars/all.yml new file mode 100644 index 0000000..652666f --- /dev/null +++ b/inventory/group_vars/all.yml @@ -0,0 +1,8 @@ +--- + +ansible_user: vagrant +ansible_ssh_pass: vagrant +ansible_python_interpreter: /usr/bin/python3 + +user_password: password +root_password: password \ No newline at end of file diff --git a/inventory/group_vars/control.yml b/inventory/group_vars/control.yml new file mode 100644 index 0000000..e09be6f --- /dev/null +++ b/inventory/group_vars/control.yml @@ -0,0 +1,5 @@ +--- + +hostname_fqdn: control.ansi.example.com +hostname_host: control +ansible_host: '192.168.55.200' \ No newline at end of file diff --git a/inventory/group_vars/node1.yml b/inventory/group_vars/node1.yml new file mode 100644 index 0000000..49ece24 --- /dev/null +++ b/inventory/group_vars/node1.yml @@ -0,0 +1,5 @@ +--- + +hostname_fqdn: node1.ansi.example.com +hostname_host: node1 +ansible_host: '192.168.55.201' \ No newline at end of file diff --git a/inventory/group_vars/node2.yml b/inventory/group_vars/node2.yml new file mode 100644 index 0000000..ac23039 --- /dev/null +++ b/inventory/group_vars/node2.yml @@ -0,0 +1,5 @@ +--- + +hostname_fqdn: node2.ansi.example.com +hostname_host: node2 +ansible_host: '192.168.55.202' \ No newline at end of file diff --git a/inventory/group_vars/node3.yml b/inventory/group_vars/node3.yml new file mode 100644 index 0000000..054b79e --- /dev/null +++ b/inventory/group_vars/node3.yml @@ -0,0 +1,5 @@ +--- + +hostname_fqdn: node3.ansi.example.com +hostname_host: node3 +ansible_host: '192.168.55.203' \ No newline at end of file diff --git a/inventory/group_vars/node4.yml b/inventory/group_vars/node4.yml new file mode 100644 index 0000000..5f1ce66 --- /dev/null +++ b/inventory/group_vars/node4.yml @@ -0,0 +1,5 @@ +--- + +hostname_fqdn: node4.ansi.example.com +hostname_host: node4 +ansible_host: '192.168.55.204' \ No newline at end of file diff --git a/inventory/group_vars/repo.yml b/inventory/group_vars/repo.yml new file mode 100644 index 0000000..0a2936e --- /dev/null +++ b/inventory/group_vars/repo.yml @@ -0,0 +1,5 @@ +--- + +hostname_fqdn: repo.ansi.example.com +hostname_host: repo +ansible_host: '192.168.55.199' \ No newline at end of file diff --git a/inventory/hosts.ini b/inventory/hosts.ini new file mode 100644 index 0000000..6da7a39 --- /dev/null +++ b/inventory/hosts.ini @@ -0,0 +1,17 @@ +[repo] +repo.ansi.example.com + +[control] +control.ansi.example.com + +[node1] +node1.ansi.example.com + +[node2] +node2.ansi.example.com + +[node3] +node3.ansi.example.com + +[node4] +node4.ansi.example.com \ No newline at end of file diff --git a/playbooks/build-nodes.yml b/playbooks/build-nodes.yml new file mode 100644 index 0000000..aa08875 --- /dev/null +++ b/playbooks/build-nodes.yml @@ -0,0 +1,10 @@ +--- + +- name: Setting Up Node + hosts: all + become: true + gather_facts: false + ignore_errors: true + + roles: + - build-nodes \ No newline at end of file diff --git a/playbooks/control.yml b/playbooks/control.yml deleted file mode 100644 index d98b220..0000000 --- a/playbooks/control.yml +++ /dev/null @@ -1,124 +0,0 @@ ---- -- name: Setting up the Control Node - hosts: control - strategy: free - gather_facts: false - ignore_errors: true - tasks: - - name: Setting Hostname - hostname: name=control.ansi.example.com - - name: Creating User Account - user: - name: user - shell: /bin/bash - groups: wheel - append: yes - generate_ssh_key: yes - force: yes - - name: Changing User Password - shell: echo password | sudo passwd user --stdin - - name: Changing Root Password - shell: echo password | sudo passwd root --stdin - - name: Fixing Resolv File - lineinfile: - path: /etc/resolv.conf - line: 'nameserver 8.8.8.8' - state: present - - name: Building Host File - copy: - dest: /etc/hosts - content: "127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4\n:1 localhost localhost.localdomain localhost6 localhost6.localdomain6\n192.168.55.199 repo.ansi.example.com repo\n192.168.55.200 control.ansi.example.com control\n192.168.55.201 node1.ansi.example.com node1\n192.168.55.202 node2.ansi.example.com node2\n192.168.55.203 node3.ansi.example.com node3\n192.168.55.204 node4.ansi.example.com node4" - force: yes - - name: Erasing Repos - file: - path: /etc/yum.repos.d/* - state: absent - - name: Creating Temporary Repo File - file: - path: /etc/yum.repos.d/ipa.repo - state: touch - mode: 0755 - - name: Adding the rhel-system-repos.rpm - copy: - src: rhel-system-roles-1.0.1-1.el8.noarch.rpm - dest: /home/vagrant - owner: vagrant - group: vagrant - mode: "0775" - - name: Building Repo File - copy: - dest: /etc/yum.repos.d/ipa.repo - content: "[base]\nname=Base\nbaseurl=http://repo/BaseOS\ngpgcheck=0\nenabled=1\n\n[apps]\nname=Apps\nbaseurl=http://repo/AppStream\ngpgcheck=0\nenabled=1" - force: yes - tags: repo - - name: Starting services - service: - name: "{{ item }}" - state: started - enabled: yes - with_items: - - firewalld - - httpd - - name: Enabling Firewall Services - firewalld: - service: "{{ item }}" - immediate: yes - permanent: yes - state: enabled - with_items: - - http - - https - - ntp - - dns - - ftp - - name: Reloading Firewall - service: name=firewalld state=restarted - - name: Configuring network - shell: nmcli con mod 'System eth1' ipv4.addresses 192.168.55.200/24 ipv4.gateway 192.168.55.1 ipv4.dns 8.8.8.8 ipv4.dns-search ansi.example.com ipv4.method manual - - name: Reloaded Network - service: - name: NetworkManager - state: restarted -# - name: Generating RSA Key -# command : ssh-keygen -q -t rsa -f /home/user/.ssh/id_rsa -C "" -N "" -# become: yes -# become_user: user - - name: Adjusting services - selinux: - state: permissive - policy: targeted - - name: Creating Welcome Message - file: - path: /etc/profile.d/welcome.sh - state: touch - mode: 0755 - - name: Erasing Repos - file: - path: /etc/yum.repos.d/* - state: absent - - name: Building Welcome Message - blockinfile: - dest: /etc/profile.d/welcome.sh - block: | - #!/bin/bash - # - echo -e ' - # _ _ _ _ _ _ _ - # /\ \ /\ \ /\ \ _ /\ \ /\ \ /\ \ _\ \ - # / \ \ / \ \ / \ \ /\_\_\ \ / \ \ / \ \ /\__ \ - # / /\ \ \ / /\ \ \ / /\ \ \_/ / /\__ \ / /\ \ \ / /\ \ \ / /_ \_\ - # / / /\ \ \ / / /\ \ \ / / /\ \___/ / /_ \ \ / / /\ \_\ / / /\ \ \ / / /\/_/ - # / / / \ \_\ / / / \ \_\/ / / \/____/ / /\ \ \/ / /_/ / // / / \ \_\/ / / - # / / / \/_/ / / / / / / / / / / / / / \/_/ / /__\/ // / / / / / / / - # / / / / / / / / / / / / / / / / / / /_____// / / / / / / / ____ - # / / /________ / / /___/ / / / / / / / / / / / /\ \ \ / / /___/ / / /_/_/ ___/\ - # / / /_________/ / /____\/ / / / / / /_/ / / / / \ \ / / /____\/ /_______/\__\/ - # \/____________\/_________/\/_/ \/_/\_\/ \/_/ \_\\/_________/\_______\/ - '"# - # - # You are logged into \"`hostname`\" as the \"`whoami`\" account. - # This system is running `cat /etc/redhat-release` - # - # Repo/AppStream - # Available to use from http://repo.ansi.example.com/BaseOS and http://repo.ansi.example.com/AppStream - " diff --git a/playbooks/keys.yml b/playbooks/keys.yml deleted file mode 100644 index 2e3324b..0000000 --- a/playbooks/keys.yml +++ /dev/null @@ -1,54 +0,0 @@ ---- -- name: Sending SSH Keys to Nodes - hosts: control - become: true - ignore_errors: yes - tasks: - - name: Sending Key to node1 - expect: - command: ssh-copy-id -i /home/user/.ssh/id_rsa.pub user@node1.ansi.example.com - responses: - 'Are you sure you want to continue connecting': 'yes' - 'password': 'password' - timeout: 10 - become_user: user - - name: Sending Key to node2 - expect: - command: ssh-copy-id -i /home/user/.ssh/id_rsa.pub user@node2.ansi.example.com - responses: - 'Are you sure you want to continue connecting': 'yes' - 'password': 'password' - timeout: 10 - become_user: user - - name: Sending Key to node3 - expect: - command: ssh-copy-id -i /home/user/.ssh/id_rsa.pub user@node3.ansi.example.com - responses: - 'Are you sure you want to continue connecting': 'yes' - 'password': 'password' - timeout: 10 - become_user: user - - name: Sending Key to node4 - expect: - command: ssh-copy-id -i /home/user/.ssh/id_rsa.pub user@node4.ansi.example.com - responses: - 'Are you sure you want to continue connecting': 'yes' - 'password': 'password' - timeout: 10 - become_user: user - - name: Welcome to the RHCE 8 Study/Test Environment! - debug: - msg: - - 'Next Steps: Accessing The Systems:' - - '- Control - 192.168.55.200' - - '- Node 1 - 192.168.55.201' - - '- Node 2 - 192.168.55.202' - - '- Node 3 - 192.168.55.203' - - '- Node 4 - 192.168.55.204' - - '- Username/Password - user/password' - - '--------------------------------------------------' - - '- For root - use `sudo` or `sudo su`' - - '- Access example - ssh user@192.168.55.200' - - '- Happy Studying!' - -... \ No newline at end of file diff --git a/playbooks/master.yml b/playbooks/master.yml deleted file mode 100644 index 5a92090..0000000 --- a/playbooks/master.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -- import_playbook: repo.yml -- import_playbook: control.yml -- import_playbook: node1.yml -- import_playbook: node2.yml -- import_playbook: node3.yml -- import_playbook: node4.yml -- import_playbook: keys.yml -... \ No newline at end of file diff --git a/playbooks/node1.yml b/playbooks/node1.yml deleted file mode 100644 index ea9496e..0000000 --- a/playbooks/node1.yml +++ /dev/null @@ -1,100 +0,0 @@ ---- -- name: Setting Up Node 1 - hosts: node1 - strategy: free - gather_facts: False - ignore_errors: true - tasks: - - name: Setting Hostname - hostname: name=node1.ansi.example.com - - name: Creating User Account - user: - name: user - shell: /bin/bash - groups: wheel - append: yes - - name: Changing User Password - shell: echo password | sudo passwd user --stdin - - name: Changing Root Password - shell: echo password | sudo passwd root --stdin - - name: Adjusting services - selinux: - state: permissive - policy: targeted - - name: Building Host File - copy: - dest: /etc/hosts - content: "127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4\n:1 localhost localhost.localdomainlocalhost6localhost6.localdomain6\n192.168.55.199 repo.ansi.example.com repo\n192.168.55.200 control.ansi.example.com control\n192.168.55.201 node1.ansi.example.com node1\n192.168.55.202 node2.ansi.example.com node2\n192.168.55.203 node3.ansi.example.com node3\n192.168.55.204 node4.ansi.example.com node4" - force: yes - - name: Erasing Repos - file: - path: /etc/yum.repos.d/* - state: absent - - name: Creating Temporary Repo File - file: - path: /etc/yum.repos.d/ipa.repo - state: touch - mode: 0755 - - name: Building Repo File - copy: - dest: /etc/yum.repos.d/ipa.repo - content: "[base]\nname=Base\nbaseurl=http://repo/BaseOS\ngpgcheck=0\nenabled=1\n\n[apps]\nname=Apps\nbaseurl=http://repo/AppStream\ngpgcheck=0\nenabled=1" - force: yes - - name: Configuring network - command: nmcli con mod 'System eth1' ipv4.addresses 192.168.55.201/24 ipv4.gateway 192.168.55.1 ipv4.method manual - - name: Restarting Network - service: - name: NetworkManager - state: restarted - - name: Enabling IPV6 - sysctl: - name: "{{ item }}" - value: '0' - sysctl_set: yes - with_items: - - net.ipv6.conf.lo.disable_ipv6 - - net.ipv6.conf.all.disable_ipv6 - - name: Environment Packages Installed. - yum: name=man-pages state=present - register: yum_sleeper - - name: Starting services - service: name=firewalld enabled=true state=started - - name: Fixing Resolv File - lineinfile: - path: /etc/resolv.conf - line: 'nameserver 8.8.8.8' - state: present - - name: Creating Welcome Message - file: - path: /etc/profile.d/welcome.sh - state: touch - mode: 0755 - - name: Erasing Repos - file: - path: /etc/yum.repos.d/* - state: absent - - name: Building Welcome Message - blockinfile: - dest: /etc/profile.d/welcome.sh - block: | - #!/bin/bash - # - echo -e ' - # _ _ _ _ _ - # /\ \ _ /\ \ /\ \ /\ \ / /\ - # / \ \ /\_\/ \ \ / \ \____ / \ \ / / \ - # / /\ \ \_/ / / /\ \ \ / /\ \_____\/ /\ \ \/_/ /\ \ - # / / /\ \___/ / / /\ \ \ / / /\/___ / / /\ \_\_\/\ \ \ - # / / / \/____/ / / \ \_\/ / / / / / /_/_ \/_/ \ \ \ - # / / / / / / / / / / / / / / / / /____/\ \ \ \ - # / / / / / / / / / / / / / / / / /\____\/ \ \ \ - # / / / / / / / /___/ / /\ \ \__/ / / / /______ __\ \ \___ - # / / / / / / / /____\/ / \ \___\/ / / /_______\ /___\_\/__/\ - # \/_/ \/_/\/_________/ \/_____/\/__________/ \_________\/ - '"# - # - # You are logged into \"`hostname`\" as the \"`whoami`\" account. - # This system is running `cat /etc/redhat-release` - # - " -... \ No newline at end of file diff --git a/playbooks/node2.yml b/playbooks/node2.yml deleted file mode 100644 index 5d74428..0000000 --- a/playbooks/node2.yml +++ /dev/null @@ -1,101 +0,0 @@ ---- -- name: Setting Up Node 2 - hosts: node2 - strategy: free - gather_facts: False - ignore_errors: true - tasks: - - name: Setting Hostname - hostname: name=node2.ansi.example.com - - name: Creating User Account - user: - name: user - shell: /bin/bash - groups: wheel - append: yes - - name: Changing User Password - shell: echo password | sudo passwd user --stdin - - name: Changing Root Password - shell: echo password | sudo passwd root --stdin - - name: Adjusting services - selinux: - state: permissive - policy: targeted - - name: Building Host File - copy: - dest: /etc/hosts - content: "127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4\n:1 localhost localhost.localdomain localhost6localhost6.localdomain6\n192.168.55.199 repo.ansi.example.com repo\n192.168.55.200 control.ansi.example.com control\n192.168.55.201 node1.ansi.example.com node1\n192.168.55.202 node2.ansi.example.com node2\n192.168.55.203 node3.ansi.example.com node3\n192.168.55.204 node4.ansi.example.com node4" - force: yes - - name: Erasing Repos - file: - path: /etc/yum.repos.d/* - state: absent - - name: Creating Temporary Repo File - file: - path: /etc/yum.repos.d/ipa.repo - state: touch - mode: 0755 - - name: Building Repo File - copy: - dest: /etc/yum.repos.d/ipa.repo - content: "[base]\nname=Base\nbaseurl=http://repo/BaseOS\ngpgcheck=0\nenabled=1\n\n[apps]\nname=Apps\nbaseurl=http://repo/AppStream\ngpgcheck=0\nenabled=1" - force: yes - tags: repo - - name: Configuring network - command: nmcli con mod 'System eth1' ipv4.addresses 192.168.55.202/24 ipv4.gateway 192.168.55.1 ipv4.method manual - - name: Restarting Network - service: - name: NetworkManager - state: restarted - - name: Enabling IPV6 - sysctl: - name: "{{ item }}" - value: '0' - sysctl_set: yes - with_items: - - net.ipv6.conf.lo.disable_ipv6 - - net.ipv6.conf.all.disable_ipv6 - - name: Environment Packages Installed. - yum: name=man-pages state=present - register: yum_sleeper - - name: Starting services - service: name=firewalld enabled=true state=started - - name: Fixing Resolv File - lineinfile: - path: /etc/resolv.conf - line: 'nameserver 8.8.8.8' - state: present - - name: Creating Welcome Message - file: - path: /etc/profile.d/welcome.sh - state: touch - mode: 0755 - - name: Erasing Repos - file: - path: /etc/yum.repos.d/* - state: absent - - name: Building Welcome Message - blockinfile: - dest: /etc/profile.d/welcome.sh - block: | - #!/bin/bash - # - echo -e ' - # _ _ _ _ _ - # /\ \ _ /\ \ /\ \ /\ \ /\ \ - # / \ \ /\_\/ \ \ / \ \____ / \ \ / \ \ - # / /\ \ \_/ / / /\ \ \ / /\ \_____\/ /\ \ \/ /\ \ \ - # / / /\ \___/ / / /\ \ \ / / /\/___ / / /\ \_\/_/\ \ \ - # / / / \/____/ / / \ \_\/ / / / / / /_/_ \/_/ / / / - # / / / / / / / / / / / / / / / / /____/\ / / / - # / / / / / / / / / / / / / / / / /\____\/ / / / _ - # / / / / / / / /___/ / /\ \ \__/ / / / /______ / / /_/\_\ - # / / / / / / / /____\/ / \ \___\/ / / /_______\ / /_____/ / - # \/_/ \/_/\/_________/ \/_____/\/__________/ \________/ - '"# - # - # You are logged into \"`hostname`\" as the \"`whoami`\" account. - # This system is running `cat /etc/redhat-release` - # - " -... \ No newline at end of file diff --git a/playbooks/node3.yml b/playbooks/node3.yml deleted file mode 100644 index a58042a..0000000 --- a/playbooks/node3.yml +++ /dev/null @@ -1,101 +0,0 @@ ---- -- name: Setting Up Node 3 - hosts: node3 - strategy: free - gather_facts: False - ignore_errors: true - tasks: - - name: Setting Hostname - hostname: name=node3.ansi.example.com - - name: Creating User Account - user: - name: user - shell: /bin/bash - groups: wheel - append: yes - - name: Changing User Password - shell: echo password | sudo passwd user --stdin - - name: Changing Root Password - shell: echo password | sudo passwd root --stdin - - name: Adjusting services - selinux: - state: permissive - policy: targeted - - name: Building Host File - copy: - dest: /etc/hosts - content: "127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4\n:1 localhost localhost.localdomain localhost6localhost6.localdomain6\n192.168.55.199 repo.ansi.example.com repo\n192.168.55.200 control.ansi.example.com control\n192.168.55.201 node1.ansi.example.com node1\n192.168.55.202 node2.ansi.example.com node2\n192.168.55.203 node3.ansi.example.com node3\n192.168.55.204 node4.ansi.example.com node4" - force: yes - - name: Erasing Repos - file: - path: /etc/yum.repos.d/* - state: absent - - name: Creating Temporary Repo File - file: - path: /etc/yum.repos.d/ipa.repo - state: touch - mode: 0755 - - name: Building Repo File - copy: - dest: /etc/yum.repos.d/ipa.repo - content: "[base]\nname=Base\nbaseurl=http://repo/BaseOS\ngpgcheck=0\nenabled=1\n\n[apps]\nname=Apps\nbaseurl=http://repo/AppStream\ngpgcheck=0\nenabled=1" - force: yes - tags: repo - - name: Configuring network - command: nmcli con mod 'System eth1' ipv4.addresses 192.168.55.203/24 ipv4.gateway 192.168.55.1 ipv4.method manual - - name: Restarting Network - service: - name: NetworkManager - state: restarted - - name: Enabling IPV6 - sysctl: - name: "{{ item }}" - value: '0' - sysctl_set: yes - with_items: - - net.ipv6.conf.lo.disable_ipv6 - - net.ipv6.conf.all.disable_ipv6 - - name: Environment Packages Installed. - yum: name=man-pages state=present - register: yum_sleeper - - name: Starting services - service: name=firewalld enabled=true state=started - - name: Fixing Resolv File - lineinfile: - path: /etc/resolv.conf - line: 'nameserver 8.8.8.8' - state: present - - name: Creating Welcome Message - file: - path: /etc/profile.d/welcome.sh - state: touch - mode: 0755 - - name: Erasing Repos - file: - path: /etc/yum.repos.d/* - state: absent - - name: Building Welcome Message - blockinfile: - dest: /etc/profile.d/welcome.sh - block: | - #!/bin/bash - # - echo -e ' - # _ _ _ _ _ - # /\ \ _ /\ \ /\ \ /\ \ /\ \ - # / \ \ /\_\/ \ \ / \ \____ / \ \ / \ \ - # / /\ \ \_/ / / /\ \ \ / /\ \_____\/ /\ \ \ / /\ \ \ - # / / /\ \___/ / / /\ \ \ / / /\/___ / / /\ \_/ / /\ \ \ - # / / / \/____/ / / \ \_\/ / / / / / /_/_ \/_\/_//_\ \ \ - # / / / / / / / / / / / / / / / / /____/\ __\___ \ \ - # / / / / / / / / / / / / / / / / /\____\/ / /\ \ \ \ - # / / / / / / / /___/ / /\ \ \__/ / / / /______ / /_/____\ \ \ - # / / / / / / / /____\/ / \ \___\/ / / /_______\/__________\ \ \ - # \/_/ \/_/\/_________/ \/_____/\/__________/\_____________\/ - '"# - # - # You are logged into \"`hostname`\" as the \"`whoami`\" account. - # This system is running `cat /etc/redhat-release` - # - " -... \ No newline at end of file diff --git a/playbooks/node4.yml b/playbooks/node4.yml deleted file mode 100644 index c0c804d..0000000 --- a/playbooks/node4.yml +++ /dev/null @@ -1,105 +0,0 @@ ---- -- name: Setting Up Node 4 - hosts: node4 - strategy: free - gather_facts: False - ignore_errors: true - tasks: - - name: Setting Hostname - hostname: name=node4.ansi.example.com - - name: Creating User Account - user: - name: user - shell: /bin/bash - groups: wheel - append: yes - - name: Changing User Password - shell: echo password | sudo passwd user --stdin - - name: Changing Root Password - shell: echo password | sudo passwd root --stdin - - name: Adjusting services - selinux: - state: permissive - policy: targeted - - name: Building Host File - copy: - dest: /etc/hosts - content: "127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4\n:1 localhost localhost.localdomain localhost6localhost6.localdomain6\n192.168.55.199 repo.ansi.example.com repo\n192.168.55.200 control.ansi.example.com control\n192.168.55.201 node1.ansi.example.com node1\n192.168.55.202 node2.ansi.example.com node2\n192.168.55.203 node3.ansi.example.com node3\n192.168.55.204 node4.ansi.example.com node4" - force: yes - - name: Erasing Repos - file: - path: /etc/yum.repos.d/* - state: absent - - name: Creating Temporary Repo File - file: - path: /etc/yum.repos.d/ipa.repo - state: touch - mode: 0755 - - name: Building Repo File - copy: - dest: /etc/yum.repos.d/ipa.repo - content: "[base]\nname=Base\nbaseurl=http://repo/BaseOS\ngpgcheck=0\nenabled=1\n\n[apps]\nname=Apps\nbaseurl=http://repo/AppStream\ngpgcheck=0\nenabled=1" - force: yes - tags: repo - - name: Configuring network - command: nmcli con mod 'System eth1' ipv4.addresses 192.168.55.204/24 ipv4.gateway 192.168.55.1 ipv4.method manual - - name: Restarting Network - service: name=NetworkManager state=restarted - - name: Enabling IPV6 - sysctl: - name: "{{ item }}" - value: '0' - sysctl_set: yes - with_items: - - net.ipv6.conf.lo.disable_ipv6 - - net.ipv6.conf.all.disable_ipv6 - - name: Environment Packages Installed - yum: - name: man-pages - state: present - register: yum_sleeper - - name: Environment Packages Installed. - yum: name=man-pages state=present - register: yum_sleeper - - name: Starting services - service: name=firewalld enabled=true state=started - - name: Fixing Resolv File - lineinfile: - path: /etc/resolv.conf - line: 'nameserver 8.8.8.8' - state: present - - name: Creating Welcome Message - file: - path: /etc/profile.d/welcome.sh - state: touch - mode: 0755 - - name: Erasing Repos - file: - path: /etc/yum.repos.d/* - state: absent - - name: Building Welcome Message - blockinfile: - dest: /etc/profile.d/welcome.sh - block: | - #!/bin/bash - # - echo -e ' - # _ _ _ _ _ - # /\ \ _ /\ \ /\ \ /\ \ _ /\ \ - # / \ \ /\_\/ \ \ / \ \____ / \ \ /\_\\ \ \ - # / /\ \ \_/ / / /\ \ \ / /\ \_____\/ /\ \ \ / / / \ \ \ - # / / /\ \___/ / / /\ \ \ / / /\/___ / / /\ \_/ / / \ \ \ - # / / / \/____/ / / \ \_\/ / / / / / /_/_ \/_\ \ \____\ \ \ - # / / / / / / / / / / / / / / / / /____/\ \ \________\ \ - # / / / / / / / / / / / / / / / / /\____\/ \/________/\ \ - # / / / / / / / /___/ / /\ \ \__/ / / / /______ \ \ \ - # / / / / / / / /____\/ / \ \___\/ / / /_______\ \ \_\ - # \/_/ \/_/\/_________/ \/_____/\/__________/ \/_/ - # - '"# - # - # You are logged into \"`hostname`\" as the \"`whoami`\" account. - # This system is running `cat /etc/redhat-release` - # - " - \ No newline at end of file diff --git a/playbooks/repo.yml b/playbooks/repo.yml deleted file mode 100644 index 8e81e9a..0000000 --- a/playbooks/repo.yml +++ /dev/null @@ -1,93 +0,0 @@ ---- -- name: Setting Up Repo Node - hosts: repo - strategy: free - gather_facts: False - ignore_errors: true - tasks: - - name: Setting Hostname - hostname: name=repo.ansi.example.com - - name: Creating User Account - user: - name: user - shell: /bin/bash - groups: wheel - append: yes - - name: Changing User Password - shell: echo password | sudo passwd user --stdin - - name: Disabling services - selinux: - state: disabled - - name: Building Host File - copy: - dest: /etc/hosts - content: "127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4\n:1 localhost localhost.localdomain localhost6localhost6.localdomain6\n192.168.55.199 repo.ansi.example.com repo\n192.168.55.200 control.ansi.example.com control\n192.168.55.201 node1.ansi.example.com node1\n192.168.55.202 node2.ansi.example.com node2\n192.168.55.203 node3.ansi.example.com node3\n192.168.55.204 node4.ansi.example.com node4" - force: yes - - name: Enabling services - service: - name: "{{ item }}" - state: started - enabled: yes - with_items: - - httpd - - firewalld - - name: Enabling services - service: - name: "{{ item }}" - state: started - enabled: yes - with_items: - - httpd - - firewalld - - name: Starting Firewalld - firewalld: - service: "{{ item }}" - immediate: yes - permanent: yes - state: enabled - with_items: - - http - - https - - ntp - - dns - - kerberos - - ldap - - ldaps - - ftp - - name: Reloading Firewall - service: name=firewalld state=restarted - - name: Enabling IPV6 - shell: sysctl net.ipv6.conf.lo.disable_ipv6=0 ; sysctl net.ipv6.conf.all.disable_ipv6=0 - - name: Creating Welcome Message - file: - path: /etc/profile.d/welcome.sh - state: touch - mode: 0755 - - name: Fixing SELinux Contexts - shell: restorecon -Rv /var/www/html - - name: Building Welcome Message - blockinfile: - dest: /etc/profile.d/welcome.sh - block: | - #!/bin/bash - # - echo -e ' - # _ _ _ _ - # /\ \ /\ \ /\ \ /\ \ - # / \ \ / \ \ / \ \ / \ \ - # / /\ \ \ / /\ \ \ / /\ \ \ / /\ \ \ - # / / /\ \_\ / / /\ \_\ / / /\ \_\/ / /\ \ \ - # / / /_/ / // /_/_ \/_/ / / /_/ / / / / \ \_\ - # / / /__\/ // /____/\ / / /__\/ / / / / / / - # / / /_____// /\____\/ / / /_____/ / / / / / - # / / /\ \ \ / / /______ / / / / / /___/ / / - # / / / \ \ / / /_______/ / / / / /____\/ / - # \/_/ \_\\/__________\/_/ \/_________/ - '"# - # Why are you here? You should be working on the system hosts... - # Anyway, try not to reboot me or bad stuff can happen. - # - # You are logged into \"`hostname`\" as the \"`whoami`\" account. - # This system is running `cat /etc/redhat-release` - # - " diff --git a/practice_exams/README.md b/practice_exams/README.md new file mode 100644 index 0000000..dcf2d7a --- /dev/null +++ b/practice_exams/README.md @@ -0,0 +1,100 @@ +# Practice Exams + +Here you can find practice exams that can be used to practice and validate your knowledge. + +## Included Exam Scenarios + +### Exam Scenario 1 + +The exam has 18 tasks for you to perform. At the end you can run a validation playbook to check that all steps were performed correctly. + +Access the exam -> [Exam Scenario 1](./exam1/README.md) + +## Creating an Exam Scenario with ChatGPT + +You can use ChatGPT to create new exam scenarios for you. Use the 2 commands below. + +### Question 1: Providing base data + + I'm providing you with the RHCE exam objectives and a sample inventory file. Don't do anythin and wait for my next question. + + ``` + [repo] + repo.ansi.example.com ansible_host=192.168.55.199 ansible_user=vagrant ansible_ssh_pass=vagrant ansible_python_interpreter=/usr/bin/python3 + [control] + control.ansi.example.com ansible_host=192.168.55.200 ansible_user=vagrant ansible_ssh_pass=vagrant ansible_python_interpreter=/usr/bin/python3 + [node1] + node1.ansi.example.com ansible_host=192.168.55.201 ansible_user=vagrant ansible_ssh_pass=vagrant ansible_python_interpreter=/usr/bin/python3 + [node2] + node2.ansi.example.com ansible_host=192.168.55.202 ansible_user=vagrant ansible_ssh_pass=vagrant ansible_python_interpreter=/usr/bin/python3 + [node3] + node3.ansi.example.com ansible_host=192.168.55.203 ansible_user=vagrant ansible_ssh_pass=vagrant ansible_python_interpreter=/usr/bin/python3 + [node4] + node4.ansi.example.com ansible_host=192.168.55.204 ansible_user=vagrant ansible_ssh_pass=vagrant ansible_python_interpreter=/usr/bin/python3 + ``` + + # RHCE exam objectives + + As an RHCE exam candidate, you should be able to handle all responsibilities expected of a Red Hat Certified System Administrator, including these tasks: + + + **Be able to perform all tasks expected of a Red Hat Certified System Administrator** + + Understand and use essential tools + + Operate running systems + + Configure local storage + + Create and configure file systems + + Deploy, configure, and maintain systems + + Manage users and groups + + Manage security + + **Understand core components of Ansible** + + Inventories + + Modules + + Variables + + Facts + + Plays + + Playbooks + + Configuration files + + **Install and configure an Ansible control node** + + Install required packages + + Create a static host inventory file + + Create a configuration file + + **Configure Ansible managed nodes** + + Create and distribute SSH keys to managed nodes + + Configure privilege escalation on managed nodes + + Validate a working configuration using ad hoc Ansible commands + + **Script administration tasks** + + Create simple shell scripts + + Create simple shell scripts that run ad hoc Ansible commands + + **Create and use static inventories to define groups of hosts** + + **Create Ansible plays and playbooks** + + Know how to work with commonly used Ansible modules + + Use variables to retrieve the results of running a command + + Use conditionals to control play execution + + Configure error handling + + Create playbooks to configure systems to a specified state + + **Use Ansible modules for system administration tasks that work with:** + + Software packages and repositories + + Services + + Firewall rules + + File systems + + Storage devices + + File content + + Archiving + + Scheduled tasks + + Security + + Users and groups + + **Create and use templates to create customized configuration files** + + **Work with Ansible variables and facts** + + **Create and work with roles** + + **Download roles from an Ansible Galaxy and use them** + + **Use Ansible Vault in playbooks to protect sensitive data** + + **Use provided documentation to look up specific information about Ansible modules and commands** + + As with all Red Hat performance-based exams, configurations must persist after reboot without intervention. + +### Question 2: Create practice exam + + Create a practice exam using the RHCE objectives and inventory file provided before. Be very specific about the tasks. For example: + + Don't just say to create a user, specify the user name and attributes. + + Don't just ask to copy a file to a node, specify the name, file attribute and contents. + + If you specify a new jinja2 template file, include the contents. + + If you specify a new config file, include the contents. diff --git a/practice_exams/exam1/README.md b/practice_exams/exam1/README.md new file mode 100644 index 0000000..8e83506 --- /dev/null +++ b/practice_exams/exam1/README.md @@ -0,0 +1,254 @@ +# Exam Scenario 1 + +Sources: ++ [Lisenet: Ansible Sample Exam for RHCE EX294 and EX407](https://www.lisenet.com/2019/ansible-sample-exam-for-ex294/) ++ [waseem-h gist: RHCE8-EX294-Practice-Exam.md](https://gist.github.com/waseem-h/6793ba3328f27df1a815402710acb3ff) + +## Validation Playbook + +After completing all the tasks on this page you can run a validation playbook to check that all steps were completed. + +a. SSH to the control node as the 'vagrant' user + +b. Browse to `/vagrant/practice_exams/exam1/validation` and run the `validate.yml` playbook: + +``` +ansible-playbook validate.yaml +``` + +The playbook will tell you which task (question) has a failure. Review the playbook output to identify where exactly is the error. + +## Answers + +Answers can also be found in the [answers](./answers/) folder. I would advise to only use it as last resort. + +## Sample Exam Questions + +**Note: Some questions may depend on the outcome of others. Please read all questions before proceeding.** + +### Task 1: Ansible Configuration + ++ Create a regular user '**automation**' with the password of '**devops**'. Use this user for all sample exam tasks. ++ All files that you create for this sample exam should be stored in `/home/automation/plays`. ++ All playbooks should exist under `/home/automation/plays/playbooks`. ++ Create a configuration file `/home/automation/plays/ansible.cfg` to meet the following requirements: + + The roles path should include `/home/automation/plays/roles`, as well as any other path that may be required for the course of the sample exam. + + The inventory file path is `/home/automation/plays/inventory`. + + Privileged escalation is **disabled** by default. + + Ansible should be able to manage **10 hosts** at a single time. + + Ansible should connect to all managed nodes using the '**automation**' user. + +Create an inventory file `/home/automation/plays/inventory` with the following: + ++ 'node1.ansi.example.com' should be a member of the '**proxy**' host group. ++ 'node2.ansi.example.com' should be a member of the '**webservers**' host group. ++ 'node3.ansi.example.com' should be a member of the '**webservers**' and '**database**' host group. ++ 'node4.ansi.example.com' should be a member of the '**database**' host group. + +### Task 2: Ad-Hoc Commands + ++ Create an SSH keypair. ++ Write a script `/home/automation/plays/adhoc.sh` that uses Ansible ad-hoc commands to achieve the following: + + User '**automation**' is created on all inventory hosts. + + SSH key (that you generated) is copied to all inventory hosts for the '**automation**' user and stored in `/home/automation/.ssh/authorized_keys`. + + The '**automation**' user is allowed to elevate privileges on all inventory hosts without having to provide a password. + + After running the ad-hoc script, you should be able to SSH into all inventory hosts using the '**automation**' user without password, as well as a run all privileged commands. + +### Task 3: File Content + +Create a playbook `/home/automation/plays/playbooks/motd.yml` that runs on all inventory hosts and does the following: + ++ The playbook should replace any existing content of `/etc/motd` with text. Text depends on the host group: + + On hosts in the '**proxy**' host group the line should be “Welcome to HAProxy server”. + + On hosts in the '**webservers**' host group the line should be “Welcome to Apache server”. + + On hosts in the '**database**' host group the line should be “Welcome to MySQL server”. + +### Task 4: Configure SSH Server + +Create a playbook `/home/automation/plays/playbooks/sshd.yml` that runs on all inventory hosts and configures SSHD daemon as follows: + ++ The banner is set to `/etc/motd` ++ `X11Forwarding` is disabled ++ `MaxAuthTries` is set to 3 + +### Task 5: Ansible Vault + ++ Create the Ansible vars file `/home/automation/plays/vars/secret.yml` and add the following variables to the file: + + '**user_password**' with value of '**devops**' + + '**database_password**' with value of '**devops**' ++ Create the Ansible password file `/home/automation/plays/vault_key` and add '**devops**' as the vault password. ++ Add the the vault password file to `ansible.cfg` ++ Encrypt the vars file `secret.yml`. + +### Task 6: Users and Groups + +You have been provided with the list of dictonary of users below. Use `/home/automation/plays/vars/user_list.yml` file to save this content: + +```yaml +--- +users: +- username: alice + uid: 1201 +- username: vincent + uid: 1202 +- username: sandy + uid: 2201 +- username: patrick + uid: 2202 +``` + +Create the playbook `/home/automation/plays/playbooks/users.yml` that uses the encrypted vars file `/home/automation/plays/secret.yml` to achieve the following: + ++ Users whose user ID starts with 1 should be created on servers in the '**webservers**' host group. User password should be used from the '**user_password**' variable. ++ Users whose user ID starts with 2 should be created on servers in the '**database**' host group. User password should be used from the '**user_password**' variable. ++ All users should be members of a supplementary group '**wheel**'. ++ Shell should be set to `/bin/bash` for all users. ++ Account passwords should use the SHA512 hash format. ++ Password should only be updated on user creation. ++ Each user should have an SSH key uploaded (use the SSH key that you create previously). + +After running the playbook, users should be able to SSH into their respective servers without passwords. + +### Task 7: Scheduled Tasks + +Create the playbook `/home/automation/plays/playbooks/regular_tasks.yml` that runs on servers in the '**proxy**' host group and does the following: + ++ A root crontab record is created that runs every hour. ++ The cron job appends the file `/var/log/time.log` with the output from the `date` command. + +### Task 8: Software Repositories + +Create the playbook `/home/automation/plays/playbooks/repository.yml` that runs on all servers and does the following: + ++ A YUM repository file is created called 'rpms.repo'. ++ The ID of the repositories in that file are 'BaseOS' and 'AppStream'. ++ The name of the repositories are is 'BaseOS on repo.ansi.example.com' and 'AppStream on repo.ansi.example.com. ++ Repositories should point to 'http://repo.ansi.example.com/BaseOS' and 'http://repo.ansi.example.com/AppStream' ++ Disable the existing 'Base' and 'Apps' repo (`ipa.repo`) + +### Task 9: Create and Work with Roles - MariaDB + +Create a role called '**sample-mysql**' and store it in `/home/automation/plays/roles`. The role should satisfy the following requirements: + ++ A primary partition number 1 of size 800MB on device `/dev/sdb` is created. ++ An LVM volume group called `vg_database` is created that uses the primary partition created above. ++ An LVM logical volume called `lv_mysql` is created of size 512MB in the volume group `vg_database`. ++ An XFS filesystem on the logical volume `lv_mysql` is created. ++ Logical volume `lv_mysql` is permanently mounted on `/mnt/mysql_backups`. ++ '**mariadb**' package is installed. ++ Firewall is configured to allow all incoming traffic on for 'MySQL' on 'TCP' port '3306'. ++ MySQL root user password should be set from the variable '**database_password**' (see task #5). ++ A `my.cnf` file should be created for root with the credentials. ++ MySQL server should be started and enabled on boot. ++ MySQL server configuration file `/etc/my.cnf.d/mariadb-server.cnf` is generated from the `my.cnf.j2` Jinja2 template with the following content: + +```ini +[mysqld] +bind_address = {{ ansible_default_ipv4.address }} +skip_name_resolve +datadir=/var/lib/mysql +socket=/var/lib/mysql/mysql.sock + +symbolic-links=0 +sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES + +[mysqld_safe] +log-error=/var/log/mysqld.log +pid-file=/var/run/mysqld/mysqld.pid +``` + +Create a playbook `/home/automation/plays/playbooks/mysql.yml` that uses the role and runs on hosts in the '**database**' group. + +### Task 10: Create and Work with Roles - Apache + +Create a role called '**sample-apache**' and store it in `/home/automation/plays/roles`. The role should satisfy the following requirements: + ++ The '**httpd**', '**mod_ssl**' and '**php**' packages are installed. Apache service is running and enabled on boot. ++ Firewall is configured to allow all incoming traffic for 'HTTP' (TCP port '80') and 'HTTPS' (TCP port '443'). ++ Apache service should be restarted every time the files `/var/www/html/index.html` or `/etc/httpd/conf/httpd.conf` are modified. ++ Identify the facts variable that stores the internal IPv4 address, which is the same as in the inventory file (your VM might have more than one address). ++ The `Listen` directive should be `Listen [internal IPv4 address variable]:80` (without the `[]`) ++ A Jinja2 template file `index.html.j2` is used to create the file `/var/www/html/index.html` with the following content: + +``` +The address of the server is: [internal IPv4 address variable] +``` + +Create the playbook `/home/automation/plays/playbooks/apache.yml` that uses the role and runs on hosts in the '**webservers**' host group. + +### Task 11: Download Roles From Ansible Galaxy and Use Them + +Use Ansible Galaxy to download and install '**geerlingguy.haproxy**' role in `/home/automation/plays/roles`. + +Create a playbook `/home/automation/plays/playbooks/haproxy.yml` that runs on servers in the '**proxy**' host group and does the following: + ++ Use '**geerlingguy.haproxy**' role to load balance request between hosts in the '**webservers**' host group. ++ Use '**roundrobin**' load balancing method. ++ HAProxy backend servers should be configured for HTTP only (port 80). ++ Backend servers should use the IP address from the task 10. ++ Confirm that the firewall is configured to allow all incoming traffic on TCP port 80. + +If your playbook works, then doing `curl http://node1.ansi.example.com/` should return output from the web server (see task #10). Running the command again should return output from the other web server. + +_Note: It won't work the same from a web browser_ + +### Task 12: Security + +Create the playbook `/home/automation/plays/playbooks/selinux.yml` that runs on hosts in the '**webservers**' host group and does the following: + ++ Uses the selinux '**RHEL system role**'. ++ Enables '**httpd_can_network_connect**' SELinux boolean. ++ The change must survive system reboot. + +### Task 13: Use Conditionals to Control Play Execution + +Create the playbook `/home/automation/plays/playbooks/sysctl.yml` that runs on all inventory hosts and does the following: + ++ If a server has more than 512MB of RAM, then parameter '**vm.swappiness**' is set to 10. ++ If a server has less than 512MB of RAM, then the following error message is displayed: '**Server memory less than 512MB**' + +### Task 14: Use Archiving + +Create the playbook `/home/automation/plays/playbooks/archive.yml` that runs on hosts in the '**database**' host group and does the following: + ++ A file `/mnt/mysql_backups/database_list.txt` is created that contains the following line: `dev,test,qa,prod`. ++ A gzip archive of the file `/mnt/mysql_backups/database_list.txt` is created and stored in `/mnt/mysql_backups/archive.gz`. + +### Task 15: Work with Ansible Facts + +Create the playbook `/home/automation/plays/playbooks/facts.yml` that runs on hosts in the '**database**' host group and does the following: + ++ A custom Ansible fact `server_role=mysql` is created that can be retrieved from `ansible_local.custom.sample_exam` when using Ansible setup module. + +### Task 16: Software Packages + +Create the playbook `/home/automation/plays/playbooks/packages.yml` that runs on all inventory hosts and does the following: + ++ Installs '**tcpdump**' and '**mailx**' packages on hosts in the '**proxy**' host groups. ++ Installs '**lsof**' and '**mailx**' and packages on hosts in the '**database**' host groups. + +### Task 17: Services + +Create the playbook `/home/automation/plays/playbooks/target.yml` that runs on hosts in the '**webservers**' host group and does the following: + ++ Sets the default boot target to '**multi-user**'. ++ Displays a message when the target is already set. + +### Task 18. Create and Use Templates to Create Customized Configuration Files + +Create the playbook `/home/automation/plays/playbooks/server_list.yml` that does the following: + ++ Playbook uses a Jinja2 template `server_list.j2` to create a file `/etc/server_list.txt` on hosts in the '**database**' host group. ++ The file `/etc/server_list.txt` is owned by the '**automation**' user. ++ File permissions are set to '**0600**'. ++ SELinux file label should be set to '**net_conf_t**'. ++ The content of the file is a list of FQDNs of all inventory hosts. + +After running the playbook, the content of the file `/etc/server_list.txt` should be the following: + +``` +node1.ansi.example.com node2.ansi.example.com node3.ansi.example.com +``` + +> [!important] +> If the FQDN of any inventory host changes, re-running the playbook should update the file with the new values. diff --git a/practice_exams/exam1/answers/adhoc.sh b/practice_exams/exam1/answers/adhoc.sh new file mode 100644 index 0000000..0cb7277 --- /dev/null +++ b/practice_exams/exam1/answers/adhoc.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +ansible all -m group -a 'name=automation' -u vagrant -b -k +ansible all -m user -a 'name=automation \ + group=automation \ + groups=wheel \ + append=yes' -u vagrant -b -k +ansible all -m file -a 'path=/home/automation/.ssh \ + state=directory \ + owner=automation \ + group=automation \ + mode=0700' -u vagrant -b -k +ansible all -m lineinfile -a 'path=/home/automation/.ssh/authorized_keys \ + create=yes \ + owner=automation \ + group=automation \ + mode=0600 \ + line="ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC84L3g/uFMnvDyM0ZIX33EvWIM/KMM0fZVdxhQGrt4ZMqakKOWXUurIA5A/gcUyx+41mmmkLcxZFjbI/j4nbX/qCvm3GOWe4MTTrhawKxjzxhZbKREzk73vC3UJpPvoxmg87W4xBleO70kfpyZ9hjSqPP3COEUnY37KEd/WmxPqFNd17ls6eRH1BpxvFZO/vTOioRMlF33dmxrqvuwr3SlDhEC6EKzSLr3bPDMxmD+KHA5x/Db6CkHSj3k9vkBj9hDlWHcrBtM7y9ZZTLwrORVKbldzOST8womG9wP625CkbDArDoFNAQ+Q1YaUXHGXBczoHzugr7iwFl7M9jDQViqOO3g6PlYPa+X8umt7vA6bUVz+CYOrcyJJ1dHrc861VZKkMa4UxgdRw98oW6p16cWIdjgl47I6WoRMo+T1SYgii66beBidP7ht24Bqng1e1DevKqeLWcqSdPvlBqZtiGHwJdBBBF9FrWc4x7WMq43bByV7BYXApa446M/IxRmT4U= automation"' -u vagrant -b -k +ansible all -m lineinfile -a "path=/etc/sudoers \ + regexp='^%wheel ALL=(ALL)' \ + line='%wheel ALL=(ALL) NOPASSWD: ALL' \ + validate='/usr/sbin/visudo -cf %s'" -u vagrant -b -k diff --git a/practice_exams/exam1/answers/ansible-template.cfg b/practice_exams/exam1/answers/ansible-template.cfg new file mode 100644 index 0000000..dd5ca8f --- /dev/null +++ b/practice_exams/exam1/answers/ansible-template.cfg @@ -0,0 +1,675 @@ +[defaults] +# (boolean) By default Ansible will issue a warning when received from a task action (module or action plugin) +# These warnings can be silenced by adjusting this setting to False. +;action_warnings=True + +# (list) Accept list of cowsay templates that are 'safe' to use, set to empty list if you want to enable all installed templates. +;cowsay_enabled_stencils=bud-frogs, bunny, cheese, daemon, default, dragon, elephant-in-snake, elephant, eyes, hellokitty, kitty, luke-koala, meow, milk, moofasa, moose, ren, sheep, small, stegosaurus, stimpy, supermilker, three-eyes, turkey, turtle, tux, udder, vader-koala, vader, www + +# (string) Specify a custom cowsay path or swap in your cowsay implementation of choice +;cowpath= + +# (string) This allows you to chose a specific cowsay stencil for the banners or use 'random' to cycle through them. +;cow_selection=default + +# (boolean) This option forces color mode even when running without a TTY or the "nocolor" setting is True. +;force_color=False + +# (path) The default root path for Ansible config files on the controller. +;home=~/.ansible + +# (boolean) This setting allows suppressing colorizing output, which is used to give a better indication of failure and status information. +;nocolor=False + +# (boolean) If you have cowsay installed but want to avoid the 'cows' (why????), use this. +;nocows=False + +# (boolean) Sets the default value for the any_errors_fatal keyword, if True, Task failures will be considered fatal errors. +;any_errors_fatal=False + +# (path) The password file to use for the become plugin. --become-password-file. +# If executable, it will be run and the resulting stdout will be used as the password. +;become_password_file= + +# (pathspec) Colon separated paths in which Ansible will search for Become Plugins. +;become_plugins={{ ANSIBLE_HOME ~ "/plugins/become:/usr/share/ansible/plugins/become" }} + +# (string) Chooses which cache plugin to use, the default 'memory' is ephemeral. +;fact_caching=memory + +# (string) Defines connection or path information for the cache plugin +;fact_caching_connection= + +# (string) Prefix to use for cache plugin files/tables +;fact_caching_prefix=ansible_facts + +# (integer) Expiration timeout for the cache plugin data +;fact_caching_timeout=86400 + +# (list) List of enabled callbacks, not all callbacks need enabling, but many of those shipped with Ansible do as we don't want them activated by default. +;callbacks_enabled= + +# (string) When a collection is loaded that does not support the running Ansible version (with the collection metadata key `requires_ansible`). +;collections_on_ansible_version_mismatch=warning + +# (pathspec) Colon separated paths in which Ansible will search for collections content. Collections must be in nested *subdirectories*, not directly in these directories. For example, if ``COLLECTIONS_PATHS`` includes ``'{{ ANSIBLE_HOME ~ "/collections" }}'``, and you want to add ``my.collection`` to that directory, it must be saved as ``'{{ ANSIBLE_HOME} ~ "/collections/ansible_collections/my/collection" }}'``. + +;collections_path={{ ANSIBLE_HOME ~ "/collections:/usr/share/ansible/collections" }} + +# (boolean) A boolean to enable or disable scanning the sys.path for installed collections +;collections_scan_sys_path=True + +# (path) The password file to use for the connection plugin. --connection-password-file. +;connection_password_file= + +# (pathspec) Colon separated paths in which Ansible will search for Action Plugins. +;action_plugins={{ ANSIBLE_HOME ~ "/plugins/action:/usr/share/ansible/plugins/action" }} + +# (boolean) When enabled, this option allows lookup plugins (whether used in variables as ``{{lookup('foo')}}`` or as a loop as with_foo) to return data that is not marked 'unsafe'. +# By default, such data is marked as unsafe to prevent the templating engine from evaluating any jinja2 templating language, as this could represent a security risk. This option is provided to allow for backward compatibility, however users should first consider adding allow_unsafe=True to any lookups which may be expected to contain data which may be run through the templating engine late +;allow_unsafe_lookups=False + +# (boolean) This controls whether an Ansible playbook should prompt for a login password. If using SSH keys for authentication, you probably do not need to change this setting. +;ask_pass=False + +# (boolean) This controls whether an Ansible playbook should prompt for a vault password. +;ask_vault_pass=False + +# (pathspec) Colon separated paths in which Ansible will search for Cache Plugins. +;cache_plugins={{ ANSIBLE_HOME ~ "/plugins/cache:/usr/share/ansible/plugins/cache" }} + +# (pathspec) Colon separated paths in which Ansible will search for Callback Plugins. +;callback_plugins={{ ANSIBLE_HOME ~ "/plugins/callback:/usr/share/ansible/plugins/callback" }} + +# (pathspec) Colon separated paths in which Ansible will search for Cliconf Plugins. +;cliconf_plugins={{ ANSIBLE_HOME ~ "/plugins/cliconf:/usr/share/ansible/plugins/cliconf" }} + +# (pathspec) Colon separated paths in which Ansible will search for Connection Plugins. +;connection_plugins={{ ANSIBLE_HOME ~ "/plugins/connection:/usr/share/ansible/plugins/connection" }} + +# (boolean) Toggles debug output in Ansible. This is *very* verbose and can hinder multiprocessing. Debug output can also include secret information despite no_log settings being enabled, which means debug mode should not be used in production. +;debug=False + +# (string) This indicates the command to use to spawn a shell under for Ansible's execution needs on a target. Users may need to change this in rare instances when shell usage is constrained, but in most cases it may be left as is. +;executable=/bin/sh + +# (string) This option allows you to globally configure a custom path for 'local_facts' for the implied :ref:`ansible_collections.ansible.builtin.setup_module` task when using fact gathering. +# If not set, it will fallback to the default from the ``ansible.builtin.setup`` module: ``/etc/ansible/facts.d``. +# This does **not** affect user defined tasks that use the ``ansible.builtin.setup`` module. +# The real action being created by the implicit task is currently ``ansible.legacy.gather_facts`` module, which then calls the configured fact modules, by default this will be ``ansible.builtin.setup`` for POSIX systems but other platforms might have different defaults. +;fact_path= + +# (pathspec) Colon separated paths in which Ansible will search for Jinja2 Filter Plugins. +;filter_plugins={{ ANSIBLE_HOME ~ "/plugins/filter:/usr/share/ansible/plugins/filter" }} + +# (boolean) This option controls if notified handlers run on a host even if a failure occurs on that host. +# When false, the handlers will not run if a failure has occurred on a host. +# This can also be set per play or on the command line. See Handlers and Failure for more details. +;force_handlers=False + +# (integer) Maximum number of forks Ansible will use to execute tasks on target hosts. +;forks=5 + +# (string) This setting controls the default policy of fact gathering (facts discovered about remote systems). +# This option can be useful for those wishing to save fact gathering time. Both 'smart' and 'explicit' will use the cache plugin. +;gathering=implicit + +# (list) Set the `gather_subset` option for the :ref:`ansible_collections.ansible.builtin.setup_module` task in the implicit fact gathering. See the module documentation for specifics. +# It does **not** apply to user defined ``ansible.builtin.setup`` tasks. +;gather_subset= + +# (integer) Set the timeout in seconds for the implicit fact gathering, see the module documentation for specifics. +# It does **not** apply to user defined :ref:`ansible_collections.ansible.builtin.setup_module` tasks. +;gather_timeout= + +# (string) This setting controls how duplicate definitions of dictionary variables (aka hash, map, associative array) are handled in Ansible. +# This does not affect variables whose values are scalars (integers, strings) or arrays. +# **WARNING**, changing this setting is not recommended as this is fragile and makes your content (plays, roles, collections) non portable, leading to continual confusion and misuse. Don't change this setting unless you think you have an absolute need for it. +# We recommend avoiding reusing variable names and relying on the ``combine`` filter and ``vars`` and ``varnames`` lookups to create merged versions of the individual variables. In our experience this is rarely really needed and a sign that too much complexity has been introduced into the data structures and plays. +# For some uses you can also look into custom vars_plugins to merge on input, even substituting the default ``host_group_vars`` that is in charge of parsing the ``host_vars/`` and ``group_vars/`` directories. Most users of this setting are only interested in inventory scope, but the setting itself affects all sources and makes debugging even harder. +# All playbooks and roles in the official examples repos assume the default for this setting. +# Changing the setting to ``merge`` applies across variable sources, but many sources will internally still overwrite the variables. For example ``include_vars`` will dedupe variables internally before updating Ansible, with 'last defined' overwriting previous definitions in same file. +# The Ansible project recommends you **avoid ``merge`` for new projects.** +# It is the intention of the Ansible developers to eventually deprecate and remove this setting, but it is being kept as some users do heavily rely on it. New projects should **avoid 'merge'**. +;hash_behaviour=replace + +# (pathlist) Comma separated list of Ansible inventory sources +;inventory=/etc/ansible/hosts + +# (pathspec) Colon separated paths in which Ansible will search for HttpApi Plugins. +;httpapi_plugins={{ ANSIBLE_HOME ~ "/plugins/httpapi:/usr/share/ansible/plugins/httpapi" }} + +# (float) This sets the interval (in seconds) of Ansible internal processes polling each other. Lower values improve performance with large playbooks at the expense of extra CPU load. Higher values are more suitable for Ansible usage in automation scenarios, when UI responsiveness is not required but CPU usage might be a concern. +# The default corresponds to the value hardcoded in Ansible <= 2.1 +;internal_poll_interval=0.001 + +# (pathspec) Colon separated paths in which Ansible will search for Inventory Plugins. +;inventory_plugins={{ ANSIBLE_HOME ~ "/plugins/inventory:/usr/share/ansible/plugins/inventory" }} + +# (string) This is a developer-specific feature that allows enabling additional Jinja2 extensions. +# See the Jinja2 documentation for details. If you do not know what these do, you probably don't need to change this setting :) +;jinja2_extensions=[] + +# (boolean) This option preserves variable types during template operations. +;jinja2_native=False + +# (boolean) Enables/disables the cleaning up of the temporary files Ansible used to execute the tasks on the remote. +# If this option is enabled it will disable ``ANSIBLE_PIPELINING``. +;keep_remote_files=False + +# (boolean) Controls whether callback plugins are loaded when running /usr/bin/ansible. This may be used to log activity from the command line, send notifications, and so on. Callback plugins are always loaded for ``ansible-playbook``. +;bin_ansible_callbacks=False + +# (tmppath) Temporary directory for Ansible to use on the controller. +;local_tmp={{ ANSIBLE_HOME ~ "/tmp" }} + +# (list) List of logger names to filter out of the log file +;log_filter= + +# (path) File to which Ansible will log on the controller. When empty logging is disabled. +;log_path= + +# (pathspec) Colon separated paths in which Ansible will search for Lookup Plugins. +;lookup_plugins={{ ANSIBLE_HOME ~ "/plugins/lookup:/usr/share/ansible/plugins/lookup" }} + +# (string) Sets the macro for the 'ansible_managed' variable available for :ref:`ansible_collections.ansible.builtin.template_module` and :ref:`ansible_collections.ansible.windows.win_template_module`. This is only relevant for those two modules. +;ansible_managed=Ansible managed + +# (string) This sets the default arguments to pass to the ``ansible`` adhoc binary if no ``-a`` is specified. +;module_args= + +# (string) Compression scheme to use when transferring Python modules to the target. +;module_compression=ZIP_DEFLATED + +# (string) Module to use with the ``ansible`` AdHoc command, if none is specified via ``-m``. +;module_name=command + +# (pathspec) Colon separated paths in which Ansible will search for Modules. +;library={{ ANSIBLE_HOME ~ "/plugins/modules:/usr/share/ansible/plugins/modules" }} + +# (pathspec) Colon separated paths in which Ansible will search for Module utils files, which are shared by modules. +;module_utils={{ ANSIBLE_HOME ~ "/plugins/module_utils:/usr/share/ansible/plugins/module_utils" }} + +# (pathspec) Colon separated paths in which Ansible will search for Netconf Plugins. +;netconf_plugins={{ ANSIBLE_HOME ~ "/plugins/netconf:/usr/share/ansible/plugins/netconf" }} + +# (boolean) Toggle Ansible's display and logging of task details, mainly used to avoid security disclosures. +;no_log=False + +# (boolean) Toggle Ansible logging to syslog on the target when it executes tasks. On Windows hosts this will disable a newer style PowerShell modules from writing to the event log. +;no_target_syslog=False + +# (raw) What templating should return as a 'null' value. When not set it will let Jinja2 decide. +;null_representation= + +# (integer) For asynchronous tasks in Ansible (covered in Asynchronous Actions and Polling), this is how often to check back on the status of those tasks when an explicit poll interval is not supplied. The default is a reasonably moderate 15 seconds which is a tradeoff between checking in frequently and providing a quick turnaround when something may have completed. +;poll_interval=15 + +# (path) Option for connections using a certificate or key file to authenticate, rather than an agent or passwords, you can set the default value here to avoid re-specifying --private-key with every invocation. +;private_key_file= + +# (boolean) Makes role variables inaccessible from other roles. +# This was introduced as a way to reset role variables to default values if a role is used more than once in a playbook. +;private_role_vars=False + +# (integer) Port to use in remote connections, when blank it will use the connection plugin default. +;remote_port= + +# (string) Sets the login user for the target machines +# When blank it uses the connection plugin's default, normally the user currently executing Ansible. +;remote_user= + +# (pathspec) Colon separated paths in which Ansible will search for Roles. +;roles_path={{ ANSIBLE_HOME ~ "/roles:/usr/share/ansible/roles:/etc/ansible/roles" }} + +# (string) Set the main callback used to display Ansible output. You can only have one at a time. +# You can have many other callbacks, but just one can be in charge of stdout. +# See :ref:`callback_plugins` for a list of available options. +;stdout_callback=default + +# (string) Set the default strategy used for plays. +;strategy=linear + +# (pathspec) Colon separated paths in which Ansible will search for Strategy Plugins. +;strategy_plugins={{ ANSIBLE_HOME ~ "/plugins/strategy:/usr/share/ansible/plugins/strategy" }} + +# (boolean) Toggle the use of "su" for tasks. +;su=False + +# (string) Syslog facility to use when Ansible logs to the remote target +;syslog_facility=LOG_USER + +# (pathspec) Colon separated paths in which Ansible will search for Terminal Plugins. +;terminal_plugins={{ ANSIBLE_HOME ~ "/plugins/terminal:/usr/share/ansible/plugins/terminal" }} + +# (pathspec) Colon separated paths in which Ansible will search for Jinja2 Test Plugins. +;test_plugins={{ ANSIBLE_HOME ~ "/plugins/test:/usr/share/ansible/plugins/test" }} + +# (integer) This is the default timeout for connection plugins to use. +;timeout=10 + +# (string) Default connection plugin to use, the 'smart' option will toggle between 'ssh' and 'paramiko' depending on controller OS and ssh versions +;transport=smart + +# (boolean) When True, this causes ansible templating to fail steps that reference variable names that are likely typoed. +# Otherwise, any '{{ template_expression }}' that contains undefined variables will be rendered in a template or ansible action line exactly as written. +;error_on_undefined_vars=True + +# (pathspec) Colon separated paths in which Ansible will search for Vars Plugins. +;vars_plugins={{ ANSIBLE_HOME ~ "/plugins/vars:/usr/share/ansible/plugins/vars" }} + +# (string) The vault_id to use for encrypting by default. If multiple vault_ids are provided, this specifies which to use for encryption. The --encrypt-vault-id cli option overrides the configured value. +;vault_encrypt_identity= + +# (string) The label to use for the default vault id label in cases where a vault id label is not provided +;vault_identity=default + +# (list) A list of vault-ids to use by default. Equivalent to multiple --vault-id args. Vault-ids are tried in order. +;vault_identity_list= + +# (string) If true, decrypting vaults with a vault id will only try the password from the matching vault-id +;vault_id_match=False + +# (path) The vault password file to use. Equivalent to --vault-password-file or --vault-id +# If executable, it will be run and the resulting stdout will be used as the password. +;vault_password_file= + +# (integer) Sets the default verbosity, equivalent to the number of ``-v`` passed in the command line. +;verbosity=0 + +# (boolean) Toggle to control the showing of deprecation warnings +;deprecation_warnings=True + +# (boolean) Toggle to control showing warnings related to running devel +;devel_warning=True + +# (boolean) Normally ``ansible-playbook`` will print a header for each task that is run. These headers will contain the name: field from the task if you specified one. If you didn't then ``ansible-playbook`` uses the task's action to help you tell which task is presently running. Sometimes you run many of the same action and so you want more information about the task to differentiate it from others of the same action. If you set this variable to True in the config then ``ansible-playbook`` will also include the task's arguments in the header. +# This setting defaults to False because there is a chance that you have sensitive values in your parameters and you do not want those to be printed. +# If you set this to True you should be sure that you have secured your environment's stdout (no one can shoulder surf your screen and you aren't saving stdout to an insecure file) or made sure that all of your playbooks explicitly added the ``no_log: True`` parameter to tasks which have sensitive values See How do I keep secret data in my playbook? for more information. +;display_args_to_stdout=False + +# (boolean) Toggle to control displaying skipped task/host entries in a task in the default callback +;display_skipped_hosts=True + +# (string) Root docsite URL used to generate docs URLs in warning/error text; must be an absolute URL with valid scheme and trailing slash. +;docsite_root_url=https://docs.ansible.com/ansible-core/ + +# (pathspec) Colon separated paths in which Ansible will search for Documentation Fragments Plugins. +;doc_fragment_plugins={{ ANSIBLE_HOME ~ "/plugins/doc_fragments:/usr/share/ansible/plugins/doc_fragments" }} + +# (string) By default Ansible will issue a warning when a duplicate dict key is encountered in YAML. +# These warnings can be silenced by adjusting this setting to False. +;duplicate_dict_key=warn + +# (boolean) Whether or not to enable the task debugger, this previously was done as a strategy plugin. +# Now all strategy plugins can inherit this behavior. The debugger defaults to activating when +# a task is failed on unreachable. Use the debugger keyword for more flexibility. +;enable_task_debugger=False + +# (boolean) Toggle to allow missing handlers to become a warning instead of an error when notifying. +;error_on_missing_handler=True + +# (list) Which modules to run during a play's fact gathering stage, using the default of 'smart' will try to figure it out based on connection type. +# If adding your own modules but you still want to use the default Ansible facts, you will want to include 'setup' or corresponding network module to the list (if you add 'smart', Ansible will also figure it out). +# This does not affect explicit calls to the 'setup' module, but does always affect the 'gather_facts' action (implicit or explicit). +;facts_modules=smart + +# (boolean) Set this to "False" if you want to avoid host key checking by the underlying tools Ansible uses to connect to the host +;host_key_checking=True + +# (boolean) Facts are available inside the `ansible_facts` variable, this setting also pushes them as their own vars in the main namespace. +# Unlike inside the `ansible_facts` dictionary, these will have an `ansible_` prefix. +;inject_facts_as_vars=True + +# (string) Path to the Python interpreter to be used for module execution on remote targets, or an automatic discovery mode. Supported discovery modes are ``auto`` (the default), ``auto_silent``, ``auto_legacy``, and ``auto_legacy_silent``. All discovery modes employ a lookup table to use the included system Python (on distributions known to include one), falling back to a fixed ordered list of well-known Python interpreter locations if a platform-specific default is not available. The fallback behavior will issue a warning that the interpreter should be set explicitly (since interpreters installed later may change which one is used). This warning behavior can be disabled by setting ``auto_silent`` or ``auto_legacy_silent``. The value of ``auto_legacy`` provides all the same behavior, but for backwards-compatibility with older Ansible releases that always defaulted to ``/usr/bin/python``, will use that interpreter if present. +;interpreter_python=auto + +# (boolean) If 'false', invalid attributes for a task will result in warnings instead of errors +;invalid_task_attribute_failed=True + +# (boolean) Toggle to control showing warnings related to running a Jinja version older than required for jinja2_native +;jinja2_native_warning=True + +# (boolean) By default Ansible will issue a warning when there are no hosts in the inventory. +# These warnings can be silenced by adjusting this setting to False. +;localhost_warning=True + +# (int) Maximum size of files to be considered for diff display +;max_diff_size=104448 + +# (list) List of extensions to ignore when looking for modules to load +# This is for rejecting script and binary module fallback extensions +;module_ignore_exts={{(REJECT_EXTS + ('.yaml', '.yml', '.ini'))}} + +# (list) TODO: write it +;network_group_modules=eos, nxos, ios, iosxr, junos, enos, ce, vyos, sros, dellos9, dellos10, dellos6, asa, aruba, aireos, bigip, ironware, onyx, netconf, exos, voss, slxos + +# (boolean) Previously Ansible would only clear some of the plugin loading caches when loading new roles, this led to some behaviours in which a plugin loaded in prevoius plays would be unexpectedly 'sticky'. This setting allows to return to that behaviour. +;old_plugin_cache_clear=False + +# (path) A number of non-playbook CLIs have a ``--playbook-dir`` argument; this sets the default value for it. +;playbook_dir= + +# (string) This sets which playbook dirs will be used as a root to process vars plugins, which includes finding host_vars/group_vars +;playbook_vars_root=top + +# (path) A path to configuration for filtering which plugins installed on the system are allowed to be used. +# See :ref:`plugin_filtering_config` for details of the filter file's format. +# The default is /etc/ansible/plugin_filters.yml +;plugin_filters_cfg= + +# (string) Attempts to set RLIMIT_NOFILE soft limit to the specified value when executing Python modules (can speed up subprocess usage on Python 2.x. See https://bugs.python.org/issue11284). The value will be limited by the existing hard limit. Default value of 0 does not attempt to adjust existing system-defined limits. +;python_module_rlimit_nofile=0 + +# (bool) This controls whether a failed Ansible playbook should create a .retry file. +;retry_files_enabled=False + +# (path) This sets the path in which Ansible will save .retry files when a playbook fails and retry files are enabled. +# This file will be overwritten after each run with the list of failed hosts from all plays. +;retry_files_save_path= + +# (str) This setting can be used to optimize vars_plugin usage depending on user's inventory size and play selection. +;run_vars_plugins=demand + +# (bool) This adds the custom stats set via the set_stats plugin to the default output +;show_custom_stats=False + +# (string) Action to take when a module parameter value is converted to a string (this does not affect variables). For string parameters, values such as '1.00', "['a', 'b',]", and 'yes', 'y', etc. will be converted by the YAML parser unless fully quoted. +# Valid options are 'error', 'warn', and 'ignore'. +# Since 2.8, this option defaults to 'warn' but will change to 'error' in 2.12. +;string_conversion_action=warn + +# (boolean) Allows disabling of warnings related to potential issues on the system running ansible itself (not on the managed hosts) +# These may include warnings about 3rd party packages or other conditions that should be resolved if possible. +;system_warnings=True + +# (boolean) This option defines whether the task debugger will be invoked on a failed task when ignore_errors=True is specified. +# True specifies that the debugger will honor ignore_errors, False will not honor ignore_errors. +;task_debugger_ignore_errors=True + +# (integer) Set the maximum time (in seconds) that a task can run for. +# If set to 0 (the default) there is no timeout. +;task_timeout=0 + +# (string) Make ansible transform invalid characters in group names supplied by inventory sources. +;force_valid_group_names=never + +# (boolean) Toggles the use of persistence for connections. +;use_persistent_connections=False + +# (bool) A toggle to disable validating a collection's 'metadata' entry for a module_defaults action group. Metadata containing unexpected fields or value types will produce a warning when this is True. +;validate_action_group_metadata=True + +# (list) Accept list for variable plugins that require it. +;vars_plugins_enabled=host_group_vars + +# (list) Allows to change the group variable precedence merge order. +;precedence=all_inventory, groups_inventory, all_plugins_inventory, all_plugins_play, groups_plugins_inventory, groups_plugins_play + +# (bool) Force 'verbose' option to use stderr instead of stdout +;verbose_to_stderr=False + +# (integer) For asynchronous tasks in Ansible (covered in Asynchronous Actions and Polling), this is how long, in seconds, to wait for the task spawned by Ansible to connect back to the named pipe used on Windows systems. The default is 5 seconds. This can be too low on slower systems, or systems under heavy load. +# This is not the total time an async command can run for, but is a separate timeout to wait for an async command to start. The task will only start to be timed against its async_timeout once it has connected to the pipe, so the overall maximum duration the task can take will be extended by the amount specified here. +;win_async_startup_timeout=5 + +# (list) Check all of these extensions when looking for 'variable' files which should be YAML or JSON or vaulted versions of these. +# This affects vars_files, include_vars, inventory and vars plugins among others. +;yaml_valid_extensions=.yml, .yaml, .json + + +[privilege_escalation] +# (boolean) Display an agnostic become prompt instead of displaying a prompt containing the command line supplied become method +;agnostic_become_prompt=True + +# (boolean) This setting controls if become is skipped when remote user and become user are the same. I.E root sudo to root. +# If executable, it will be run and the resulting stdout will be used as the password. +;become_allow_same_user=False + +# (boolean) Toggles the use of privilege escalation, allowing you to 'become' another user after login. +;become=False + +# (boolean) Toggle to prompt for privilege escalation password. +;become_ask_pass=False + +# (string) executable to use for privilege escalation, otherwise Ansible will depend on PATH +;become_exe= + +# (string) Flags to pass to the privilege escalation executable. +;become_flags= + +# (string) Privilege escalation method to use when `become` is enabled. +;become_method=sudo + +# (string) The user your login/remote user 'becomes' when using privilege escalation, most systems will use 'root' when no user is specified. +;become_user=root + + +[persistent_connection] +# (path) Specify where to look for the ansible-connection script. This location will be checked before searching $PATH. +# If null, ansible will start with the same directory as the ansible script. +;ansible_connection_path= + +# (int) This controls the amount of time to wait for response from remote device before timing out persistent connection. +;command_timeout=30 + +# (integer) This controls the retry timeout for persistent connection to connect to the local domain socket. +;connect_retry_timeout=15 + +# (integer) This controls how long the persistent connection will remain idle before it is destroyed. +;connect_timeout=30 + +# (path) Path to socket to be used by the connection persistence system. +;control_path_dir={{ ANSIBLE_HOME ~ "/pc" }} + + +[connection] +# (boolean) This is a global option, each connection plugin can override either by having more specific options or not supporting pipelining at all. +# Pipelining, if supported by the connection plugin, reduces the number of network operations required to execute a module on the remote server, by executing many Ansible modules without actual file transfer. +# It can result in a very significant performance improvement when enabled. +# However this conflicts with privilege escalation (become). For example, when using 'sudo:' operations you must first disable 'requiretty' in /etc/sudoers on all managed hosts, which is why it is disabled by default. +# This setting will be disabled if ``ANSIBLE_KEEP_REMOTE_FILES`` is enabled. +;pipelining=False + + +[colors] +# (string) Defines the color to use on 'Changed' task status +;changed=yellow + +# (string) Defines the default color to use for ansible-console +;console_prompt=white + +# (string) Defines the color to use when emitting debug messages +;debug=dark gray + +# (string) Defines the color to use when emitting deprecation messages +;deprecate=purple + +# (string) Defines the color to use when showing added lines in diffs +;diff_add=green + +# (string) Defines the color to use when showing diffs +;diff_lines=cyan + +# (string) Defines the color to use when showing removed lines in diffs +;diff_remove=red + +# (string) Defines the color to use when emitting error messages +;error=red + +# (string) Defines the color to use for highlighting +;highlight=white + +# (string) Defines the color to use when showing 'OK' task status +;ok=green + +# (string) Defines the color to use when showing 'Skipped' task status +;skip=cyan + +# (string) Defines the color to use on 'Unreachable' status +;unreachable=bright red + +# (string) Defines the color to use when emitting verbose messages. i.e those that show with '-v's. +;verbose=blue + +# (string) Defines the color to use when emitting warning messages +;warn=bright purple + + +[selinux] +# (boolean) This setting causes libvirt to connect to lxc containers by passing --noseclabel to virsh. This is necessary when running on systems which do not have SELinux. +;libvirt_lxc_noseclabel=False + +# (list) Some filesystems do not support safe operations and/or return inconsistent errors, this setting makes Ansible 'tolerate' those in the list w/o causing fatal errors. +# Data corruption may occur and writes are not always verified when a filesystem is in the list. +;special_context_filesystems=fuse, nfs, vboxsf, ramfs, 9p, vfat + + +[diff] +# (bool) Configuration toggle to tell modules to show differences when in 'changed' status, equivalent to ``--diff``. +;always=False + +# (integer) How many lines of context to show when displaying the differences between files. +;context=3 + + +[galaxy] +# (path) The directory that stores cached responses from a Galaxy server. +# This is only used by the ``ansible-galaxy collection install`` and ``download`` commands. +# Cache files inside this dir will be ignored if they are world writable. +;cache_dir={{ ANSIBLE_HOME ~ "/galaxy_cache" }} + +# (path) Collection skeleton directory to use as a template for the ``init`` action in ``ansible-galaxy collection``, same as ``--collection-skeleton``. +;collection_skeleton= + +# (list) patterns of files to ignore inside a Galaxy collection skeleton directory +;collection_skeleton_ignore=^.git$, ^.*/.git_keep$ + +# (bool) Disable GPG signature verification during collection installation. +;disable_gpg_verify=False + +# (bool) Some steps in ``ansible-galaxy`` display a progress wheel which can cause issues on certain displays or when outputing the stdout to a file. +# This config option controls whether the display wheel is shown or not. +# The default is to show the display wheel if stdout has a tty. +;display_progress= + +# (path) Configure the keyring used for GPG signature verification during collection installation and verification. +;gpg_keyring= + +# (boolean) If set to yes, ansible-galaxy will not validate TLS certificates. This can be useful for testing against a server with a self-signed certificate. +;ignore_certs= + +# (list) A list of GPG status codes to ignore during GPG signature verification. See L(https://github.com/gpg/gnupg/blob/master/doc/DETAILS#general-status-codes) for status code descriptions. +# If fewer signatures successfully verify the collection than `GALAXY_REQUIRED_VALID_SIGNATURE_COUNT`, signature verification will fail even if all error codes are ignored. +;ignore_signature_status_codes= + +# (str) The number of signatures that must be successful during GPG signature verification while installing or verifying collections. +# This should be a positive integer or all to indicate all signatures must successfully validate the collection. +# Prepend + to the value to fail if no valid signatures are found for the collection. +;required_valid_signature_count=1 + +# (path) Role skeleton directory to use as a template for the ``init`` action in ``ansible-galaxy``/``ansible-galaxy role``, same as ``--role-skeleton``. +;role_skeleton= + +# (list) patterns of files to ignore inside a Galaxy role or collection skeleton directory +;role_skeleton_ignore=^.git$, ^.*/.git_keep$ + +# (string) URL to prepend when roles don't specify the full URI, assume they are referencing this server as the source. +;server=https://galaxy.ansible.com + +# (list) A list of Galaxy servers to use when installing a collection. +# The value corresponds to the config ini header ``[galaxy_server.{{item}}]`` which defines the server details. +# See :ref:`galaxy_server_config` for more details on how to define a Galaxy server. +# The order of servers in this list is used to as the order in which a collection is resolved. +# Setting this config option will ignore the :ref:`galaxy_server` config option. +;server_list= + +# (path) Local path to galaxy access token file +;token_path={{ ANSIBLE_HOME ~ "/galaxy_token" }} + + +[inventory] +# (string) This setting changes the behaviour of mismatched host patterns, it allows you to force a fatal error, a warning or just ignore it +;host_pattern_mismatch=warning + +# (boolean) If 'true', it is a fatal error when any given inventory source cannot be successfully parsed by any available inventory plugin; otherwise, this situation only attracts a warning. + +;any_unparsed_is_failed=False + +# (bool) Toggle to turn on inventory caching. +# This setting has been moved to the individual inventory plugins as a plugin option :ref:`inventory_plugins`. +# The existing configuration settings are still accepted with the inventory plugin adding additional options from inventory configuration. +# This message will be removed in 2.16. +;cache=False + +# (string) The plugin for caching inventory. +# This setting has been moved to the individual inventory plugins as a plugin option :ref:`inventory_plugins`. +# The existing configuration settings are still accepted with the inventory plugin adding additional options from inventory and fact cache configuration. +# This message will be removed in 2.16. +;cache_plugin= + +# (string) The inventory cache connection. +# This setting has been moved to the individual inventory plugins as a plugin option :ref:`inventory_plugins`. +# The existing configuration settings are still accepted with the inventory plugin adding additional options from inventory and fact cache configuration. +# This message will be removed in 2.16. +;cache_connection= + +# (string) The table prefix for the cache plugin. +# This setting has been moved to the individual inventory plugins as a plugin option :ref:`inventory_plugins`. +# The existing configuration settings are still accepted with the inventory plugin adding additional options from inventory and fact cache configuration. +# This message will be removed in 2.16. +;cache_prefix=ansible_inventory_ + +# (string) Expiration timeout for the inventory cache plugin data. +# This setting has been moved to the individual inventory plugins as a plugin option :ref:`inventory_plugins`. +# The existing configuration settings are still accepted with the inventory plugin adding additional options from inventory and fact cache configuration. +# This message will be removed in 2.16. +;cache_timeout=3600 + +# (list) List of enabled inventory plugins, it also determines the order in which they are used. +;enable_plugins=host_list, script, auto, yaml, ini, toml + +# (bool) Controls if ansible-inventory will accurately reflect Ansible's view into inventory or its optimized for exporting. +;export=False + +# (list) List of extensions to ignore when using a directory as an inventory source +;ignore_extensions={{(REJECT_EXTS + ('.orig', '.ini', '.cfg', '.retry'))}} + +# (list) List of patterns to ignore when using a directory as an inventory source +;ignore_patterns= + +# (bool) If 'true' it is a fatal error if every single potential inventory source fails to parse, otherwise this situation will only attract a warning. + +;unparsed_is_failed=False + +# (boolean) By default Ansible will issue a warning when no inventory was loaded and notes that it will use an implicit localhost-only inventory. +# These warnings can be silenced by adjusting this setting to False. +;inventory_unparsed_warning=True + + +[netconf_connection] +# (string) This variable is used to enable bastion/jump host with netconf connection. If set to True the bastion/jump host ssh settings should be present in ~/.ssh/config file, alternatively it can be set to custom ssh configuration file path to read the bastion/jump host settings. +;ssh_config= + + +[paramiko_connection] +# (boolean) TODO: write it +;host_key_auto_add=False + +# (boolean) TODO: write it +;look_for_keys=True + + +[jinja2] +# (list) This list of filters avoids 'type conversion' when templating variables +# Useful when you want to avoid conversion into lists or dictionaries for JSON strings, for example. +;dont_type_filters=string, to_json, to_nice_json, to_yaml, to_nice_yaml, ppretty, json + + +[tags] +# (list) default list of tags to run in your plays, Skip Tags has precedence. +;run= + +# (list) default list of tags to skip in your plays, has precedence over Run Tags +;skip= + diff --git a/practice_exams/exam1/answers/ansible.cfg b/practice_exams/exam1/answers/ansible.cfg new file mode 100644 index 0000000..c300739 --- /dev/null +++ b/practice_exams/exam1/answers/ansible.cfg @@ -0,0 +1,14 @@ +[defaults] + +roles_path = ./roles:/usr/share/ansible/roles +forks = 10 +become = false +inventory = ./inventory + +remote_user = automation +private_key_file = ./id_rsa +host_key_checking = false +vault_password_file = ./vault_key + +[galaxy] +server = https://old-galaxy.ansible.com diff --git a/practice_exams/exam1/answers/id_rsa b/practice_exams/exam1/answers/id_rsa new file mode 100644 index 0000000..963bd0d --- /dev/null +++ b/practice_exams/exam1/answers/id_rsa @@ -0,0 +1,38 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn +NhAAAAAwEAAQAAAYEAvOC94P7hTJ7w8jNGSF99xL1iDPyjDNH2VXcYUBq7eGTKmpCjll1L +qyAOQP4HFMsfuNZpppC3MWRY2yP4+J21/6gr5txjlnuDE064WsCsY88YWWykRM5O97wt1C +aT76MZoPO1uMQZXju9JH6cmfYY0qjz9wjhFJ2N+yhHf1psT6hTXde5bOnkR9QacbxWTv70 +zoqETJRd93Zsa6r7sK90pQ4RAuhCs0i692zwzMZg/ihwOcfw2+gpB0o95Pb5AY/YQ5Vh3K +wbTO8vWWUy8KzkVSm5Xczkk/MKJhvcD+tuQpGwwKw6BTQEPkNWGlFxxlwXM6B87oK+4sBZ +ezPYw0FYqjjt4Oj5WD2vl/Lpre7wOm1Fc/gmDq3MiSdXR63POtVWSpDGuFMYHUcPfKFuqd +enFiHY4JeOyOlqETKPk9UmIIouum3gYnT+4bduAap4NXtQ3ryqni1nKknT75QambYhh8CX +QQQRfRa1nOMe1jKuN2wclewWFwKWuOOjPyMUZk+FAAAFiDzJWSI8yVkiAAAAB3NzaC1yc2 +EAAAGBALzgveD+4Uye8PIzRkhffcS9Ygz8owzR9lV3GFAau3hkypqQo5ZdS6sgDkD+BxTL +H7jWaaaQtzFkWNsj+Pidtf+oK+bcY5Z7gxNOuFrArGPPGFlspETOTve8LdQmk++jGaDztb +jEGV47vSR+nJn2GNKo8/cI4RSdjfsoR39abE+oU13XuWzp5EfUGnG8Vk7+9M6KhEyUXfd2 +bGuq+7CvdKUOEQLoQrNIuvds8MzGYP4ocDnH8NvoKQdKPeT2+QGP2EOVYdysG0zvL1llMv +Cs5FUpuV3M5JPzCiYb3A/rbkKRsMCsOgU0BD5DVhpRccZcFzOgfO6CvuLAWXsz2MNBWKo4 +7eDo+Vg9r5fy6a3u8DptRXP4Jg6tzIknV0etzzrVVkqQxrhTGB1HD3yhbqnXpxYh2OCXjs +jpahEyj5PVJiCKLrpt4GJ0/uG3bgGqeDV7UN68qp4tZypJ0++UGpm2IYfAl0EEEX0WtZzj +HtYyrjdsHJXsFhcClrjjoz8jFGZPhQAAAAMBAAEAAAGBAJzBTPVJs8R6ePAaG+9+yQuaPa +EXn17Jds7Ri60XspUl2XxUJGBrx5wbe5j2+vuH5SjrUj26B0AHzzL4dO4pPd4TPXRZXpGK +qmtAvwIavDgNrWCyKNct/h3e4I4dAlQ1IdURzrSsk31AySZbqi6hL1LOg8N3bA5HAIn8kP +IiIpgt1BqjKjI5H4t5fgT80Qi40oYEMe64iBAUCcGF42NtCrrdpMKr7oeLChjFIkhhMChf +eVyLEtv/nuV8+UdorZpdPStAAD7pCWfdpZOKaBTkuuUEIZ8fzYo+d8AjjrQEBt5UQxbGa/ +JS1Lob3Jv160evf9hz9bicn1r2wbjpKtG/2sbf4yY/kGlAkVkOAI24hBJ6wj5fTcYWMSx3 +c5cmZIvnov9xrmPJXamjb+zygcGjgr+HYt3FkwtlAlLLjB56HRLYspYtMA680hAEOEFUfb +Z7c5EHTP5/hUjpxRK2Ly2FRQYp1cXhE23Lc7ytLYiK1SAJbX80IFABsyH8wVU/ksjZgQAA +AMEAsyUSPd9B7hV/tgmBSCEL3uN1/N3pZTeWYJJG3ilUJI/FqMkwBDekwmuuM8LLhuE4+b +b+cEoAv/zTtJivtADTfy/3PUy/OIaSqX9+Fyan7XLBIQxaOSu1KrHFGn7yW8eyZn98C0C8 +PcUqGHlsS0WzEPrGDm27eSs+5CoxCqUItlbDo3MpreKT0ew+eZ9S0wvrwtVPs1QUgRFVCr +nxHwHgaDNqZjyaJ8V/73djfcZ5B5W9w4BCgN3TkMCtmPVd/zgcAAAAwQDdrt5dV/moEdgg +WcR7irKEZyWFfPxOB5CMj7QAmmvwfkXRExiW4ZNQFBC477dWgEuOu5sxaGLSVHlUyVLsBx +H8AHJUjpoARO9QiNdXJnfibYPKNXwIc0BdpbgjHAqZj3Q+ytkHK1n+4En9zEVqh9OyeubN +daYA/DwGqNfApORZyaDujjFwBgcZTSMArhVfngeicey/CSLAB4AeXOfbJPy1SFv3yKpykx +jyBtztmdee5XSodySkH7EJ+2EBS4vvp2UAAADBANod1CaxBBFbjDlBrD2QGwSBRji1D0u7 +hggtFSoi4mOR5KUylBYeyQjgyLh53Oamqgi5J/WZoL2xHxgDpVj2rTKWb9ZirAB7/4sAFs +FRaoP+NZU2l95wUeX8aw0olvqJ5QszURgwngdaOvLHevHhm6hSWdZIXRP3kGbiHUDd4hEN +dqF7X7mPCj90am15wdgdCGnCSTtsOUSFVN1UUGvZma6KJ6RNS7gx9okqcYqTNe4J6a5tTn +h5GtxNtGH+hdvVoQAAAAphdXRvbWF0aW9uAQIDBAUGBw== +-----END OPENSSH PRIVATE KEY----- diff --git a/practice_exams/exam1/answers/id_rsa.pub b/practice_exams/exam1/answers/id_rsa.pub new file mode 100644 index 0000000..07481e5 --- /dev/null +++ b/practice_exams/exam1/answers/id_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC84L3g/uFMnvDyM0ZIX33EvWIM/KMM0fZVdxhQGrt4ZMqakKOWXUurIA5A/gcUyx+41mmmkLcxZFjbI/j4nbX/qCvm3GOWe4MTTrhawKxjzxhZbKREzk73vC3UJpPvoxmg87W4xBleO70kfpyZ9hjSqPP3COEUnY37KEd/WmxPqFNd17ls6eRH1BpxvFZO/vTOioRMlF33dmxrqvuwr3SlDhEC6EKzSLr3bPDMxmD+KHA5x/Db6CkHSj3k9vkBj9hDlWHcrBtM7y9ZZTLwrORVKbldzOST8womG9wP625CkbDArDoFNAQ+Q1YaUXHGXBczoHzugr7iwFl7M9jDQViqOO3g6PlYPa+X8umt7vA6bUVz+CYOrcyJJ1dHrc861VZKkMa4UxgdRw98oW6p16cWIdjgl47I6WoRMo+T1SYgii66beBidP7ht24Bqng1e1DevKqeLWcqSdPvlBqZtiGHwJdBBBF9FrWc4x7WMq43bByV7BYXApa446M/IxRmT4U= automation diff --git a/practice_exams/exam1/answers/inventory b/practice_exams/exam1/answers/inventory new file mode 100644 index 0000000..c06cf44 --- /dev/null +++ b/practice_exams/exam1/answers/inventory @@ -0,0 +1,10 @@ +[proxy] +node1.ansi.example.com ansible_host=192.168.55.201 + +[webservers] +node2.ansi.example.com ansible_host=192.168.55.202 +node3.ansi.example.com ansible_host=192.168.55.203 + +[database] +node3.ansi.example.com ansible_host=192.168.55.203 ansible_python_interpreter=/bin/python3 +node4.ansi.example.com ansible_host=192.168.55.204 diff --git a/practice_exams/exam1/answers/inventory_localhost b/practice_exams/exam1/answers/inventory_localhost new file mode 100644 index 0000000..2fbb50c --- /dev/null +++ b/practice_exams/exam1/answers/inventory_localhost @@ -0,0 +1 @@ +localhost diff --git a/practice_exams/exam1/answers/password b/practice_exams/exam1/answers/password new file mode 100644 index 0000000..d6a9762 --- /dev/null +++ b/practice_exams/exam1/answers/password @@ -0,0 +1 @@ +vagrant diff --git a/practice_exams/exam1/answers/playbooks/apache.yml b/practice_exams/exam1/answers/playbooks/apache.yml new file mode 100644 index 0000000..eebd5b8 --- /dev/null +++ b/practice_exams/exam1/answers/playbooks/apache.yml @@ -0,0 +1,7 @@ +--- +- hosts: webservers + become: yes + + + roles: + - sample-apache diff --git a/practice_exams/exam1/answers/playbooks/archive.yml b/practice_exams/exam1/answers/playbooks/archive.yml new file mode 100644 index 0000000..2eb9e6e --- /dev/null +++ b/practice_exams/exam1/answers/playbooks/archive.yml @@ -0,0 +1,17 @@ +--- +- hosts: database + become: yes + + tasks: + + - name: Create file + copy: + content: 'dev,test,qa,prod' + dest: /mnt/mysql_backups/database_list.txt + + - name: Create a tar.gz archive of a single file. + archive: + path: /mnt/mysql_backups/database_list.txt + dest: /mnt/mysql_backups/archive.gz + format: gz + diff --git a/practice_exams/exam1/answers/playbooks/facts.yml b/practice_exams/exam1/answers/playbooks/facts.yml new file mode 100644 index 0000000..f6f0e2c --- /dev/null +++ b/practice_exams/exam1/answers/playbooks/facts.yml @@ -0,0 +1,17 @@ +--- +- hosts: database + become: yes + + tasks: + + - name: Create fact.d + file: + path: /etc/ansible/facts.d + state: directory + + - name: Create file + copy: + content: | + [sample_exam] + server_role=mysql + dest: /etc/ansible/facts.d/custom.fact diff --git a/practice_exams/exam1/answers/playbooks/haproxy.yml b/practice_exams/exam1/answers/playbooks/haproxy.yml new file mode 100644 index 0000000..5e74856 --- /dev/null +++ b/practice_exams/exam1/answers/playbooks/haproxy.yml @@ -0,0 +1,20 @@ +--- +- hosts: all + become: yes + + tasks: + + - name: Confirms firewall is open + firewalld: + immediate: yes + permanent: yes + service: "{{ item }}" + state: enabled + with_items: + - http + when: "'proxy' in group_names" + + roles: + - name: geerlingguy.haproxy + when: "'proxy' in group_names" + diff --git a/practice_exams/exam1/answers/playbooks/motd.yml b/practice_exams/exam1/answers/playbooks/motd.yml new file mode 100644 index 0000000..c8d0d08 --- /dev/null +++ b/practice_exams/exam1/answers/playbooks/motd.yml @@ -0,0 +1,24 @@ +--- +- hosts: all + become: yes + tasks: + + - name: Set the welcome message + copy: + dest: /etc/motd + content: "Welcome to HAProxy server\n" + when: '"proxy" in group_names' + + - name: Set the welcome message + copy: + dest: /etc/motd + content: "Welcome to Apache server\n" + when: '"webservers" in group_names' + + - name: Set the welcome message + copy: + dest: /etc/motd + content: "Welcome to MySQL server\n" + when: '"database" in group_names' + + diff --git a/practice_exams/exam1/answers/playbooks/mysql.yml b/practice_exams/exam1/answers/playbooks/mysql.yml new file mode 100644 index 0000000..2a8070d --- /dev/null +++ b/practice_exams/exam1/answers/playbooks/mysql.yml @@ -0,0 +1,8 @@ +--- +- hosts: database + become: yes + + vars_files: ../vars/secret.yml + + roles: + - sample-mysql diff --git a/practice_exams/exam1/answers/playbooks/packages.yml b/practice_exams/exam1/answers/playbooks/packages.yml new file mode 100644 index 0000000..24e4622 --- /dev/null +++ b/practice_exams/exam1/answers/playbooks/packages.yml @@ -0,0 +1,18 @@ +--- +- hosts: all + become: yes + tasks: + + - name: Installs packages + dnf: + name: + - tcpdump + - mailx + when: "'proxy' in group_names" + + - name: Installs packages + dnf: + name: + - lsof + - mailx + when: "'database' in group_names" diff --git a/practice_exams/exam1/answers/playbooks/regular_tasks.yml b/practice_exams/exam1/answers/playbooks/regular_tasks.yml new file mode 100644 index 0000000..356a42b --- /dev/null +++ b/practice_exams/exam1/answers/playbooks/regular_tasks.yml @@ -0,0 +1,14 @@ +--- +- hosts: proxy + become: yes + + tasks: + + - name: Creates cron for root + cron: + #hour: * + #minute: 0 + name: Cron for task 7 + special_time: 'hourly' + job: date &> /var/log/time.log + diff --git a/practice_exams/exam1/answers/playbooks/repository.yml b/practice_exams/exam1/answers/playbooks/repository.yml new file mode 100644 index 0000000..741d567 --- /dev/null +++ b/practice_exams/exam1/answers/playbooks/repository.yml @@ -0,0 +1,29 @@ +--- +- hosts: all + become: yes + + tasks: + + - name: Creates the RPMS repo + copy: + dest: /etc/yum.repos.d/rpms.repo + content: | + [BaseOS] + name=BaseOS on repo.ansi.example.com + baseurl=http://repo.ansi.example.com/BaseOS + enabled=1 + gpgcheck=0 + + [AppStream] + name=AppStream on repo.ansi.example.com + baseurl=http://repo.ansi.example.com/AppStream + enabled=1 + gpgcheck=0 + + - name: Disable IPA repo + lineinfile: + path: /etc/yum.repos.d/ipa.repo + regexp: '^enabled=*' + line: 'enabled=0' + ignore_errors: yes + diff --git a/practice_exams/exam1/answers/playbooks/selinux.yml b/practice_exams/exam1/answers/playbooks/selinux.yml new file mode 100644 index 0000000..4e439fa --- /dev/null +++ b/practice_exams/exam1/answers/playbooks/selinux.yml @@ -0,0 +1,11 @@ +--- +- hosts: webservers + become: yes + + vars: + selinux_booleans: + - { name: 'httpd_can_network_connect', state: 'on', persistent: 'yes' } + + roles: + - role: rhel-system-roles.selinux + diff --git a/practice_exams/exam1/answers/playbooks/server_list.j2 b/practice_exams/exam1/answers/playbooks/server_list.j2 new file mode 100644 index 0000000..deb192f --- /dev/null +++ b/practice_exams/exam1/answers/playbooks/server_list.j2 @@ -0,0 +1 @@ +{{ hostvars['node1.ansi.example.com'].ansible_fqdn }} {{ hostvars['node2.ansi.example.com'].ansible_fqdn }} {{ hostvars['node3.ansi.example.com'].ansible_fqdn }} diff --git a/practice_exams/exam1/answers/playbooks/server_list.yml b/practice_exams/exam1/answers/playbooks/server_list.yml new file mode 100644 index 0000000..52fb820 --- /dev/null +++ b/practice_exams/exam1/answers/playbooks/server_list.yml @@ -0,0 +1,14 @@ +--- +- hosts: all + become: yes + tasks: + + - name: Template + template: + src: server_list.j2 + dest: /etc/server_list.txt + owner: automation + mode: 0600 + setype: net_conf_t + when: "'database' in group_names" + diff --git a/practice_exams/exam1/answers/playbooks/sshd.yml b/practice_exams/exam1/answers/playbooks/sshd.yml new file mode 100644 index 0000000..1084f13 --- /dev/null +++ b/practice_exams/exam1/answers/playbooks/sshd.yml @@ -0,0 +1,24 @@ +--- +- hosts: all + become: yes + tasks: + + - name: + lineinfile: + path: /etc/ssh/sshd_config + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + insertafter: "{{ item.insertafter }}" + backup: yes + loop: + - { regexp: '^Banner*', line: 'Banner /etc/motd', insertafter: '^#Banner*' } + - { regexp: '^X11Forwarding*', line: 'X11Forwarding no', insertafter: '^#GatewayPorts*' } + - { regexp: '^MaxAuthTries*', line: 'MaxAuthTries 3', insertafter: '^#MaxAuthTries*' } + notify: "Restart SSHD" + + handlers: + - name: Restarts SSHD + systemd: + name: sshd.service + state: restarted + listen: "Restart SSHD" diff --git a/practice_exams/exam1/answers/playbooks/sysctl.yml b/practice_exams/exam1/answers/playbooks/sysctl.yml new file mode 100644 index 0000000..d082590 --- /dev/null +++ b/practice_exams/exam1/answers/playbooks/sysctl.yml @@ -0,0 +1,19 @@ +--- +- hosts: all + become: yes + + tasks: + + - sysctl: + name: vm.swappiness + value: '10' + sysctl_set: yes + state: present + reload: yes + when: ansible_memtotal_mb > 512 + + - name: Displays less + debug: + msg: "Server memory less than 512MB" + when: ansible_memtotal_mb < 512 + diff --git a/practice_exams/exam1/answers/playbooks/target.yml b/practice_exams/exam1/answers/playbooks/target.yml new file mode 100644 index 0000000..5a75488 --- /dev/null +++ b/practice_exams/exam1/answers/playbooks/target.yml @@ -0,0 +1,18 @@ +--- +- hosts: webservers + become: yes + tasks: + + - name: gets the default target + command: systemctl get-default + register: get_target + changed_when: false + + - name: Output value + debug: + msg: "Already multi-user.target" + when: get_target.stdout == 'multi-user.target' + + - name: Sets default target + command: systemctl set-default multi-user.target + when: get_target.stdout != 'multi-user.target' diff --git a/practice_exams/exam1/answers/playbooks/users.yml b/practice_exams/exam1/answers/playbooks/users.yml new file mode 100644 index 0000000..850688c --- /dev/null +++ b/practice_exams/exam1/answers/playbooks/users.yml @@ -0,0 +1,86 @@ +--- +- hosts: all + become: yes + + vars_files: + - ../vars/user_list.yml + - ../vars/secret.yml + + + tasks: + + # - name: Print var + # debug: + # var: item.username + # #msg: "{{ item.uid|select('startswith', 1) }}" + # with_items: "{{ users }}" + # when: item.uid | string | regex_search('^1') + # #when: item.uid == 1201 + + + - name: Create webserver users + user: + name: "{{ item.username }}" + uid: "{{ item.uid }}" + groups: wheel + shell: '/bin/bash' + ssh_key_file: '.ssh/id_rsa' + update_password: on_create + password: "{{ user_password | password_hash('sha512') }}" + with_items: "{{ users }}" + when: + - item.uid | string | regex_search('^1') and 'webservers' in group_names + + - name: Create database users + user: + name: "{{ item.username }}" + uid: "{{ item.uid }}" + groups: wheel + shell: '/bin/bash' + ssh_key_file: '.ssh/id_rsa' + password: "{{ database_password | password_hash('sha512') }}" + update_password: on_create + with_items: "{{ users }}" + when: + - item.uid | string | regex_search('^2') and 'database' in group_names + + - name: Creates the .ssh folder for webserver users + file: + path: "/home/{{ item.username }}/.ssh" + state: directory + owner: "{{ item.username }}" + mode: 0700 + with_items: "{{ users }}" + when: + - item.uid | string | regex_search('^1') and 'webservers' in group_names + + - name: Creates the .ssh folder for database users + file: + path: "/home/{{ item.username }}/.ssh" + state: directory + owner: "{{ item.username }}" + mode: 0700 + with_items: "{{ users }}" + when: + - item.uid | string | regex_search('^2') and 'database' in group_names + + - name: Copy SSH key for webservers user + copy: + src: ../id_rsa + dest: "/home/{{ item.username }}/.ssh/id_rsa" + owner: "{{ item.username }}" + mode: 0700 + with_items: "{{ users }}" + when: + - item.uid | string | regex_search('^1') and 'webservers' in group_names + + - name: Copy SSH key for database user + copy: + src: ../id_rsa + dest: "/home/{{ item.username }}/.ssh/id_rsa" + owner: "{{ item.username }}" + mode: 0700 + with_items: "{{ users }}" + when: + - item.uid | string | regex_search('^2') and 'database' in group_names + diff --git a/practice_exams/exam1/answers/roles/geerlingguy.haproxy/.ansible-lint b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/.ansible-lint new file mode 100644 index 0000000..acc8255 --- /dev/null +++ b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/.ansible-lint @@ -0,0 +1,3 @@ +skip_list: + - 'yaml' + - 'role-name' diff --git a/practice_exams/exam1/answers/roles/geerlingguy.haproxy/.github/FUNDING.yml b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/.github/FUNDING.yml new file mode 100644 index 0000000..96b4938 --- /dev/null +++ b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/.github/FUNDING.yml @@ -0,0 +1,4 @@ +# These are supported funding model platforms +--- +github: geerlingguy +patreon: geerlingguy diff --git a/practice_exams/exam1/answers/roles/geerlingguy.haproxy/.github/stale.yml b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/.github/stale.yml new file mode 100644 index 0000000..3cc6ec3 --- /dev/null +++ b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/.github/stale.yml @@ -0,0 +1,57 @@ +# Configuration for probot-stale - https://github.com/probot/stale + +# Number of days of inactivity before an Issue or Pull Request becomes stale +daysUntilStale: 90 + +# Number of days of inactivity before an Issue or Pull Request with the stale label is closed. +# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. +daysUntilClose: 30 + +# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled) +onlyLabels: [] + +# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable +exemptLabels: + - bug + - pinned + - security + - planned + +# Set to true to ignore issues in a project (defaults to false) +exemptProjects: false + +# Set to true to ignore issues in a milestone (defaults to false) +exemptMilestones: false + +# Set to true to ignore issues with an assignee (defaults to false) +exemptAssignees: false + +# Label to use when marking as stale +staleLabel: stale + +# Limit the number of actions per hour, from 1-30. Default is 30 +limitPerRun: 30 + +pulls: + markComment: |- + This pull request has been marked 'stale' due to lack of recent activity. If there is no further activity, the PR will be closed in another 30 days. Thank you for your contribution! + + Please read [this blog post](https://www.jeffgeerling.com/blog/2020/enabling-stale-issue-bot-on-my-github-repositories) to see the reasons why I mark pull requests as stale. + + unmarkComment: >- + This pull request is no longer marked for closure. + + closeComment: >- + This pull request has been closed due to inactivity. If you feel this is in error, please reopen the pull request or file a new PR with the relevant details. + +issues: + markComment: |- + This issue has been marked 'stale' due to lack of recent activity. If there is no further activity, the issue will be closed in another 30 days. Thank you for your contribution! + + Please read [this blog post](https://www.jeffgeerling.com/blog/2020/enabling-stale-issue-bot-on-my-github-repositories) to see the reasons why I mark issues as stale. + + unmarkComment: >- + This issue is no longer marked for closure. + + closeComment: >- + This issue has been closed due to inactivity. If you feel this is in error, please reopen the issue or file a new issue with the relevant details. diff --git a/practice_exams/exam1/answers/roles/geerlingguy.haproxy/.github/workflows/ci.yml b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/.github/workflows/ci.yml new file mode 100644 index 0000000..d048cda --- /dev/null +++ b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/.github/workflows/ci.yml @@ -0,0 +1,66 @@ +--- +name: CI +'on': + pull_request: + push: + branches: + - master + schedule: + - cron: "30 5 * * 2" + +defaults: + run: + working-directory: 'geerlingguy.haproxy' + +jobs: + + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - name: Check out the codebase. + uses: actions/checkout@v2 + with: + path: 'geerlingguy.haproxy' + + - name: Set up Python 3. + uses: actions/setup-python@v2 + with: + python-version: '3.x' + + - name: Install test dependencies. + run: pip3 install yamllint + + - name: Lint code. + run: | + yamllint . + + molecule: + name: Molecule + runs-on: ubuntu-latest + strategy: + matrix: + distro: + - rockylinux8 + - ubuntu2004 + + steps: + - name: Check out the codebase. + uses: actions/checkout@v2 + with: + path: 'geerlingguy.haproxy' + + - name: Set up Python 3. + uses: actions/setup-python@v2 + with: + python-version: '3.x' + + - name: Install test dependencies. + run: pip3 install ansible molecule[docker] docker + + - name: Run Molecule tests. + run: molecule test + env: + PY_COLORS: '1' + ANSIBLE_FORCE_COLOR: '1' + MOLECULE_DISTRO: ${{ matrix.distro }} diff --git a/practice_exams/exam1/answers/roles/geerlingguy.haproxy/.github/workflows/release.yml b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/.github/workflows/release.yml new file mode 100644 index 0000000..1d3d0b5 --- /dev/null +++ b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/.github/workflows/release.yml @@ -0,0 +1,40 @@ +--- +# This workflow requires a GALAXY_API_KEY secret present in the GitHub +# repository or organization. +# +# See: https://github.com/marketplace/actions/publish-ansible-role-to-galaxy +# See: https://github.com/ansible/galaxy/issues/46 + +name: Release +'on': + push: + tags: + - '*' + +defaults: + run: + working-directory: 'geerlingguy.haproxy' + +jobs: + + release: + name: Release + runs-on: ubuntu-latest + steps: + - name: Check out the codebase. + uses: actions/checkout@v2 + with: + path: 'geerlingguy.haproxy' + + - name: Set up Python 3. + uses: actions/setup-python@v2 + with: + python-version: '3.x' + + - name: Install Ansible. + run: pip3 install ansible-core + + - name: Trigger a new import on Galaxy. + run: >- + ansible-galaxy role import --api-key ${{ secrets.GALAXY_API_KEY }} + $(echo ${{ github.repository }} | cut -d/ -f1) $(echo ${{ github.repository }} | cut -d/ -f2) diff --git a/practice_exams/exam1/answers/roles/geerlingguy.haproxy/.gitignore b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/.gitignore new file mode 100644 index 0000000..8840c8f --- /dev/null +++ b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/.gitignore @@ -0,0 +1,5 @@ +*.retry +*/__pycache__ +*.pyc +.cache + diff --git a/practice_exams/exam1/answers/roles/geerlingguy.haproxy/.yamllint b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/.yamllint new file mode 100644 index 0000000..76a383c --- /dev/null +++ b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/.yamllint @@ -0,0 +1,10 @@ +--- +extends: default + +rules: + line-length: + max: 120 + level: warning + +ignore: | + .github/stale.yml diff --git a/practice_exams/exam1/answers/roles/geerlingguy.haproxy/LICENSE b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/LICENSE new file mode 100644 index 0000000..4275cf3 --- /dev/null +++ b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2017 Jeff Geerling + +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: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +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. diff --git a/practice_exams/exam1/answers/roles/geerlingguy.haproxy/README.md b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/README.md new file mode 100644 index 0000000..0224312 --- /dev/null +++ b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/README.md @@ -0,0 +1,81 @@ +# Ansible Role: HAProxy + +[![CI](https://github.com/geerlingguy/ansible-role-haproxy/workflows/CI/badge.svg?event=push)](https://github.com/geerlingguy/ansible-role-haproxy/actions?query=workflow%3ACI) + +Installs HAProxy on RedHat/CentOS and Debian/Ubuntu Linux servers. + +**Note**: This role _officially_ supports HAProxy versions 1.4 or 1.5. Future versions may require some rework. + +## Requirements + +None. + +## Role Variables + +Available variables are listed below, along with default values (see `defaults/main.yml`): + + haproxy_socket: /var/lib/haproxy/stats + +The socket through which HAProxy can communicate (for admin purposes or statistics). To disable/remove this directive, set `haproxy_socket: ''` (an empty string). + + haproxy_chroot: /var/lib/haproxy + +The jail directory where chroot() will be performed before dropping privileges. To disable/remove this directive, set `haproxy_chroot: ''` (an empty string). Only change this if you know what you're doing! + + haproxy_user: haproxy + haproxy_group: haproxy + +The user and group under which HAProxy should run. Only change this if you know what you're doing! + + haproxy_frontend_name: 'hafrontend' + haproxy_frontend_bind_address: '*' + haproxy_frontend_port: 80 + haproxy_frontend_mode: 'http' + +HAProxy frontend configuration directives. + + haproxy_backend_name: 'habackend' + haproxy_backend_mode: 'http' + haproxy_backend_balance_method: 'roundrobin' + haproxy_backend_httpchk: 'HEAD / HTTP/1.1\r\nHost:localhost' + +HAProxy backend configuration directives. + + haproxy_backend_servers: + - name: app1 + address: 192.168.0.1:80 + - name: app2 + address: 192.168.0.2:80 + +A list of backend servers (name and address) to which HAProxy will distribute requests. + + haproxy_connect_timeout: 5000 + haproxy_client_timeout: 50000 + haproxy_server_timeout: 50000 + +HAProxy default timeout configurations. + + haproxy_global_vars: + - 'ssl-default-bind-ciphers ABCD+KLMJ:...' + - 'ssl-default-bind-options no-sslv3' + +A list of extra global variables to add to the global configuration section inside `haproxy.cfg`. + +## Dependencies + +None. + +## Example Playbook + + - hosts: balancer + sudo: yes + roles: + - { role: geerlingguy.haproxy } + +## License + +MIT / BSD + +## Author Information + +This role was created in 2015 by [Jeff Geerling](https://www.jeffgeerling.com/), author of [Ansible for DevOps](https://www.ansiblefordevops.com/). diff --git a/practice_exams/exam1/answers/roles/geerlingguy.haproxy/defaults/main.yml b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/defaults/main.yml new file mode 100644 index 0000000..efc4c00 --- /dev/null +++ b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/defaults/main.yml @@ -0,0 +1,36 @@ +--- +haproxy_socket: /var/lib/haproxy/stats +haproxy_chroot: /var/lib/haproxy +haproxy_user: haproxy +haproxy_group: haproxy + +# Frontend settings. +haproxy_frontend_name: 'hafrontend' +haproxy_frontend_bind_address: '*' +haproxy_frontend_port: 80 +haproxy_frontend_mode: 'http' + +# Backend settings. +haproxy_backend_name: 'habackend' +haproxy_backend_mode: 'http' +haproxy_backend_balance_method: 'roundrobin' +haproxy_backend_httpchk: 'HEAD / HTTP/1.1\r\nHost:localhost' + +# List of backen d servers. +haproxy_backend_servers: + - name: node2 + address: "{{ hostvars['node2.ansi.example.com'].ansible_eth1.ipv4.address }}:80" + - name: node3 + address: "{{ hostvars['node3.ansi.example.com'].ansible_eth1.ipv4.address }}:80" +# - name: app1 +# address: 192.168.0.1:80 +# - name: app2 +# address: 192.168.0.2:80 + +# Extra global vars (see README for example usage). +haproxy_global_vars: [] + +# Default haproxy timeouts +haproxy_connect_timeout: 5000 +haproxy_client_timeout: 50000 +haproxy_server_timeout: 50000 diff --git a/practice_exams/exam1/answers/roles/geerlingguy.haproxy/handlers/main.yml b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/handlers/main.yml new file mode 100644 index 0000000..2de15f4 --- /dev/null +++ b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/handlers/main.yml @@ -0,0 +1,3 @@ +--- +- name: restart haproxy + service: name=haproxy state=restarted diff --git a/practice_exams/exam1/answers/roles/geerlingguy.haproxy/meta/.galaxy_install_info b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/meta/.galaxy_install_info new file mode 100644 index 0000000..c3619b6 --- /dev/null +++ b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/meta/.galaxy_install_info @@ -0,0 +1,2 @@ +install_date: Wed Nov 15 00:10:30 2023 +version: 1.3.1 diff --git a/practice_exams/exam1/answers/roles/geerlingguy.haproxy/meta/main.yml b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/meta/main.yml new file mode 100644 index 0000000..64dbdb4 --- /dev/null +++ b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/meta/main.yml @@ -0,0 +1,28 @@ +--- +dependencies: [] +# - role: sample-apache + +galaxy_info: + role_name: haproxy + author: geerlingguy + description: HAProxy installation and configuration. + company: "Midwestern Mac, LLC" + license: "license (BSD, MIT)" + min_ansible_version: 2.2 + platforms: + - name: EL + versions: + - 7 + - 8 + - name: Ubuntu + versions: + - precise + - trusty + - xenial + galaxy_tags: + - web + - networking + - cloud + - haproxy + - loadbalancer + - http diff --git a/practice_exams/exam1/answers/roles/geerlingguy.haproxy/molecule/default/converge.yml b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/molecule/default/converge.yml new file mode 100644 index 0000000..8a1de2e --- /dev/null +++ b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/molecule/default/converge.yml @@ -0,0 +1,22 @@ +--- +- name: Converge + hosts: all + become: true + + vars: + haproxy_socket: '' + haproxy_chroot: '' + haproxy_user: root + haproxy_group: root + + haproxy_backend_servers: + - name: app1 + address: 127.0.0.1:8080 + + pre_tasks: + - name: Update apt cache. + apt: update_cache=yes cache_valid_time=600 + when: ansible_os_family == 'Debian' + + roles: + - role: geerlingguy.haproxy diff --git a/practice_exams/exam1/answers/roles/geerlingguy.haproxy/molecule/default/molecule.yml b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/molecule/default/molecule.yml new file mode 100644 index 0000000..d291e5b --- /dev/null +++ b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/molecule/default/molecule.yml @@ -0,0 +1,19 @@ +--- +role_name_check: 1 +dependency: + name: galaxy +driver: + name: docker +platforms: + - name: instance + image: "geerlingguy/docker-${MOLECULE_DISTRO:-centos7}-ansible:latest" + command: ${MOLECULE_DOCKER_COMMAND:-""} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + cgroupns_mode: host + privileged: true + pre_build_image: true +provisioner: + name: ansible + playbooks: + converge: ${MOLECULE_PLAYBOOK:-converge.yml} diff --git a/practice_exams/exam1/answers/roles/geerlingguy.haproxy/tasks/main.yml b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/tasks/main.yml new file mode 100644 index 0000000..0f30afd --- /dev/null +++ b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/tasks/main.yml @@ -0,0 +1,32 @@ +--- +- name: Ensure HAProxy is installed. + package: name=haproxy state=present + +- name: Ensure HAProxy is enabled (so init script will start it on Debian). + lineinfile: + dest: /etc/default/haproxy + regexp: "^ENABLED.+$" + line: "ENABLED=1" + state: present + when: ansible_os_family == 'Debian' + +- name: Get HAProxy version. + command: haproxy -v + register: haproxy_version_result + changed_when: false + check_mode: false + +- name: Set HAProxy version. + set_fact: + haproxy_version: '{{ haproxy_version_result.stdout_lines[0] | regex_replace("^HA-?Proxy version (\d+(\.\d+)*).*$", "\1") }}' + +- name: Copy HAProxy configuration in place. + template: + src: haproxy.cfg.j2 + dest: /etc/haproxy/haproxy.cfg + mode: 0644 + validate: haproxy -f %s -c -q + notify: restart haproxy + +- name: Ensure HAProxy is started and enabled on boot. + service: name=haproxy state=started enabled=yes diff --git a/practice_exams/exam1/answers/roles/geerlingguy.haproxy/templates/haproxy.cfg.j2 b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/templates/haproxy.cfg.j2 new file mode 100644 index 0000000..63c088c --- /dev/null +++ b/practice_exams/exam1/answers/roles/geerlingguy.haproxy/templates/haproxy.cfg.j2 @@ -0,0 +1,56 @@ +global + log /dev/log local0 + log /dev/log local1 notice +{% if haproxy_socket != '' %} + stats socket {{ haproxy_socket }} level admin +{% endif %} +{% if haproxy_chroot != '' %} + chroot {{ haproxy_chroot }} +{% endif %} + user {{ haproxy_user }} + group {{ haproxy_group }} + daemon +{% for global_var in haproxy_global_vars %} + {{ global_var }} +{% endfor %} + +defaults + log global + mode http + option httplog + option dontlognull +{% if haproxy_version is version('1.4', '<=') %} + contimeout {{ haproxy_connect_timeout }} + clitimeout {{ haproxy_client_timeout }} + srvtimeout {{ haproxy_server_timeout }} +{% else %} + timeout connect {{ haproxy_connect_timeout }} + timeout client {{ haproxy_client_timeout }} + timeout server {{ haproxy_server_timeout }} +{% endif %} +{% if ansible_os_family == 'Debian' %} + errorfile 400 /etc/haproxy/errors/400.http + errorfile 403 /etc/haproxy/errors/403.http + errorfile 408 /etc/haproxy/errors/408.http + errorfile 500 /etc/haproxy/errors/500.http + errorfile 502 /etc/haproxy/errors/502.http + errorfile 503 /etc/haproxy/errors/503.http + errorfile 504 /etc/haproxy/errors/504.http +{% endif %} + +frontend {{ haproxy_frontend_name }} + bind {{ haproxy_frontend_bind_address }}:{{ haproxy_frontend_port }} + mode {{ haproxy_frontend_mode }} + default_backend {{ haproxy_backend_name }} + +backend {{ haproxy_backend_name }} + mode {{ haproxy_backend_mode }} + balance {{ haproxy_backend_balance_method }} + option forwardfor +{% if haproxy_backend_httpchk != '' %} + option httpchk {{ haproxy_backend_httpchk }} +{% endif %} + cookie SERVERID insert indirect +{% for backend in haproxy_backend_servers %} + server {{ backend.name }} {{ backend.address }} cookie {{ backend.name }} check +{% endfor %} diff --git a/practice_exams/exam1/answers/roles/sample-apache/README.md b/practice_exams/exam1/answers/roles/sample-apache/README.md new file mode 100644 index 0000000..225dd44 --- /dev/null +++ b/practice_exams/exam1/answers/roles/sample-apache/README.md @@ -0,0 +1,38 @@ +Role Name +========= + +A brief description of the role goes here. + +Requirements +------------ + +Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. + +Role Variables +-------------- + +A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. + +Dependencies +------------ + +A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. + +Example Playbook +---------------- + +Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: + + - hosts: servers + roles: + - { role: username.rolename, x: 42 } + +License +------- + +BSD + +Author Information +------------------ + +An optional section for the role authors to include contact information, or a website (HTML is not allowed). diff --git a/practice_exams/exam1/answers/roles/sample-apache/defaults/main.yml b/practice_exams/exam1/answers/roles/sample-apache/defaults/main.yml new file mode 100644 index 0000000..bcdee42 --- /dev/null +++ b/practice_exams/exam1/answers/roles/sample-apache/defaults/main.yml @@ -0,0 +1,2 @@ +--- +# defaults file for sample-apache \ No newline at end of file diff --git a/practice_exams/exam1/answers/roles/sample-apache/handlers/main.yml b/practice_exams/exam1/answers/roles/sample-apache/handlers/main.yml new file mode 100644 index 0000000..d29ac69 --- /dev/null +++ b/practice_exams/exam1/answers/roles/sample-apache/handlers/main.yml @@ -0,0 +1,7 @@ +--- +# handlers file for sample-apache +# +- systemd: + name: httpd + state: reloaded + listen: "Restart HTTPD" diff --git a/practice_exams/exam1/answers/roles/sample-apache/meta/main.yml b/practice_exams/exam1/answers/roles/sample-apache/meta/main.yml new file mode 100644 index 0000000..3a212a9 --- /dev/null +++ b/practice_exams/exam1/answers/roles/sample-apache/meta/main.yml @@ -0,0 +1,53 @@ +galaxy_info: + author: your name + description: your description + company: your company (optional) + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Choose a valid license ID from https://spdx.org - some suggested licenses: + # - BSD-3-Clause (default) + # - MIT + # - GPL-2.0-or-later + # - GPL-3.0-only + # - Apache-2.0 + # - CC-BY-4.0 + license: license (GPL-2.0-or-later, MIT, etc) + + min_ansible_version: 2.4 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + # platforms: + # - name: Fedora + # versions: + # - all + # - 25 + # - name: SomePlatform + # versions: + # - all + # - 1.0 + # - 7 + # - 99.99 + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. + \ No newline at end of file diff --git a/practice_exams/exam1/answers/roles/sample-apache/tasks/main.yml b/practice_exams/exam1/answers/roles/sample-apache/tasks/main.yml new file mode 100644 index 0000000..3eff473 --- /dev/null +++ b/practice_exams/exam1/answers/roles/sample-apache/tasks/main.yml @@ -0,0 +1,39 @@ +--- +# tasks file for sample-apache + +- name: Installs packages + dnf: + name: + - httpd + - mod_ssl + - php + update_cache: yes + +- name: Enables httpd + systemd: + name: httpd + enabled: yes + +- name: Open services + firewalld: + immediate: yes + permanent: yes + service: "{{ item }}" + state: enabled + with_items: + - http + - https + +- name: changes port + lineinfile: + path: /etc/httpd/conf/httpd.conf + regex: '^Listen*' + backup: yes + line: "Listen {{ ansible_eth1.ipv4.address }}:80" + notify: "Restart HTTPD" + +- name: Create index.html + template: + src: index.html.j2 + dest: /var/www/html/index.html + notify: "Restart HTTPD" diff --git a/practice_exams/exam1/answers/roles/sample-apache/templates/index.html.j2 b/practice_exams/exam1/answers/roles/sample-apache/templates/index.html.j2 new file mode 100644 index 0000000..459a613 --- /dev/null +++ b/practice_exams/exam1/answers/roles/sample-apache/templates/index.html.j2 @@ -0,0 +1 @@ +The address of the server is: "{{ ansible_eth1.ipv4.address }}" diff --git a/practice_exams/exam1/answers/roles/sample-apache/tests/inventory b/practice_exams/exam1/answers/roles/sample-apache/tests/inventory new file mode 100644 index 0000000..878877b --- /dev/null +++ b/practice_exams/exam1/answers/roles/sample-apache/tests/inventory @@ -0,0 +1,2 @@ +localhost + diff --git a/practice_exams/exam1/answers/roles/sample-apache/tests/test.yml b/practice_exams/exam1/answers/roles/sample-apache/tests/test.yml new file mode 100644 index 0000000..aed0df4 --- /dev/null +++ b/practice_exams/exam1/answers/roles/sample-apache/tests/test.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - sample-apache \ No newline at end of file diff --git a/practice_exams/exam1/answers/roles/sample-apache/vars/main.yml b/practice_exams/exam1/answers/roles/sample-apache/vars/main.yml new file mode 100644 index 0000000..843b0b1 --- /dev/null +++ b/practice_exams/exam1/answers/roles/sample-apache/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for sample-apache \ No newline at end of file diff --git a/practice_exams/exam1/answers/roles/sample-mysql/README.md b/practice_exams/exam1/answers/roles/sample-mysql/README.md new file mode 100644 index 0000000..225dd44 --- /dev/null +++ b/practice_exams/exam1/answers/roles/sample-mysql/README.md @@ -0,0 +1,38 @@ +Role Name +========= + +A brief description of the role goes here. + +Requirements +------------ + +Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. + +Role Variables +-------------- + +A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. + +Dependencies +------------ + +A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. + +Example Playbook +---------------- + +Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: + + - hosts: servers + roles: + - { role: username.rolename, x: 42 } + +License +------- + +BSD + +Author Information +------------------ + +An optional section for the role authors to include contact information, or a website (HTML is not allowed). diff --git a/practice_exams/exam1/answers/roles/sample-mysql/defaults/main.yml b/practice_exams/exam1/answers/roles/sample-mysql/defaults/main.yml new file mode 100644 index 0000000..5da4748 --- /dev/null +++ b/practice_exams/exam1/answers/roles/sample-mysql/defaults/main.yml @@ -0,0 +1,2 @@ +--- +# defaults file for sample-mysql \ No newline at end of file diff --git a/practice_exams/exam1/answers/roles/sample-mysql/handlers/main.yml b/practice_exams/exam1/answers/roles/sample-mysql/handlers/main.yml new file mode 100644 index 0000000..4d9e4b2 --- /dev/null +++ b/practice_exams/exam1/answers/roles/sample-mysql/handlers/main.yml @@ -0,0 +1,2 @@ +--- +# handlers file for sample-mysql \ No newline at end of file diff --git a/practice_exams/exam1/answers/roles/sample-mysql/meta/main.yml b/practice_exams/exam1/answers/roles/sample-mysql/meta/main.yml new file mode 100644 index 0000000..3a212a9 --- /dev/null +++ b/practice_exams/exam1/answers/roles/sample-mysql/meta/main.yml @@ -0,0 +1,53 @@ +galaxy_info: + author: your name + description: your description + company: your company (optional) + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Choose a valid license ID from https://spdx.org - some suggested licenses: + # - BSD-3-Clause (default) + # - MIT + # - GPL-2.0-or-later + # - GPL-3.0-only + # - Apache-2.0 + # - CC-BY-4.0 + license: license (GPL-2.0-or-later, MIT, etc) + + min_ansible_version: 2.4 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + # platforms: + # - name: Fedora + # versions: + # - all + # - 25 + # - name: SomePlatform + # versions: + # - all + # - 1.0 + # - 7 + # - 99.99 + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. + \ No newline at end of file diff --git a/practice_exams/exam1/answers/roles/sample-mysql/tasks/main.yml b/practice_exams/exam1/answers/roles/sample-mysql/tasks/main.yml new file mode 100644 index 0000000..51a29a0 --- /dev/null +++ b/practice_exams/exam1/answers/roles/sample-mysql/tasks/main.yml @@ -0,0 +1,104 @@ +--- +# tasks file for sample-mysql + +- name: check partition + command: fdisk -l /dev/sdb1 + register: partition_state + ignore_errors: yes + changed_when: false + +- debug: + var: partition_state.rc + +- name: Create partition + parted: + device: /dev/sdb + label: gpt + part_type: primary + number: 2 + part_end: 800MB + flags: [ lvm ] + state: present + when: partition_state.rc == 1 + +- name: Configure LVM volume group + lvg: + pvs: /dev/sdb1 + vg: vg_database + #force: yes + +- name: Create the LV + lvol: + lv: lv_mysql + size: 100%VG + vg: vg_database + +- name: Creates the filesystem + filesystem: + fstype: xfs + dev: /dev/mapper/vg_database-lv_mysql + + #- name: Create /mnt/mysql_backups + # file: + # path: /mnt/mysql_backups + # state: directory + +- name: Control active and configured mount points + mount: + path: /mnt/mysql_backups + src: /dev/mapper/vg_database-lv_mysql + state: mounted + fstype: xfs + opts: defaults + +- name: Install MariaDB + yum: + name: + - mariadb-server + - python3-PyMySQL + state: present + update_cache: yes + #enablerepo: apps + +- name: MySQL server config file + template: + src: my.cnf.j2 + dest: /etc/my.cnf.d/mariadb-server.cnf + backup: yes + +- name: Open 3306 on firewall + firewalld: + permanent: yes + service: mysql + immediate: yes + state: enabled + +- name: Enable mariadb + systemd: + name: mariadb + enabled: yes + state: started + +- name: Checks if the DB credentials exist + stat: + path: ~/.my.cnf + register: credentials_file + +- block: + + - name: Setup the root password + mysql_user: + login_unix_socket: /var/lib/mysql/mysql.sock + name: root + password: "{{ database_password }}" + + - name: Creates the DB credentials file + copy: + dest: ~/.my.cnf + content: | + [client] + user=root + password={{ database_password }} + + when: not credentials_file.stat.exists + diff --git a/practice_exams/exam1/answers/roles/sample-mysql/templates/my.cnf.j2 b/practice_exams/exam1/answers/roles/sample-mysql/templates/my.cnf.j2 new file mode 100644 index 0000000..f5e7c95 --- /dev/null +++ b/practice_exams/exam1/answers/roles/sample-mysql/templates/my.cnf.j2 @@ -0,0 +1,11 @@ +[mysqld] +bind_address = {{ ansible_default_ipv4.address }} +skip_name_resolve +datadir=/var/lib/mysql +socket=/var/lib/mysql/mysql.sock +symbolic-links=0 +sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES + +[mysqld_safe] +log-error=/var/log/mysqld.log +pid-file=/var/run/mysqld/mysqld.pid diff --git a/practice_exams/exam1/answers/roles/sample-mysql/tests/inventory b/practice_exams/exam1/answers/roles/sample-mysql/tests/inventory new file mode 100644 index 0000000..878877b --- /dev/null +++ b/practice_exams/exam1/answers/roles/sample-mysql/tests/inventory @@ -0,0 +1,2 @@ +localhost + diff --git a/practice_exams/exam1/answers/roles/sample-mysql/tests/test.yml b/practice_exams/exam1/answers/roles/sample-mysql/tests/test.yml new file mode 100644 index 0000000..a7001c5 --- /dev/null +++ b/practice_exams/exam1/answers/roles/sample-mysql/tests/test.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - sample-mysql \ No newline at end of file diff --git a/practice_exams/exam1/answers/roles/sample-mysql/vars/main.yml b/practice_exams/exam1/answers/roles/sample-mysql/vars/main.yml new file mode 100644 index 0000000..4f3ab4e --- /dev/null +++ b/practice_exams/exam1/answers/roles/sample-mysql/vars/main.yml @@ -0,0 +1,3 @@ +--- +# vars file for sample-mysql + diff --git a/practice_exams/exam1/answers/vars/secret.yml b/practice_exams/exam1/answers/vars/secret.yml new file mode 100644 index 0000000..d59fb2b --- /dev/null +++ b/practice_exams/exam1/answers/vars/secret.yml @@ -0,0 +1,8 @@ +$ANSIBLE_VAULT;1.1;AES256 +35653830333061333139306363636134326365313466666462646435363638623639303830356437 +3231346661393165653434393532386436666531626339350a613434356634393833363238326530 +66393066656432643531393961366565306132623863303566343832383761343637623366633036 +3931643862626335390a336163396336363033363731626466356630333735323962353037323362 +39396265666264376537643834323464376462633565363064633136343364666339396530613633 +34623039373864393130623639613634393032636561376663323130643163373366616635643033 +366565313330333334613665303330666362 diff --git a/practice_exams/exam1/answers/vars/user_list.yml b/practice_exams/exam1/answers/vars/user_list.yml new file mode 100644 index 0000000..24cb2d1 --- /dev/null +++ b/practice_exams/exam1/answers/vars/user_list.yml @@ -0,0 +1,12 @@ +$ANSIBLE_VAULT;1.1;AES256 +36366337303265613865613865316361333332613434323438663533326333646639316638363239 +6331643265313633646137363364393363633339643365390a373335333338656438306266303130 +61333831336464653561303437313834383362666139613934363361636337316561326664613033 +3034663633313963310a646232646430663165343162383734656339313034376331383132373232 +34326437623039353739383634393336363132636364633534393335336230336535336462653061 +66313837356265333134363839373233303033616563373830363831376434326166316137393333 +33386639336531346131653930343761316262383135623866373663363538376363633661613539 +30363734393935313335636439306132633931633764373634616330663239373961383939363235 +30386132663065626566333230643636636132613932303365353562656537353866663738656565 +35313661393930386561356139393538656262613564383639613032363662633233326238383332 +656636363461616266366639303830383466 diff --git a/practice_exams/exam1/answers/vault_key b/practice_exams/exam1/answers/vault_key new file mode 100644 index 0000000..e18b651 --- /dev/null +++ b/practice_exams/exam1/answers/vault_key @@ -0,0 +1 @@ +devops diff --git a/practice_exams/exam1/validation/ansible.cfg b/practice_exams/exam1/validation/ansible.cfg new file mode 100644 index 0000000..a58b3fb --- /dev/null +++ b/practice_exams/exam1/validation/ansible.cfg @@ -0,0 +1,11 @@ +[defaults] + +roles_path = ./roles +inventory = ./inventory + +remote_user = vagrant +private_key_file = ./id_rsa +host_key_checking = false + +display_skipped_hosts = false + diff --git a/practice_exams/exam1/validation/automation_id_rsa b/practice_exams/exam1/validation/automation_id_rsa new file mode 100644 index 0000000..963bd0d --- /dev/null +++ b/practice_exams/exam1/validation/automation_id_rsa @@ -0,0 +1,38 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn +NhAAAAAwEAAQAAAYEAvOC94P7hTJ7w8jNGSF99xL1iDPyjDNH2VXcYUBq7eGTKmpCjll1L +qyAOQP4HFMsfuNZpppC3MWRY2yP4+J21/6gr5txjlnuDE064WsCsY88YWWykRM5O97wt1C +aT76MZoPO1uMQZXju9JH6cmfYY0qjz9wjhFJ2N+yhHf1psT6hTXde5bOnkR9QacbxWTv70 +zoqETJRd93Zsa6r7sK90pQ4RAuhCs0i692zwzMZg/ihwOcfw2+gpB0o95Pb5AY/YQ5Vh3K +wbTO8vWWUy8KzkVSm5Xczkk/MKJhvcD+tuQpGwwKw6BTQEPkNWGlFxxlwXM6B87oK+4sBZ +ezPYw0FYqjjt4Oj5WD2vl/Lpre7wOm1Fc/gmDq3MiSdXR63POtVWSpDGuFMYHUcPfKFuqd +enFiHY4JeOyOlqETKPk9UmIIouum3gYnT+4bduAap4NXtQ3ryqni1nKknT75QambYhh8CX +QQQRfRa1nOMe1jKuN2wclewWFwKWuOOjPyMUZk+FAAAFiDzJWSI8yVkiAAAAB3NzaC1yc2 +EAAAGBALzgveD+4Uye8PIzRkhffcS9Ygz8owzR9lV3GFAau3hkypqQo5ZdS6sgDkD+BxTL +H7jWaaaQtzFkWNsj+Pidtf+oK+bcY5Z7gxNOuFrArGPPGFlspETOTve8LdQmk++jGaDztb +jEGV47vSR+nJn2GNKo8/cI4RSdjfsoR39abE+oU13XuWzp5EfUGnG8Vk7+9M6KhEyUXfd2 +bGuq+7CvdKUOEQLoQrNIuvds8MzGYP4ocDnH8NvoKQdKPeT2+QGP2EOVYdysG0zvL1llMv +Cs5FUpuV3M5JPzCiYb3A/rbkKRsMCsOgU0BD5DVhpRccZcFzOgfO6CvuLAWXsz2MNBWKo4 +7eDo+Vg9r5fy6a3u8DptRXP4Jg6tzIknV0etzzrVVkqQxrhTGB1HD3yhbqnXpxYh2OCXjs +jpahEyj5PVJiCKLrpt4GJ0/uG3bgGqeDV7UN68qp4tZypJ0++UGpm2IYfAl0EEEX0WtZzj +HtYyrjdsHJXsFhcClrjjoz8jFGZPhQAAAAMBAAEAAAGBAJzBTPVJs8R6ePAaG+9+yQuaPa +EXn17Jds7Ri60XspUl2XxUJGBrx5wbe5j2+vuH5SjrUj26B0AHzzL4dO4pPd4TPXRZXpGK +qmtAvwIavDgNrWCyKNct/h3e4I4dAlQ1IdURzrSsk31AySZbqi6hL1LOg8N3bA5HAIn8kP +IiIpgt1BqjKjI5H4t5fgT80Qi40oYEMe64iBAUCcGF42NtCrrdpMKr7oeLChjFIkhhMChf +eVyLEtv/nuV8+UdorZpdPStAAD7pCWfdpZOKaBTkuuUEIZ8fzYo+d8AjjrQEBt5UQxbGa/ +JS1Lob3Jv160evf9hz9bicn1r2wbjpKtG/2sbf4yY/kGlAkVkOAI24hBJ6wj5fTcYWMSx3 +c5cmZIvnov9xrmPJXamjb+zygcGjgr+HYt3FkwtlAlLLjB56HRLYspYtMA680hAEOEFUfb +Z7c5EHTP5/hUjpxRK2Ly2FRQYp1cXhE23Lc7ytLYiK1SAJbX80IFABsyH8wVU/ksjZgQAA +AMEAsyUSPd9B7hV/tgmBSCEL3uN1/N3pZTeWYJJG3ilUJI/FqMkwBDekwmuuM8LLhuE4+b +b+cEoAv/zTtJivtADTfy/3PUy/OIaSqX9+Fyan7XLBIQxaOSu1KrHFGn7yW8eyZn98C0C8 +PcUqGHlsS0WzEPrGDm27eSs+5CoxCqUItlbDo3MpreKT0ew+eZ9S0wvrwtVPs1QUgRFVCr +nxHwHgaDNqZjyaJ8V/73djfcZ5B5W9w4BCgN3TkMCtmPVd/zgcAAAAwQDdrt5dV/moEdgg +WcR7irKEZyWFfPxOB5CMj7QAmmvwfkXRExiW4ZNQFBC477dWgEuOu5sxaGLSVHlUyVLsBx +H8AHJUjpoARO9QiNdXJnfibYPKNXwIc0BdpbgjHAqZj3Q+ytkHK1n+4En9zEVqh9OyeubN +daYA/DwGqNfApORZyaDujjFwBgcZTSMArhVfngeicey/CSLAB4AeXOfbJPy1SFv3yKpykx +jyBtztmdee5XSodySkH7EJ+2EBS4vvp2UAAADBANod1CaxBBFbjDlBrD2QGwSBRji1D0u7 +hggtFSoi4mOR5KUylBYeyQjgyLh53Oamqgi5J/WZoL2xHxgDpVj2rTKWb9ZirAB7/4sAFs +FRaoP+NZU2l95wUeX8aw0olvqJ5QszURgwngdaOvLHevHhm6hSWdZIXRP3kGbiHUDd4hEN +dqF7X7mPCj90am15wdgdCGnCSTtsOUSFVN1UUGvZma6KJ6RNS7gx9okqcYqTNe4J6a5tTn +h5GtxNtGH+hdvVoQAAAAphdXRvbWF0aW9uAQIDBAUGBw== +-----END OPENSSH PRIVATE KEY----- diff --git a/practice_exams/exam1/validation/id_rsa b/practice_exams/exam1/validation/id_rsa new file mode 100644 index 0000000..00404e7 --- /dev/null +++ b/practice_exams/exam1/validation/id_rsa @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAozOkXjggSmQfRYOKdovQLBKvT37AhnvUsAKq4yvqX4SLvEp+ +ZeX0f+5OeWs1yr3t7G9GUi2awANtz6EYc1uBzhVSOJgExQev/HEZ+DqSp7ur0pyE +5kw2S5y9qBTnkrTaWLXuBaiOz8h4+oLg4mnX2nwg1klcuQpPLUOyV8matArdDAR7 +6wWwfNTEKICJdnRx/4iwMag6y6iqFwi8EX98RC6GGZ4OqstE82KGqEYK+dymHbQm +g07WziMU6KgYx5pVf4tM66BH0cEhQDYd1v+uy7f4LuezjgWC0Xi0vZzmttsCgVgn +HpFR2Z6BRTAU59ZdDmgeyi8eDwppL95+cmPBkQIDAQABAoIBABCLh7pVjlB8Xf86 +Gqtx+SS+sC8q9nGr1CAT5ScqqJQOZ+wq0S2bZnIhwqrkh4uKPbief06NeQbGUjee +aVAokrxFxRQftTwUT28UOEHGDmAa0oyDeaWvTEHWHhQQKnnhA9HCf+Lq969w73LW +Gd5aRJvNwbZ3sYLA3M4F8uqbcaeW2OZ6VdN1poUwegfjDsdkwHxbR3UPjktNyamR +m7QMP+M7Cbg1QrHlGYj52h0Teu1e61cuyTRuFIqkKi0TRKapV1imO8EWVodyCjkD +xBcnevGgeSIPF7cF3daK3YAwnZra046SxQR8WGvFfLpR6zIHt1Bt2mOQr8RYJBtG +Nc+A85ECgYEA0EO9Sk8tkG5q8X2++ut/tfNfj5gyNXZNZE/TdgXBqDnOcSNi/xuC +wtvC3QvQjkg7qKak4GSOlgz+qyDRw50xsEiQn3sQgTJAT2xuLi1ujYzS0xKp3cVF +FrBSp1eNFmpj+wk9ecWsmDVZzQi1x5DcZ89hWkmUhG+zUupXlSPdaMMCgYEAyJvE +BcS1EBJ1kP8FHVJBpagkqjgXuMcYztG3dZs7mJGVX0dW2Gp0nA8rpGmJXnPoeeqS +HDqFVxMb56b0AxjqfptoPn8fbyqASwFTOMI+SNAaNh7aW1QE0f1dYZY4ll5TpFBA +JSFbNitckvPv/pWXuqxo1gSR1zt4qy2MawNcJxsCgYEAiusUYXPNHdE5TpolAPSD +PJf5PywzGYwu9WF12Pzf/1mHxdnn1+i+4UF7irytwaqW+Nknk3If1iEW4olCwmuh +UEgnB+oryTH+ybu3BuBRJOQxYI/LdN14RzkX+P2iY7hVtoakVgywIts7alOMBXEw +Q6KF+paoFWr4v68G+rlwn8cCgYAj3y6rNWSHLjXVqrR4bMgOXkXIJmWfhgKaoQek +QRDkFExYkEIoSsj1SwUrzi9hM2rDuj1MTO6hBmq7/q+tihwMba+zVToCv9/XCbKe ++KT4kjXNrbCwGhMOlbbIB3uw78cXH76IpTFRO2m/YV1t8cQC/md0tbZ6fUjzmx57 +2Er3NwKBgB0HWHJ8eHA4zhnnI/VvK12wybERyNV1gF5Y9wxxtrqSolt536/3ZdUU +UIGjulfzrRZgH650yXsLWwxUEc+4wZJWYHrA6tXseuCPc5EfDeAybv+wYx1SE775 +RZSRZhdqK4UyU6XS/UbFebgNJGlfX4SOnKy9eoGSx1wnA0UKoN0c +-----END RSA PRIVATE KEY----- diff --git a/practice_exams/exam1/validation/index.html.j2 b/practice_exams/exam1/validation/index.html.j2 new file mode 100644 index 0000000..459a613 --- /dev/null +++ b/practice_exams/exam1/validation/index.html.j2 @@ -0,0 +1 @@ +The address of the server is: "{{ ansible_eth1.ipv4.address }}" diff --git a/practice_exams/exam1/validation/inventory b/practice_exams/exam1/validation/inventory new file mode 100644 index 0000000..15c0cc4 --- /dev/null +++ b/practice_exams/exam1/validation/inventory @@ -0,0 +1,13 @@ +[control] +localhost + +[proxy] +node1.ansi.example.com ansible_host=192.168.55.201 + +[webservers] +node2.ansi.example.com ansible_host=192.168.55.202 +node3.ansi.example.com ansible_host=192.168.55.203 + +[database] +node3.ansi.example.com ansible_host=192.168.55.203 +node4.ansi.example.com ansible_host=192.168.55.204 diff --git a/practice_exams/exam1/validation/my.cnf.j2 b/practice_exams/exam1/validation/my.cnf.j2 new file mode 100644 index 0000000..f5e7c95 --- /dev/null +++ b/practice_exams/exam1/validation/my.cnf.j2 @@ -0,0 +1,11 @@ +[mysqld] +bind_address = {{ ansible_default_ipv4.address }} +skip_name_resolve +datadir=/var/lib/mysql +socket=/var/lib/mysql/mysql.sock +symbolic-links=0 +sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES + +[mysqld_safe] +log-error=/var/log/mysqld.log +pid-file=/var/run/mysqld/mysqld.pid diff --git a/practice_exams/exam1/validation/server_list.j2 b/practice_exams/exam1/validation/server_list.j2 new file mode 100644 index 0000000..deb192f --- /dev/null +++ b/practice_exams/exam1/validation/server_list.j2 @@ -0,0 +1 @@ +{{ hostvars['node1.ansi.example.com'].ansible_fqdn }} {{ hostvars['node2.ansi.example.com'].ansible_fqdn }} {{ hostvars['node3.ansi.example.com'].ansible_fqdn }} diff --git a/practice_exams/exam1/validation/validate.yml b/practice_exams/exam1/validation/validate.yml new file mode 100644 index 0000000..dd34aef --- /dev/null +++ b/practice_exams/exam1/validation/validate.yml @@ -0,0 +1,1236 @@ +--- +- name: RHCE Exam 1 Validation + hosts: control + become: true + gather_facts: true + + tasks: + +#-- Task 1 --------------------------------------------------------------------- + + - name: Task 1 - Ansible Installation and Configuration + block: + + - name: Checks that automation user exists + user: + name: automation + register: automation_user_on_control + check_mode: true + failed_when: automation_user_on_control.changed == true + + - name: Run stat for files + stat: + path: "{{ item }}" + loop: + - '/home/automation/plays/ansible.cfg' + - '/home/automation/plays/inventory' + register: check_file_exists + + - name: Checking that all files were created + assert: + quiet: true + that: + - "{{ item.stat.isreg }}" + loop: "{{ check_file_exists.results }}" + loop_control: + label: "{{ item.stat.path }}" + + - name: Run stat for folders + stat: + path: "{{ item }}" + loop: + - '/home/automation/plays/' + - '/home/automation/plays/playbooks' + register: check_dir_exists + + - name: Checking that required directories were created + assert: + quiet: true + that: + - "{{ item.stat.isdir }}" + loop: "{{ check_dir_exists.results }}" + loop_control: + label: "{{ item.stat.path }}" + + - command: cat /home/automation/plays/ansible.cfg + register: ansible_config_content + changed_when: false + + - name: Check ansible.cfg configuration + assert: + that: + - "{{ ansible_config_content.stdout_lines}} | string | regex_search('{{ item }}')" + loop: + - 'roles_path *= *\./*roles' + - 'become *= *.alse' + - 'forks *= *10' + - 'remote_user *= *automation' + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 1 on control node' + + # - name: Force a failure in middle of recovery + # command: /bin/false + + tags: task1 + + +#-- Task 2 --------------------------------------------------------------------- + + - name: Task 2 - Ad-Hoc Commands on control node + block: + + - name: Run stat for files + stat: + path: "{{ item }}" + loop: + - '/home/automation/plays/adhoc.sh' + - '/home/automation/plays/id_rsa' + - '/home/automation/plays/id_rsa.pub' + register: check_file_exists + + - name: Checking that all files were created + assert: + quiet: true + that: + - "{{ item.stat.isreg }}" + fail_msg: "Missing {{ item.stat.path }} " + loop: "{{ check_file_exists.results }}" + loop_control: + label: "{{ item.stat.path }}" + + - name: Copies key + copy: + src: /home/automation/plays/id_rsa + dest: /vagrant/practice_exams/exam1/validation/automation_id_rsa + owner: vagrant + group: vagrant + remote_src: true + mode: 0600 + force: yes + changed_when: false + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 2 on control node' + + tags: task2 + +- hosts: proxy:database:webservers + become: true + remote_user: automation + + vars: + - ansible_ssh_private_key_file: /vagrant/practice_exams/exam1/validation/automation_id_rsa + + tasks: + - name: Task 2 - Ad-Hoc Commands on other nodes + block: + + - name: Checks login + shell: hostname > /dev/null + # remote_user: automation + # vars: + # - ansible_ssh_private_key_file: /home/automation/plays/id_rsa + changed_when: false + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 2' + + tags: task2 + +#-- Task 3 --------------------------------------------------------------------- + + + - name: Task 3 - File Content + block: + + - command: cat /etc/motd + register: motd_content + changed_when: false + + - name: Check motd content + assert: + that: + - "{{ motd_content.stdout_lines}} | string | regex_search('Welcome to HAProxy server')" + when: "'proxy' in group_names" + + - name: Check motd content for database + assert: + that: + - "{{ motd_content.stdout_lines}} | string | regex_search('Welcome to (MySQL|Apache server)')" + when: "'database' in group_names or 'webservers' in group_names" + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 3' + + tags: task3 + +#-- Task 4 --------------------------------------------------------------------- + + - name: Task 4 - Configure SSH Server + block: + + - command: cat /etc/ssh/sshd_config + register: sshd_content + changed_when: false + + - name: Check /etc/ssh/sshd_config configuration + assert: + that: + - "{{ sshd_content.stdout_lines}} | string | regex_search('{{ item }}')" + loop: + - 'Banner /etc/motd' + - 'X11Forwarding no' + - 'MaxAuthTries 3' + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 4' + + tags: task4 + + +#-- Task 5 --------------------------------------------------------------------- + +- hosts: control + gather_facts: false + become: true + + tasks: + + - name: Task 5 - Ansible Vault + block: + + - name: Run stat for files + stat: + path: "{{ item }}" + loop: + - '/home/automation/plays/vars/secret.yml' + - '/home/automation/plays/vault_key' + register: check_file_exists + + - name: Checking that all files were created + assert: + quiet: true + that: + - "{{ item.stat.isreg }}" + loop: "{{ check_file_exists.results }}" + loop_control: + label: "{{ item.stat.path }}" + + - command: cat /home/automation/plays/ansible.cfg + register: ansible_config_content + changed_when: false + + - name: Check ansible.cfg configuration + assert: + that: + - "{{ ansible_config_content.stdout_lines}} | string | regex_search('{{ item }}')" + loop: + - 'vault_password_file *= *\./*vault_key' + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 5' + + tags: task5 + +#-- Task 6 --------------------------------------------------------------------- + + - name: Task 6 - Users and Groups on control node + block: + + - name: Run stat for files + stat: + path: "{{ item }}" + loop: + - '/home/automation/plays/vars/user_list.yml' + register: check_file_exists + + - name: Checking that all files were created + assert: + quiet: true + that: + - "{{ item.stat.isreg }}" + loop: "{{ check_file_exists.results }}" + loop_control: + label: "{{ item.stat.path }}" + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 6' + + tags: task6 + + +- hosts: proxy:database:webservers + gather_facts: false + become: true + + vars: + - users: + - username: alice + uid: 1201 + - username: vincent + uid: 1202 + - username: sandy + uid: 2201 + - username: patrick + uid: 2202 + + tasks: + + - name: Task 6 - Users and Groups on other nodes + block: + + - name: Check webserver users + user: + name: "{{ item.username }}" + uid: "{{ item.uid }}" + groups: wheel + shell: '/bin/bash' + ssh_key_file: '.ssh/id_rsa' + with_items: "{{ users }}" + register: user_output + when: + - item.uid | string | regex_search('^1') and 'webservers' in group_names + check_mode: true + failed_when: user_output.changed == true + + - name: Check database users + user: + name: "{{ item.username }}" + uid: "{{ item.uid }}" + groups: wheel + shell: '/bin/bash' + ssh_key_file: '.ssh/id_rsa' + with_items: "{{ users }}" + register: user_output + when: + - item.uid | string | regex_search('^2') and 'database' in group_names + check_mode: true + failed_when: user_output.changed == true + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 6' + + tags: task6 + + +#-- Task 7 --------------------------------------------------------------------- + +- hosts: proxy + gather_facts: false + become: true + + tasks: + + - name: Task 7 - Scheduled Tasks + block: + + - name: Creates cron for root + cron: + name: Cron for task 7 + special_time: 'hourly' + job: date &> /var/log/time.log + register: crontab_output + check_mode: true + failed_when: crontab_output.changed == true + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 7' + + tags: task7 + + +#-- Task 8 --------------------------------------------------------------------- + +- hosts: proxy:database:webservers + gather_facts: false + become: true + + tasks: + + - name: Task 8 - Software Repositories + block: + + - name: Checking if IPA repo was disabled + lineinfile: + path: /etc/yum.repos.d/ipa.repo + regexp: '^enabled=*' + line: 'enabled=0' + register: check_ipa_repo + check_mode: true + failed_when: check_ipa_repo.changed == true + + - command: cat /etc/yum.repos.d/rpms.repo + register: rpms_repo_content + changed_when: false + + - name: Check ansible.cfg configuration + assert: + that: + - "{{ rpms_repo_content.stdout_lines}} | string | regex_search('{{ item }}')" + loop: + - '[BaseOS]' + - 'name *= *BaseOS on repo.ansi.example.com' + - 'baseurl*= *http://repo.ansi.example.com/BaseOS' + - '[AppStream]' + - 'name *= *AppStream on repo.ansi.example.com' + - 'baseurl*= *http://repo.ansi.example.com/AppStream' + - 'enabled*= *1' + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 8' + + tags: task8 + +#-- Task 9 --------------------------------------------------------------------- + +- hosts: control + gather_facts: false + become: true + + tasks: + + - name: Task 9 - Create and Work with Roles - MariaDB on control node + block: + + - name: Run stat for files + stat: + path: "{{ item }}" + loop: + - '/home/automation/plays/playbooks/mysql.yml' + register: check_file_exists + + - name: Checking that all files were created + assert: + quiet: true + that: + - "{{ item.stat.isreg }}" + loop: "{{ check_file_exists.results }}" + loop_control: + label: "{{ item.stat.path }}" + + - name: Run stat for folders + stat: + path: "{{ item }}" + loop: + - '/home/automation/plays/roles/sample-mysql' + register: check_dir_exists + + - name: Checking that required directories were created + assert: + quiet: true + that: + - "{{ item.stat.isdir }}" + loop: "{{ check_dir_exists.results }}" + loop_control: + label: "{{ item.stat.path }}" + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 9' + + tags: task9 + +- hosts: database + gather_facts: false + become: true + + vars: + - database_password: devops + + tasks: + + - name: Task 9 - Create and Work with Roles - MariaDB on database nodes + block: + + - name: Checks partition + command: fdisk -l /dev/sdb1 + changed_when: false + + - name: Checks the LVM volume group + lvg: + pvs: /dev/sdb1 + vg: vg_database + check_mode: true + + - name: Checks the LV + lvol: + lv: lv_mysql + size: 100%VG + vg: vg_database + check_mode: true + + - name: Checks the filesystem + filesystem: + fstype: xfs + dev: /dev/mapper/vg_database-lv_mysql + check_mode: true + + - name: Checks mount points + mount: + path: /mnt/mysql_backups + src: /dev/mapper/vg_database-lv_mysql + state: mounted + fstype: xfs + opts: defaults + check_mode: true + + - name: Checks MariaDB package + yum: + name: + - mariadb-server + - python3-PyMySQL + state: present + check_mode: true + + - name: Checks MySQL server config file + template: + src: my.cnf.j2 + dest: /etc/my.cnf.d/mariadb-server.cnf + backup: yes + check_mode: true + + - name: Checks port 3306 on firewall + firewalld: + permanent: yes + service: mysql + immediate: yes + state: enabled + check_mode: true + + - name: Checks mariadb service + systemd: + name: mariadb + enabled: yes + state: started + check_mode: true + + - name: Checks the DB credentials file + copy: + dest: ~/.my.cnf + content: | + [client] + user=root + password={{ database_password }} + check_mode: true + + - name: Tests MySQL login + mysql_db: + login_user: root + login_password: "{{ database_password }}" + login_unix_socket: /var/lib/mysql/mysql.sock + state: present + name: mysql + check_mode: true + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 9' + + tags: task9 + + +#-- Task 10 --------------------------------------------------------------------- + +- hosts: control + gather_facts: false + become: true + + tasks: + + - name: Task 10 - Create and Work with Roles - Apache on control + block: + + - name: Run stat for files + stat: + path: "{{ item }}" + loop: + - '/home/automation/plays/playbooks/apache.yml' + register: check_file_exists + + - name: Checking that all files were created + assert: + quiet: true + that: + - "{{ item.stat.isreg }}" + loop: "{{ check_file_exists.results }}" + loop_control: + label: "{{ item.stat.path }}" + + - name: Run stat for folders + stat: + path: "{{ item }}" + loop: + - '/home/automation/plays/roles/sample-apache' + register: check_dir_exists + + - name: Checking that required directories were created + assert: + quiet: true + that: + - "{{ item.stat.isdir }}" + loop: "{{ check_dir_exists.results }}" + loop_control: + label: "{{ item.stat.path }}" + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 10' + + tags: task10 + + +- hosts: webservers + gather_facts: false + become: true + + tasks: + + - name: Task 10 - Create and Work with Roles - Apache on webservers + block: + + - name: Checks packages + dnf: + name: + - httpd + - mod_ssl + - php + update_cache: yes + check_mode: true + register: checks_packages + failed_when: checks_packages.changed == true + + - name: Checks httpd service + systemd: + name: httpd + enabled: yes + state: started + check_mode: true + register: check_httpd_service + failed_when: check_httpd_service.changed == true + + - name: Checks firewalld + firewalld: + immediate: yes + permanent: yes + service: "{{ item }}" + state: enabled + with_items: + - http + - https + check_mode: true + register: check_firewalld + failed_when: check_firewalld.changed == true + + - name: Checks httpd.conf port + lineinfile: + path: /etc/httpd/conf/httpd.conf + regex: '^Listen*' + backup: yes + line: "Listen {{ ansible_eth1.ipv4.address }}:80" + check_mode: true + register: check_httpd_conf + failed_when: check_httpd_conf.changed == true + + - name: Checks /var/www/html/index.html + template: + src: index.html.j2 + dest: /var/www/html/index.html + check_mode: true + register: check_index_html + failed_when: check_index_html.changed == true + + - name: Checks curl + shell: | + curl -s {{ ansible_eth1.ipv4.address }} | grep -q \ + 'The address of the server is: "{{ ansible_eth1.ipv4.address }}"' + args: + warn: false + changed_when: false + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 10' + + tags: task10 + + +#-- Task 11--------------------------------------------------------------------- + +- hosts: control + gather_facts: false + become: true + + tasks: + + - name: Task 11 - Download Roles from Ansible Galaxy and Use Them on control + block: + + - name: Run stat for files + stat: + path: "{{ item }}" + loop: + - '/home/automation/plays/playbooks/haproxy.yml' + register: check_file_exists + + - name: Checking that all files were created + assert: + quiet: true + that: + - "{{ item.stat.isreg }}" + loop: "{{ check_file_exists.results }}" + loop_control: + label: "{{ item.stat.path }}" + + - name: Run stat for folders + stat: + path: "{{ item }}" + loop: + - '/home/automation/plays/roles/geerlingguy.haproxy' + register: check_dir_exists + + - name: Checking that required directories were created + assert: + quiet: true + that: + - "{{ item.stat.isdir }}" + loop: "{{ check_dir_exists.results }}" + loop_control: + label: "{{ item.stat.path }}" + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 11' + + tags: task11 + +- hosts: proxy + gather_facts: false + become: true + + tasks: + + - name: Task 11 - Download Roles from Ansible Galaxy and Use Them on proxy + block: + + - name: Checks /etc/haproxy/haproxy.cfg config + lineinfile: + path: /etc/haproxy/haproxy.cfg + regex: "{{ item.regex }}" + line: "{{ item.line }}" + loop: + - { regex: ' bind .*80', line: ' bind *:80' } + - { regex: ' balance roundrobin', line: ' balance roundrobin' } + - { regex: ' server node2', line: " server node2 {{ hostvars['node2.ansi.example.com'].ansible_eth1.ipv4.address }}:80 cookie node2 check" } + - { regex: ' server node3', line: " server node3 {{ hostvars['node3.ansi.example.com'].ansible_eth1.ipv4.address }}:80 cookie node3 check" } + check_mode: true + register: check_haproxy_cfg + failed_when: check_haproxy_cfg.changed == true + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 11' + + tags: task11 + +- hosts: control + gather_facts: false + become: true + + tasks: + + - name: Task 11 - Download Roles from Ansible Galaxy and Use Them on control + block: + + - name: Gets HAProxy first value + command: curl -s http://node1.ansi.example.com/ + register: curl_output1 + args: + warn: false + changed_when: false + + - name: Gets HAProxy first value + command: curl -s http://node1.ansi.example.com/ + register: curl_output2 + args: + warn: false + changed_when: false + + - name: Compares output + assert: + that: curl_output1.stdout != curl_output2.stdout + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 11' + + tags: task11 + + +#-- Task 12 -------------------------------------------------------------------- + +- hosts: control + gather_facts: false + become: true + + tasks: + + - name: Task 12 - Security on control + block: + + - name: Run stat for files + stat: + path: "{{ item }}" + loop: + - '/home/automation/plays/playbooks/selinux.yml' + register: check_file_exists + + - name: Checking that all files were created + assert: + quiet: true + that: + - "{{ item.stat.isreg }}" + loop: "{{ check_file_exists.results }}" + loop_control: + label: "{{ item.stat.path }}" + + - name: Checks if rhel-system-role is installed + dnf: + name: rhel-system-roles + state: present + check_mode: true + register: check_rhel_system_roles + failed_when: check_rhel_system_roles.changed == true + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 12' + + tags: task12 + +- hosts: webservers + gather_facts: false + become: true + + tasks: + + - name: Task 12 - Security on webservers + block: + + - name: Check SELinux boolean + seboolean: + name: httpd_can_network_connect + persistent: yes + state: yes + check_mode: true + register: check_selinux_bool + failed_when: check_selinux_bool.changed == true + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 12' + + tags: task12 + + +#-- Task 13 -------------------------------------------------------------------- + +- hosts: control + gather_facts: false + become: true + + tasks: + + - name: Task 13 - Use Contionals to Control Play Execution on control + block: + + - name: Run stat for files + stat: + path: "{{ item }}" + loop: + - '/home/automation/plays/playbooks/sysctl.yml' + register: check_file_exists + + - name: Checking that all files were created + assert: + quiet: true + that: + - "{{ item.stat.isreg }}" + loop: "{{ check_file_exists.results }}" + loop_control: + label: "{{ item.stat.path }}" + + +- hosts: proxy:database:webservers + gather_facts: false + become: true + + tasks: + + - name: Task 13 - Use Contionals to Control Play Execution on all + block: + + - name: Check sysctl + sysctl: + name: vm.swappiness + value: '10' + sysctl_set: yes + state: present + when: ansible_memtotal_mb > 512 + check_mode: true + register: check_sysctl + failed_when: check_sysctl.changed == true + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 13' + + tags: task13 + + +#-- Task 14 -------------------------------------------------------------------- + +- hosts: control + gather_facts: false + become: true + + tasks: + + - name: Task 14 - Use Archiving on control + block: + + - name: Run stat for files + stat: + path: "{{ item }}" + loop: + - '/home/automation/plays/playbooks/archive.yml' + register: check_file_exists + + - name: Checking that all files were created + assert: + quiet: true + that: + - "{{ item.stat.isreg }}" + loop: "{{ check_file_exists.results }}" + loop_control: + label: "{{ item.stat.path }}" + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 14' + + tags: task14 + +- hosts: database + gather_facts: false + become: true + + tasks: + + - name: Task 14 - Use Archiving on database + block: + + - name: Check create file + copy: + content: 'dev,test,qa,prod' + dest: /mnt/mysql_backups/database_list.txt + check_mode: true + register: check_database_list_file + failed_when: check_database_list_file.changed == true + + + - name: Create a tar.gz archive of a single file. + file: + path: /mnt/mysql_backups/archive.gz + check_mode: true + register: check_archive_file + failed_when: check_archive_file.changed == true + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 14' + + tags: task14 + +#-- Task 15 -------------------------------------------------------------------- + +- hosts: control + gather_facts: false + become: true + + tasks: + + - name: Task 15 - Work with Ansible Facts + block: + + - name: Run stat for files + stat: + path: "{{ item }}" + loop: + - '/home/automation/plays/playbooks/facts.yml' + register: check_file_exists + + - name: Checking that all files were created + assert: + quiet: true + that: + - "{{ item.stat.isreg }}" + loop: "{{ check_file_exists.results }}" + loop_control: + label: "{{ item.stat.path }}" + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 15' + + tags: task15 + +- hosts: database + become: yes + + tasks: + + - name: Task 15 - Work with Ansible Facts + block: + + - name: Check custom fact file + copy: + content: | + [sample_exam] + server_role=mysql + dest: /etc/ansible/facts.d/custom.fact + check_mode: true + register: check_custom_fact + failed_when: check_custom_fact.changed == true + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 15' + + tags: task15 + + +#-- Task 16 -------------------------------------------------------------------- + +- hosts: control + gather_facts: false + become: true + + tasks: + + - name: Task 16 - Software Packages on control + block: + + - name: Run stat for files + stat: + path: "{{ item }}" + loop: + - '/home/automation/plays/playbooks/packages.yml' + register: check_file_exists + + - name: Checking that all files were created + assert: + quiet: true + that: + - "{{ item.stat.isreg }}" + loop: "{{ check_file_exists.results }}" + loop_control: + label: "{{ item.stat.path }}" + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 16' + + tags: task16 + +- hosts: proxy:database + gather_facts: false + become: true + + tasks: + + - name: Task 16 - Software Packages on control + block: + + - name: Installs packages + dnf: + name: + - tcpdump + - mailx + when: "'proxy' in group_names" + check_mode: true + register: check_tcpdump_mailx + failed_when: check_tcpdump_mailx.changed == true + + - name: Installs packages + dnf: + name: + - lsof + - mailx + when: "'database' in group_names" + check_mode: true + register: check_lsof_mailx + failed_when: check_lsof_mailx.changed == true + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 16' + + tags: task16 + + +#-- Task 17 -------------------------------------------------------------------- + +- hosts: control + gather_facts: false + become: true + + tasks: + + - name: Task 17 - Services on control + block: + + - name: Run stat for files + stat: + path: "{{ item }}" + loop: + - '/home/automation/plays/playbooks/target.yml' + register: check_file_exists + + - name: Checking that all files were created + assert: + quiet: true + that: + - "{{ item.stat.isreg }}" + loop: "{{ check_file_exists.results }}" + loop_control: + label: "{{ item.stat.path }}" + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 17' + + tags: task17 + +- hosts: webservers + gather_facts: false + become: true + + tasks: + + - name: Task 17 - Services on webservers + block: + + - name: Gets the default target + command: systemctl get-default + changed_when: false + check_mode: true + register: check_default_target + failed_when: check_default_target.stdout != 'multi-user.target' + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 17' + + tags: task17 + + + +#-- Task 18 -------------------------------------------------------------------- + +- hosts: control + gather_facts: false + become: true + + tasks: + + - name: Task 18 - Create and Use Templates to Create Customized Configuration Files on control + block: + + - name: Run stat for files + stat: + path: "{{ item }}" + loop: + - '/home/automation/plays/playbooks/server_list.yml' + register: check_file_exists + + - name: Checking that all files were created + assert: + quiet: true + that: + - "{{ item.stat.isreg }}" + loop: "{{ check_file_exists.results }}" + loop_control: + label: "{{ item.stat.path }}" + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 18' + + tags: task18 + +- hosts: database + gather_facts: false + become: true + + tasks: + + - name: Task 18 - Create and Use Templates to Create Customized Configuration Files on database + block: + + - name: Template + template: + src: server_list.j2 + dest: /etc/server_list.txt + owner: automation + mode: 0600 + setype: net_conf_t + check_mode: true + register: check_server_list_file + failed_when: check_server_list_file.changed == true + + rescue: + - name: Print when errors + fail: + msg: 'Found errors for Task 18' + + tags: task18 diff --git a/roles/build-nodes/README.md b/roles/build-nodes/README.md new file mode 100644 index 0000000..225dd44 --- /dev/null +++ b/roles/build-nodes/README.md @@ -0,0 +1,38 @@ +Role Name +========= + +A brief description of the role goes here. + +Requirements +------------ + +Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. + +Role Variables +-------------- + +A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. + +Dependencies +------------ + +A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. + +Example Playbook +---------------- + +Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: + + - hosts: servers + roles: + - { role: username.rolename, x: 42 } + +License +------- + +BSD + +Author Information +------------------ + +An optional section for the role authors to include contact information, or a website (HTML is not allowed). diff --git a/roles/build-nodes/files/hosts b/roles/build-nodes/files/hosts new file mode 100644 index 0000000..f2b4bd6 --- /dev/null +++ b/roles/build-nodes/files/hosts @@ -0,0 +1,8 @@ +127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 +:1 localhost localhost.localdomain localhost6localhost6.localdomain6 +192.168.55.199 repo.ansi.example.com repo +192.168.55.200 control.ansi.example.com control +192.168.55.201 node1.ansi.example.com node1 +192.168.55.202 node2.ansi.example.com node2 +192.168.55.203 node3.ansi.example.com node3 +192.168.55.204 node4.ansi.example.com node4 diff --git a/roles/build-nodes/files/hosts.bak b/roles/build-nodes/files/hosts.bak new file mode 100644 index 0000000..f2b4bd6 --- /dev/null +++ b/roles/build-nodes/files/hosts.bak @@ -0,0 +1,8 @@ +127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 +:1 localhost localhost.localdomain localhost6localhost6.localdomain6 +192.168.55.199 repo.ansi.example.com repo +192.168.55.200 control.ansi.example.com control +192.168.55.201 node1.ansi.example.com node1 +192.168.55.202 node2.ansi.example.com node2 +192.168.55.203 node3.ansi.example.com node3 +192.168.55.204 node4.ansi.example.com node4 diff --git a/roles/build-nodes/files/ipa.repo b/roles/build-nodes/files/ipa.repo new file mode 100644 index 0000000..4184eb7 --- /dev/null +++ b/roles/build-nodes/files/ipa.repo @@ -0,0 +1,11 @@ +[base] +name=Base +baseurl=http://repo/BaseOS +gpgcheck=0 +enabled=1 + +[apps] +name=Apps +baseurl=http://repo/AppStream +gpgcheck=0 +enabled=1 diff --git a/roles/build-nodes/files/ipa.repo.bak b/roles/build-nodes/files/ipa.repo.bak new file mode 100644 index 0000000..4184eb7 --- /dev/null +++ b/roles/build-nodes/files/ipa.repo.bak @@ -0,0 +1,11 @@ +[base] +name=Base +baseurl=http://repo/BaseOS +gpgcheck=0 +enabled=1 + +[apps] +name=Apps +baseurl=http://repo/AppStream +gpgcheck=0 +enabled=1 diff --git a/playbooks/rhel-system-roles-1.0.1-1.el8.noarch.rpm b/roles/build-nodes/files/rhel-system-roles-1.0.1-1.el8.noarch.rpm similarity index 100% rename from playbooks/rhel-system-roles-1.0.1-1.el8.noarch.rpm rename to roles/build-nodes/files/rhel-system-roles-1.0.1-1.el8.noarch.rpm diff --git a/roles/build-nodes/files/welcome-control.sh b/roles/build-nodes/files/welcome-control.sh new file mode 100644 index 0000000..fbb4542 --- /dev/null +++ b/roles/build-nodes/files/welcome-control.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# +echo -e ' +# _ _ _ _ _ _ _ +# /\ \ /\ \ /\ \ _ /\ \ /\ \ /\ \ _\ \ +# / \ \ / \ \ / \ \ /\_\_\ \ / \ \ / \ \ /\__ \ +# / /\ \ \ / /\ \ \ / /\ \ \_/ / /\__ \ / /\ \ \ / /\ \ \ / /_ \_\ +# / / /\ \ \ / / /\ \ \ / / /\ \___/ / /_ \ \ / / /\ \_\ / / /\ \ \ / / /\/_/ +# / / / \ \_\ / / / \ \_\/ / / \/____/ / /\ \ \/ / /_/ / // / / \ \_\/ / / +# / / / \/_/ / / / / / / / / / / / / / \/_/ / /__\/ // / / / / / / / +# / / / / / / / / / / / / / / / / / / /_____// / / / / / / / ____ +# / / /________ / / /___/ / / / / / / / / / / / /\ \ \ / / /___/ / / /_/_/ ___/\ +# / / /_________/ / /____\/ / / / / / /_/ / / / / \ \ / / /____\/ /_______/\__\/ +# \/____________\/_________/\/_/ \/_/\_\/ \/_/ \_\\/_________/\_______\/ +'"# +# +# You are logged into \"`hostname`\" as the \"`whoami`\" account. +# This system is running `cat /etc/redhat-release` +# +# Repo/AppStream +# Available to use from http://repo.ansi.example.com/BaseOS and http://repo.ansi.example.com/AppStream +" \ No newline at end of file diff --git a/roles/build-nodes/files/welcome-node1.sh b/roles/build-nodes/files/welcome-node1.sh new file mode 100644 index 0000000..78cde85 --- /dev/null +++ b/roles/build-nodes/files/welcome-node1.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +echo -e ' +# _ _ _ _ _ +# /\ \ _ /\ \ /\ \ /\ \ / /\ +# / \ \ /\_\/ \ \ / \ \____ / \ \ / / \ +# / /\ \ \_/ / / /\ \ \ / /\ \_____\/ /\ \ \/_/ /\ \ +# / / /\ \___/ / / /\ \ \ / / /\/___ / / /\ \_\_\/\ \ \ +# / / / \/____/ / / \ \_\/ / / / / / /_/_ \/_/ \ \ \ +# / / / / / / / / / / / / / / / / /____/\ \ \ \ +# / / / / / / / / / / / / / / / / /\____\/ \ \ \ +# / / / / / / / /___/ / /\ \ \__/ / / / /______ __\ \ \___ +# / / / / / / / /____\/ / \ \___\/ / / /_______\ /___\_\/__/\ +# \/_/ \/_/\/_________/ \/_____/\/__________/ \_________\/ +'"# +# +# You are logged into \"`hostname`\" as the \"`whoami`\" account. +# This system is running `cat /etc/redhat-release` +# +" \ No newline at end of file diff --git a/roles/build-nodes/files/welcome-node2.sh b/roles/build-nodes/files/welcome-node2.sh new file mode 100644 index 0000000..2749744 --- /dev/null +++ b/roles/build-nodes/files/welcome-node2.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# +echo -e ' +# _ _ _ _ _ +# /\ \ _ /\ \ /\ \ /\ \ /\ \ +# / \ \ /\_\/ \ \ / \ \____ / \ \ / \ \ +# / /\ \ \_/ / / /\ \ \ / /\ \_____\/ /\ \ \/ /\ \ \ +# / / /\ \___/ / / /\ \ \ / / /\/___ / / /\ \_\/_/\ \ \ +# / / / \/____/ / / \ \_\/ / / / / / /_/_ \/_/ / / / +# / / / / / / / / / / / / / / / / /____/\ / / / +# / / / / / / / / / / / / / / / / /\____\/ / / / _ +# / / / / / / / /___/ / /\ \ \__/ / / / /______ / / /_/\_\ +# / / / / / / / /____\/ / \ \___\/ / / /_______\ / /_____/ / +# \/_/ \/_/\/_________/ \/_____/\/__________/ \________/ +'"# +# +# You are logged into \"`hostname`\" as the \"`whoami`\" account. +# This system is running `cat /etc/redhat-release` +# +" \ No newline at end of file diff --git a/roles/build-nodes/files/welcome-node3.sh b/roles/build-nodes/files/welcome-node3.sh new file mode 100644 index 0000000..c2f8b2c --- /dev/null +++ b/roles/build-nodes/files/welcome-node3.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# +echo -e ' +# _ _ _ _ _ +# /\ \ _ /\ \ /\ \ /\ \ /\ \ +# / \ \ /\_\/ \ \ / \ \____ / \ \ / \ \ +# / /\ \ \_/ / / /\ \ \ / /\ \_____\/ /\ \ \ / /\ \ \ +# / / /\ \___/ / / /\ \ \ / / /\/___ / / /\ \_/ / /\ \ \ +# / / / \/____/ / / \ \_\/ / / / / / /_/_ \/_\/_//_\ \ \ +# / / / / / / / / / / / / / / / / /____/\ __\___ \ \ +# / / / / / / / / / / / / / / / / /\____\/ / /\ \ \ \ +# / / / / / / / /___/ / /\ \ \__/ / / / /______ / /_/____\ \ \ +# / / / / / / / /____\/ / \ \___\/ / / /_______\/__________\ \ \ +# \/_/ \/_/\/_________/ \/_____/\/__________/\_____________\/ +'"# +# +# You are logged into \"`hostname`\" as the \"`whoami`\" account. +# This system is running `cat /etc/redhat-release` +# +" \ No newline at end of file diff --git a/roles/build-nodes/files/welcome-node4.sh b/roles/build-nodes/files/welcome-node4.sh new file mode 100644 index 0000000..1ba8b11 --- /dev/null +++ b/roles/build-nodes/files/welcome-node4.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# +echo -e ' +# _ _ _ _ _ +# /\ \ _ /\ \ /\ \ /\ \ _ /\ \ +# / \ \ /\_\/ \ \ / \ \____ / \ \ /\_\\ \ \ +# / /\ \ \_/ / / /\ \ \ / /\ \_____\/ /\ \ \ / / / \ \ \ +# / / /\ \___/ / / /\ \ \ / / /\/___ / / /\ \_/ / / \ \ \ +# / / / \/____/ / / \ \_\/ / / / / / /_/_ \/_\ \ \____\ \ \ +# / / / / / / / / / / / / / / / / /____/\ \ \________\ \ +# / / / / / / / / / / / / / / / / /\____\/ \/________/\ \ +# / / / / / / / /___/ / /\ \ \__/ / / / /______ \ \ \ +# / / / / / / / /____\/ / \ \___\/ / / /_______\ \ \_\ +# \/_/ \/_/\/_________/ \/_____/\/__________/ \/_/ +# +'"# +# +# You are logged into \"`hostname`\" as the \"`whoami`\" account. +# This system is running `cat /etc/redhat-release` +# +" \ No newline at end of file diff --git a/roles/build-nodes/files/welcome-repo.sh b/roles/build-nodes/files/welcome-repo.sh new file mode 100644 index 0000000..d993b3f --- /dev/null +++ b/roles/build-nodes/files/welcome-repo.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# +echo -e ' +# _ _ _ _ +# /\ \ /\ \ /\ \ /\ \ +# / \ \ / \ \ / \ \ / \ \ +# / /\ \ \ / /\ \ \ / /\ \ \ / /\ \ \ +# / / /\ \_\ / / /\ \_\ / / /\ \_\/ / /\ \ \ +# / / /_/ / // /_/_ \/_/ / / /_/ / / / / \ \_\ +# / / /__\/ // /____/\ / / /__\/ / / / / / / +# / / /_____// /\____\/ / / /_____/ / / / / / +# / / /\ \ \ / / /______ / / / / / /___/ / / +# / / / \ \ / / /_______/ / / / / /____\/ / +# \/_/ \_\\/__________\/_/ \/_________/ +'"# +# Why are you here? You should be working on the system hosts... +# Anyway, try not to reboot me or bad stuff can happen. +# +# You are logged into \"`hostname`\" as the \"`whoami`\" account. +# This system is running `cat /etc/redhat-release` +# +" \ No newline at end of file diff --git a/roles/build-nodes/tasks/archived/control.yml b/roles/build-nodes/tasks/archived/control.yml new file mode 100644 index 0000000..38a63e8 --- /dev/null +++ b/roles/build-nodes/tasks/archived/control.yml @@ -0,0 +1,114 @@ +--- + +- name: Setting Hostname + ansible.builtin.hostname: + name: "{{ hostname_fqdn }}" + +- name: Creating User Account + ansible.builtin.user: + name: user + shell: /bin/bash + groups: wheel + append: true + password: "{{ user_password | password_hash('sha512') }}" + +- name: Changing Root Password + ansible.builtin.user: + name: root + password: "{{ root_password | password_hash('sha512') }}"in + +- name: Adjusting SELinux + ansible.posix.selinux: + state: permissive + policy: targeted + +- name: Building Host File + ansible.builtin.copy: + src: "{{ role_path }}/files/hosts" + dest: /etc/hosts + mode: "0644" + owner: root + group: root + force: true + +- name: Fixing Resolv File + ansible.builtin.lineinfile: + path: /etc/resolv.conf + line: nameserver 8.8.8.8 + state: present + +- name: Erasing Repos + ansible.builtin.file: + path: /etc/yum.repos.d/* + state: absent + +- name: Building Repo File + ansible.builtin.copy: + src: "{{ role_path }}/files/ipa.repo" + dest: /etc/yum.repos.d/ipa.repo + mode: "0644" + owner: root + group: root + force: true + +- name: Adding the rhel-system-repos.rpm + ansible.builtin.copy: + src: rhel-system-roles-1.0.1-1.el8.noarch.rpm + dest: /home/vagrant + owner: vagrant + group: vagrant + mode: "0775" + +- name: Configuring network + ansible.builtin.command: nmcli con mod 'System eth1' ipv4.addresses 192.168.55.200/24 ipv4.gateway 192.168.55.1 ipv4.dns 8.8.8.8 ipv4.dns-search ansi.example.com + ipv4.method manual + +- name: Restarting Network + ansible.builtin.service: + name: NetworkManager + state: restarted + +- name: Starting services + ansible.builtin.service: + name: "{{ item }}" + state: started + enabled: true + with_items: + - firewalld + - httpd # control only + +# Control only +- name: Enabling Firewall Services + ansible.posix.firewalld: + service: "{{ item }}" + immediate: true + permanent: true + state: enabled + with_items: + - http + - https + - ntp + - dns + - ftp + when: "'control' in group_names" + +- name: Reloading Firewall + ansible.builtin.service: + name: firewalld + state: restarted + when: "'control' in group_names or 'repo' in group_names" + + +- name: Erasing Repos + ansible.builtin.file: + path: /etc/yum.repos.d/* + state: absent + +- name: Copy Welcome Message + ansible.builtin.copy: + src: "{{ role_path }}/files/welcome-{{ hostname_host }}.sh" + dest: /etc/profile.d/welcome.sh + mode: "0755" + owner: root + group: root + force: true diff --git a/roles/build-nodes/tasks/archived/repo.yml b/roles/build-nodes/tasks/archived/repo.yml new file mode 100644 index 0000000..0f70db4 --- /dev/null +++ b/roles/build-nodes/tasks/archived/repo.yml @@ -0,0 +1,117 @@ +--- +- name: Setting Up Repo Node + hosts: repo + become: true + gather_facts: false + ignore_errors: true + + vars: + - password: password + + tasks: + + - name: Setting Hostname + ansible.builtin.hostname: + name: repo.ansi.example.com + + - name: Creating User Account + ansible.builtin.user: + name: user + shell: /bin/bash + groups: wheel + append: true + password: "{{ password | password_hash('sha512') }}" + + - name: Changing Root Password + ansible.builtin.user: + name: root + password: "{{ password | password_hash('sha512') }}" + + - name: Disabling services + ansible.posix.selinux: + state: disabled + + - name: Building Host File + ansible.builtin.copy: + dest: /etc/hosts + src: "{{ playbook_dir }}/files/hosts" + mode: "0644" + owner: root + group: root + force: true + + - name: Enabling services + ansible.builtin.service: + name: "{{ item }}" + state: started + enabled: true + with_items: + - httpd + - firewalld + + - name: Starting Firewalld + ansible.posix.firewalld: + service: "{{ item }}" + immediate: true + permanent: true + state: enabled + with_items: + - http + - https + - ntp + - dns + - kerberos + - ldap + - ldaps + - ftp + + - name: Reloading Firewall + ansible.builtin.service: + name: firewalld + state: restarted + + - name: Enabling IPV6 + ansible.posix.sysctl: + name: "{{ item }}" + value: '0' + state: present + reload: true + with_items: + - net.ipv6.conf.lo.disable_ipv6 + - net.ipv6.conf.all.disable_ipv6 + + - name: Creating Welcome Message + ansible.builtin.file: + path: /etc/profile.d/welcome.sh + state: touch + mode: "0755" + + - name: Fixing SELinux Contexts + ansible.builtin.command: restorecon -Rv /var/www/html + + - name: Building Welcome Message + ansible.builtin.blockinfile: + dest: /etc/profile.d/welcome.sh + block: | + #!/bin/bash + # + echo -e ' + # _ _ _ _ + # /\ \ /\ \ /\ \ /\ \ + # / \ \ / \ \ / \ \ / \ \ + # / /\ \ \ / /\ \ \ / /\ \ \ / /\ \ \ + # / / /\ \_\ / / /\ \_\ / / /\ \_\/ / /\ \ \ + # / / /_/ / // /_/_ \/_/ / / /_/ / / / / \ \_\ + # / / /__\/ // /____/\ / / /__\/ / / / / / / + # / / /_____// /\____\/ / / /_____/ / / / / / + # / / /\ \ \ / / /______ / / / / / /___/ / / + # / / / \ \ / / /_______/ / / / / /____\/ / + # \/_/ \_\\/__________\/_/ \/_________/ + '"# + # Why are you here? You should be working on the system hosts... + # Anyway, try not to reboot me or bad stuff can happen. + # + # You are logged into \"`hostname`\" as the \"`whoami`\" account. + # This system is running `cat /etc/redhat-release` + # + " diff --git a/roles/build-nodes/tasks/build-nodes.yml b/roles/build-nodes/tasks/build-nodes.yml new file mode 100644 index 0000000..feadb91 --- /dev/null +++ b/roles/build-nodes/tasks/build-nodes.yml @@ -0,0 +1,189 @@ +--- +# tasks file for build-nodes + +##-- Configure networking ------------------------------------------------------ + +- name: Setting Hostname + ansible.builtin.hostname: + name: "{{ hostname_fqdn }}" + +- name: Building Host File + ansible.builtin.copy: + src: "{{ role_path }}/files/hosts" + dest: /etc/hosts + mode: "0644" + owner: root + group: root + remote_src: true + force: true + +- name: Fixing Resolv File + ansible.builtin.lineinfile: + path: /etc/resolv.conf + line: nameserver 8.8.8.8 + state: present + +- name: Configuring network + command: nmcli con mod 'System eth1' ipv4.addresses "{{ ansible_host }}"/24 ipv4.gateway 192.168.55.1 ipv4.method manual + +# - name: Configuring network +# nmcli: +# type: ethernet +# conn_name: 'System eth1' +# ifname: eth1 +# ip4: "{{ ansible_host }}/24" +# gw4: 192.168.55.1 +# state: present + +# Non control +- name: Enabling IPV6 + # ansible.posix.sysctl: + sysctl: + name: "{{ item }}" + value: "0" + reload: true + sysctl_set: true + with_items: + - net.ipv6.conf.lo.disable_ipv6 + - net.ipv6.conf.all.disable_ipv6 + when: "'control' not in group_names" + +- name: Restarting Network + ansible.builtin.service: + name: NetworkManager + state: restarted + +##-- Configure users ----------------------------------------------------------- + +- name: Creating User Account + ansible.builtin.user: + name: user + shell: /bin/bash + groups: wheel + append: true + generate_ssh_key: true + password: "{{ user_password | password_hash('sha512') }}" + +- name: Changing Root Password + ansible.builtin.user: + name: root + password: "{{ root_password | password_hash('sha512') }}" + +##-- Configure SELinux ---------------------------------------------------------- + +- name: Adjusting SELinux + # ansible.posix.selinux: + selinux: + state: permissive + policy: targeted + when: "'repo' not in group_names" + +- name: Disabling SELinux + # ansible.posix.selinux: + selinux: + state: disabled + when: "'repo' in group_names" + +- name: Fixing SELinux Contexts + # ansible.builtin.command: restorecon -Rv /var/www/html + command: restorecon -Rv /var/www/html + when: "'repo' in group_names" + +##-- Configure repo and packages ----------------------------------------------- + +- name: Erasing Repos + ansible.builtin.file: + path: /etc/yum.repos.d/* + state: absent + +- name: Building Repo File + ansible.builtin.copy: + src: "{{ role_path }}/files/ipa.repo" + dest: /etc/yum.repos.d/ipa.repo + mode: "0644" + owner: root + group: root + remote_src: true + force: true + +# Non control +- name: Environment Packages Installed. + ansible.builtin.dnf: + name: man-pages + state: present + register: yum_sleeper # What is this for + +- name: Adding the rhel-system-repos.rpm + copy: + src: rhel-system-roles-1.0.1-1.el8.noarch.rpm + dest: /home/vagrant/rhel-system-roles-1.0.1-1.el8.noarch.rpm + owner: vagrant + group: vagrant + mode: "0775" + +##-- Configure services -------------------------------------------------------- + +- name: Starting and enabling firewalld services + ansible.builtin.service: + name: firewalld + enabled: true + state: restarted + +- name: Starting httpd services + ansible.builtin.service: + name: "{{ item }}" + state: started + enabled: true + with_items: + - httpd + when: "'control' in group_names or 'repo' in group_names" + +- name: Enabling generic Firewalld Services + # ansible.posix.firewalld: + firewalld: + service: "{{ item }}" + immediate: true + permanent: true + state: enabled + with_items: + - http + - https + - ntp + - dns + - ftp + when: "'control' in group_names or 'repo' in group_names" + +- name: Starting auth Firewalld Services + # ansible.posix.firewalld: + firewalld: + service: "{{ item }}" + immediate: true + permanent: true + state: enabled + with_items: + - kerberos + - ldap + - ldaps + when: "'repo' in group_names" + +- name: Reloading Firewall + ansible.builtin.service: + name: firewalld + state: restarted + +##-- Wrap up ------------------------------------------------------------------- + +- name: Erasing Repos + ansible.builtin.file: + path: /etc/yum.repos.d/* + state: absent + +- name: Copy Welcome Message + ansible.builtin.copy: + src: "{{ role_path }}/files/welcome-{{ hostname_host }}.sh" + dest: /etc/profile.d/welcome.sh + mode: "0755" + owner: root + group: root + remote_src: true + force: true diff --git a/roles/build-nodes/tasks/keys.yml b/roles/build-nodes/tasks/keys.yml new file mode 100644 index 0000000..242877b --- /dev/null +++ b/roles/build-nodes/tasks/keys.yml @@ -0,0 +1,53 @@ +--- +# tasks file for build-nodes + +- name: Sending Key to node1 + expect: + command: ssh-copy-id -i /home/user/.ssh/id_rsa.pub user@node1.ansi.example.com + responses: + 'Are you sure you want to continue connecting': 'yes' + 'password': 'password' + timeout: 10 + become_user: user + +- name: Sending Key to node2 + expect: + command: ssh-copy-id -i /home/user/.ssh/id_rsa.pub user@node2.ansi.example.com + responses: + 'Are you sure you want to continue connecting': 'yes' + 'password': 'password' + timeout: 10 + become_user: user + +- name: Sending Key to node3 + expect: + command: ssh-copy-id -i /home/user/.ssh/id_rsa.pub user@node3.ansi.example.com + responses: + 'Are you sure you want to continue connecting': 'yes' + 'password': 'password' + timeout: 10 + become_user: user + +- name: Sending Key to node4 + expect: + command: ssh-copy-id -i /home/user/.ssh/id_rsa.pub user@node4.ansi.example.com + responses: + 'Are you sure you want to continue connecting': 'yes' + 'password': 'password' + timeout: 10 + become_user: user + +- name: Welcome to the RHCE 8 Study/Test Environment! + debug: + msg: + - 'Next Steps: Accessing The Systems:' + - '- Control - 192.168.55.200' + - '- Node 1 - 192.168.55.201' + - '- Node 2 - 192.168.55.202' + - '- Node 3 - 192.168.55.203' + - '- Node 4 - 192.168.55.204' + - '- Username/Password - user/password' + - '--------------------------------------------------' + - '- For root - use `sudo` or `sudo su`' + - '- Access example - ssh user@192.168.55.200' + - '- Happy Studying!' diff --git a/roles/build-nodes/tasks/main.yml b/roles/build-nodes/tasks/main.yml new file mode 100644 index 0000000..cb97426 --- /dev/null +++ b/roles/build-nodes/tasks/main.yml @@ -0,0 +1,11 @@ +--- +# tasks file for build-nodes + +# - ansible.builtin.include_tasks: +- include_tasks: + file: build-nodes.yml + +# - ansible.builtin.include_tasks: +- include_tasks: + file: keys.yml + when: "'control' in group_names" \ No newline at end of file diff --git a/roles/build-nodes/templates/hosts b/roles/build-nodes/templates/hosts new file mode 100644 index 0000000..f2b4bd6 --- /dev/null +++ b/roles/build-nodes/templates/hosts @@ -0,0 +1,8 @@ +127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 +:1 localhost localhost.localdomain localhost6localhost6.localdomain6 +192.168.55.199 repo.ansi.example.com repo +192.168.55.200 control.ansi.example.com control +192.168.55.201 node1.ansi.example.com node1 +192.168.55.202 node2.ansi.example.com node2 +192.168.55.203 node3.ansi.example.com node3 +192.168.55.204 node4.ansi.example.com node4 diff --git a/roles/build-nodes/templates/ipa.repo.bak b/roles/build-nodes/templates/ipa.repo.bak new file mode 100644 index 0000000..4184eb7 --- /dev/null +++ b/roles/build-nodes/templates/ipa.repo.bak @@ -0,0 +1,11 @@ +[base] +name=Base +baseurl=http://repo/BaseOS +gpgcheck=0 +enabled=1 + +[apps] +name=Apps +baseurl=http://repo/AppStream +gpgcheck=0 +enabled=1